aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt82
-rw-r--r--Documentation/sound/alsa/HD-Audio.txt8
-rw-r--r--arch/arm/mach-davinci/devices.c13
-rw-r--r--arch/arm/mach-ep93xx/core.c40
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h1
-rw-r--r--arch/arm/mach-ep93xx/include/mach/platform.h1
-rw-r--r--arch/arm/mach-ep93xx/simone.c1
-rw-r--r--arch/arm/mach-kirkwood/common.c6
-rw-r--r--arch/arm/mach-omap1/devices.c26
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c17
-rw-r--r--arch/arm/mach-omap2/board-zoom-peripherals.c12
-rw-r--r--arch/arm/mach-omap2/board-zoom2.c36
-rw-r--r--arch/arm/mach-omap2/devices.c39
-rw-r--r--arch/arm/mach-omap2/include/mach/board-zoom.h2
-rw-r--r--arch/arm/mach-pxa/devices.c25
-rw-r--r--arch/arm/mach-pxa/devices.h6
-rw-r--r--arch/arm/mach-pxa/pxa27x.c4
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c5
-rw-r--r--arch/arm/mach-pxa/zylonite.c11
-rw-r--r--arch/arm/mach-s3c64xx/dev-audio.c20
-rw-r--r--arch/arm/mach-s3c64xx/mach-smdk6410.c1
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h7
-rw-r--r--arch/arm/plat-s3c24xx/devs.c34
-rw-r--r--arch/arm/plat-samsung/include/plat/devs.h2
-rw-r--r--arch/mips/alchemy/devboards/db1200/platform.c6
-rw-r--r--arch/powerpc/boot/dts/mpc8610_hpcd.dts1
-rw-r--r--arch/powerpc/configs/mpc85xx_defconfig3
-rw-r--r--arch/powerpc/configs/mpc85xx_smp_defconfig3
-rw-r--r--arch/powerpc/include/asm/fsl_guts.h (renamed from arch/powerpc/include/asm/immap_86xx.h)111
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c211
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c2
-rw-r--r--drivers/input/misc/twl4030-vibra.c4
-rw-r--r--drivers/mfd/twl-core.c6
-rw-r--r--drivers/mfd/twl4030-codec.c8
-rw-r--r--drivers/staging/xgifb/TODO2
-rw-r--r--drivers/video/Kconfig3
-rw-r--r--drivers/video/sh_mobile_hdmi.c84
-rw-r--r--include/linux/i2c/twl.h6
-rw-r--r--include/sound/core.h2
-rw-r--r--include/sound/emu10k1.h2
-rw-r--r--include/sound/jack.h5
-rw-r--r--include/sound/max98088.h50
-rw-r--r--include/sound/pcm.h1
-rw-r--r--include/sound/sh_fsi.h3
-rw-r--r--include/sound/soc-dai.h98
-rw-r--r--include/sound/soc-dapm.h18
-rw-r--r--include/sound/soc-of-simple.h25
-rw-r--r--include/sound/soc.h245
-rw-r--r--include/sound/tlv.h4
-rw-r--r--include/sound/tlv320aic3x.h43
-rw-r--r--include/sound/wm8962.h32
-rw-r--r--include/video/sh_mobile_hdmi.h16
-rw-r--r--sound/core/init.c9
-rw-r--r--sound/core/oss/mixer_oss.c34
-rw-r--r--sound/core/pcm.c3
-rw-r--r--sound/core/pcm_lib.c14
-rw-r--r--sound/core/pcm_native.c4
-rw-r--r--sound/drivers/Kconfig19
-rw-r--r--sound/drivers/Makefile2
-rw-r--r--sound/drivers/aloop.c1258
-rw-r--r--sound/drivers/virmidi.c2
-rw-r--r--sound/i2c/other/ak4xxx-adda.c2
-rw-r--r--sound/isa/Kconfig36
-rw-r--r--sound/isa/Makefile4
-rw-r--r--sound/isa/ad1816a/ad1816a.c2
-rw-r--r--sound/isa/azt2320.c2
-rw-r--r--sound/isa/galaxy/Makefile10
-rw-r--r--sound/isa/galaxy/azt1605.c91
-rw-r--r--sound/isa/galaxy/azt2316.c111
-rw-r--r--sound/isa/galaxy/galaxy.c652
-rw-r--r--sound/isa/gus/gusmax.c4
-rw-r--r--sound/isa/sb/sb8.c2
-rw-r--r--sound/isa/sgalaxy.c369
-rw-r--r--sound/oss/Kconfig8
-rw-r--r--sound/oss/Makefile1
-rw-r--r--sound/oss/au1550_ac97.c48
-rw-r--r--sound/oss/dmasound/dmasound_core.c41
-rw-r--r--sound/oss/msnd_pinnacle.c15
-rw-r--r--sound/oss/sh_dac_audio.c325
-rw-r--r--sound/oss/soundcard.c43
-rw-r--r--sound/oss/swarm_cs4297a.c20
-rw-r--r--sound/oss/vwsnd.c30
-rw-r--r--sound/pci/Kconfig17
-rw-r--r--sound/pci/au88x0/au88x0_mixer.c2
-rw-r--r--sound/pci/ca0106/ca0106.h5
-rw-r--r--sound/pci/ca0106/ca0106_main.c136
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c93
-rw-r--r--sound/pci/emu10k1/emumpu401.c2
-rw-r--r--sound/pci/hda/Kconfig39
-rw-r--r--sound/pci/hda/Makefile15
-rw-r--r--sound/pci/hda/hda_codec.c271
-rw-r--r--sound/pci/hda/hda_codec.h13
-rw-r--r--sound/pci/hda/hda_eld.c7
-rw-r--r--sound/pci/hda/hda_generic.c41
-rw-r--r--sound/pci/hda/hda_intel.c101
-rw-r--r--sound/pci/hda/hda_local.h51
-rw-r--r--sound/pci/hda/patch_analog.c48
-rw-r--r--sound/pci/hda/patch_atihdmi.c224
-rw-r--r--sound/pci/hda/patch_ca0110.c10
-rw-r--r--sound/pci/hda/patch_cirrus.c94
-rw-r--r--sound/pci/hda/patch_conexant.c651
-rw-r--r--sound/pci/hda/patch_hdmi.c797
-rw-r--r--sound/pci/hda/patch_intelhdmi.c220
-rw-r--r--sound/pci/hda/patch_nvhdmi.c608
-rw-r--r--sound/pci/hda/patch_realtek.c908
-rw-r--r--sound/pci/hda/patch_sigmatel.c379
-rw-r--r--sound/pci/hda/patch_via.c587
-rw-r--r--sound/pci/ice1712/delta.c10
-rw-r--r--sound/pci/ice1712/delta.h4
-rw-r--r--sound/pci/ice1712/pontis.c6
-rw-r--r--sound/pci/ice1712/prodigy192.c2
-rw-r--r--sound/pci/oxygen/oxygen.c4
-rw-r--r--sound/pci/oxygen/oxygen.h1
-rw-r--r--sound/pci/oxygen/oxygen_lib.c55
-rw-r--r--sound/pci/oxygen/oxygen_mixer.c5
-rw-r--r--sound/pci/oxygen/oxygen_pcm.c12
-rw-r--r--sound/pci/oxygen/oxygen_regs.h10
-rw-r--r--sound/pci/oxygen/virtuoso.c5
-rw-r--r--sound/pci/oxygen/xonar_cs43xx.c8
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c29
-rw-r--r--sound/pci/oxygen/xonar_wm87x6.c121
-rw-r--r--sound/pci/rme96.c8
-rw-r--r--sound/pci/rme9652/hdsp.c8
-rw-r--r--sound/ppc/tumbler.c2
-rw-r--r--sound/soc/atmel/atmel-pcm.c59
-rw-r--r--sound/soc/atmel/atmel-pcm.h3
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c148
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h3
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c65
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c59
-rw-r--r--sound/soc/atmel/snd-soc-afeb9260.c35
-rw-r--r--sound/soc/au1x/db1200.c39
-rw-r--r--sound/soc/au1x/dbdma2.c95
-rw-r--r--sound/soc/au1x/psc-ac97.c71
-rw-r--r--sound/soc/au1x/psc-i2s.c53
-rw-r--r--sound/soc/au1x/psc.h10
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c43
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.h3
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c41
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.h2
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c23
-rw-r--r--sound/soc/blackfin/bf5xx-ad193x.c23
-rw-r--r--sound/soc/blackfin/bf5xx-ad1980.c19
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c22
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c44
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.h3
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c45
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.h14
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c38
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c43
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.h3
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c15
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.h2
-rw-r--r--sound/soc/codecs/88pm860x-codec.c1486
-rw-r--r--sound/soc/codecs/88pm860x-codec.h97
-rw-r--r--sound/soc/codecs/Kconfig24
-rw-r--r--sound/soc/codecs/Makefile12
-rw-r--r--sound/soc/codecs/ac97.c125
-rw-r--r--sound/soc/codecs/ac97.h19
-rw-r--r--sound/soc/codecs/ad1836.c191
-rw-r--r--sound/soc/codecs/ad1836.h2
-rw-r--r--sound/soc/codecs/ad193x.c217
-rw-r--r--sound/soc/codecs/ad193x.h3
-rw-r--r--sound/soc/codecs/ad1980.c113
-rw-r--r--sound/soc/codecs/ad1980.h3
-rw-r--r--sound/soc/codecs/ad73311.c66
-rw-r--r--sound/soc/codecs/ad73311.h2
-rw-r--r--sound/soc/codecs/ads117x.c72
-rw-r--r--sound/soc/codecs/ads117x.h4
-rw-r--r--sound/soc/codecs/ak4104.c149
-rw-r--r--sound/soc/codecs/ak4104.h7
-rw-r--r--sound/soc/codecs/ak4535.c236
-rw-r--r--sound/soc/codecs/ak4535.h8
-rw-r--r--sound/soc/codecs/ak4642.c235
-rw-r--r--sound/soc/codecs/ak4642.h20
-rw-r--r--sound/soc/codecs/ak4671.c140
-rw-r--r--sound/soc/codecs/ak4671.h3
-rw-r--r--sound/soc/codecs/cq93vc.c132
-rw-r--r--sound/soc/codecs/cq93vc.h29
-rw-r--r--sound/soc/codecs/cs4270.c394
-rw-r--r--sound/soc/codecs/cs4270.h28
-rw-r--r--sound/soc/codecs/cs42l51.c295
-rw-r--r--sound/soc/codecs/cs42l51.h2
-rw-r--r--sound/soc/codecs/cx20442.c173
-rw-r--r--sound/soc/codecs/cx20442.h2
-rw-r--r--sound/soc/codecs/da7210.c163
-rw-r--r--sound/soc/codecs/da7210.h24
-rw-r--r--sound/soc/codecs/jz4740.c116
-rw-r--r--sound/soc/codecs/jz4740.h20
-rw-r--r--sound/soc/codecs/max98088.c2097
-rw-r--r--sound/soc/codecs/max98088.h193
-rw-r--r--sound/soc/codecs/pcm3008.c92
-rw-r--r--sound/soc/codecs/pcm3008.h3
-rw-r--r--sound/soc/codecs/spdif_transciever.c102
-rw-r--r--sound/soc/codecs/spdif_transciever.h18
-rw-r--r--sound/soc/codecs/ssm2602.c218
-rw-r--r--sound/soc/codecs/ssm2602.h3
-rw-r--r--sound/soc/codecs/stac9766.c118
-rw-r--r--sound/soc/codecs/stac9766.h4
-rw-r--r--sound/soc/codecs/tlv320aic23.c182
-rw-r--r--sound/soc/codecs/tlv320aic23.h3
-rw-r--r--sound/soc/codecs/tlv320aic26.c180
-rw-r--r--sound/soc/codecs/tlv320aic26.h3
-rw-r--r--sound/soc/codecs/tlv320aic3x.c1230
-rw-r--r--sound/soc/codecs/tlv320aic3x.h100
-rw-r--r--sound/soc/codecs/tlv320dac33.c276
-rw-r--r--sound/soc/codecs/tlv320dac33.h3
-rw-r--r--sound/soc/codecs/tpa6130a2.c28
-rw-r--r--sound/soc/codecs/twl4030.c228
-rw-r--r--sound/soc/codecs/twl4030.h55
-rw-r--r--sound/soc/codecs/twl6040.c170
-rw-r--r--sound/soc/codecs/twl6040.h3
-rw-r--r--sound/soc/codecs/uda134x.c154
-rw-r--r--sound/soc/codecs/uda134x.h3
-rw-r--r--sound/soc/codecs/uda1380.c331
-rw-r--r--sound/soc/codecs/uda1380.h3
-rw-r--r--sound/soc/codecs/wl1273.c528
-rw-r--r--sound/soc/codecs/wl1273.h101
-rw-r--r--sound/soc/codecs/wm2000.h3
-rw-r--r--sound/soc/codecs/wm8350.c231
-rw-r--r--sound/soc/codecs/wm8350.h3
-rw-r--r--sound/soc/codecs/wm8400.c181
-rw-r--r--sound/soc/codecs/wm8400.h3
-rw-r--r--sound/soc/codecs/wm8510.c288
-rw-r--r--sound/soc/codecs/wm8510.h3
-rw-r--r--sound/soc/codecs/wm8523.c177
-rw-r--r--sound/soc/codecs/wm8523.h3
-rw-r--r--sound/soc/codecs/wm8580.c321
-rw-r--r--sound/soc/codecs/wm8580.h17
-rw-r--r--sound/soc/codecs/wm8711.c203
-rw-r--r--sound/soc/codecs/wm8711.h3
-rw-r--r--sound/soc/codecs/wm8727.c106
-rw-r--r--sound/soc/codecs/wm8727.h21
-rw-r--r--sound/soc/codecs/wm8728.c289
-rw-r--r--sound/soc/codecs/wm8728.h9
-rw-r--r--sound/soc/codecs/wm8731.c245
-rw-r--r--sound/soc/codecs/wm8731.h7
-rw-r--r--sound/soc/codecs/wm8741.c378
-rw-r--r--sound/soc/codecs/wm8741.h3
-rw-r--r--sound/soc/codecs/wm8750.c264
-rw-r--r--sound/soc/codecs/wm8750.h9
-rw-r--r--sound/soc/codecs/wm8753.c404
-rw-r--r--sound/soc/codecs/wm8753.h3
-rw-r--r--sound/soc/codecs/wm8776.c248
-rw-r--r--sound/soc/codecs/wm8776.h3
-rw-r--r--sound/soc/codecs/wm8804.c833
-rw-r--r--sound/soc/codecs/wm8804.h61
-rw-r--r--sound/soc/codecs/wm8900.c246
-rw-r--r--sound/soc/codecs/wm8900.h3
-rw-r--r--sound/soc/codecs/wm8903.c265
-rw-r--r--sound/soc/codecs/wm8903.h3
-rw-r--r--sound/soc/codecs/wm8904.c208
-rw-r--r--sound/soc/codecs/wm8904.h3
-rw-r--r--sound/soc/codecs/wm8940.c199
-rw-r--r--sound/soc/codecs/wm8940.h2
-rw-r--r--sound/soc/codecs/wm8955.c181
-rw-r--r--sound/soc/codecs/wm8955.h3
-rw-r--r--sound/soc/codecs/wm8960.c209
-rw-r--r--sound/soc/codecs/wm8960.h3
-rw-r--r--sound/soc/codecs/wm8961.c237
-rw-r--r--sound/soc/codecs/wm8961.h3
-rw-r--r--sound/soc/codecs/wm8962.c3977
-rw-r--r--sound/soc/codecs/wm8962.h3780
-rw-r--r--sound/soc/codecs/wm8971.c247
-rw-r--r--sound/soc/codecs/wm8971.h8
-rw-r--r--sound/soc/codecs/wm8974.c167
-rw-r--r--sound/soc/codecs/wm8974.h3
-rw-r--r--sound/soc/codecs/wm8978.c190
-rw-r--r--sound/soc/codecs/wm8978.h3
-rw-r--r--sound/soc/codecs/wm8985.c1192
-rw-r--r--sound/soc/codecs/wm8985.h1045
-rw-r--r--sound/soc/codecs/wm8988.c261
-rw-r--r--sound/soc/codecs/wm8988.h3
-rw-r--r--sound/soc/codecs/wm8990.c223
-rw-r--r--sound/soc/codecs/wm8990.h8
-rw-r--r--sound/soc/codecs/wm8993.c304
-rw-r--r--sound/soc/codecs/wm8993.h3
-rw-r--r--sound/soc/codecs/wm8994.c3410
-rw-r--r--sound/soc/codecs/wm8994.h3
-rw-r--r--sound/soc/codecs/wm9081.c208
-rw-r--r--sound/soc/codecs/wm9081.h3
-rw-r--r--sound/soc/codecs/wm9090.c183
-rw-r--r--sound/soc/codecs/wm9090.h2
-rw-r--r--sound/soc/codecs/wm9705.c116
-rw-r--r--sound/soc/codecs/wm9705.h3
-rw-r--r--sound/soc/codecs/wm9712.c124
-rw-r--r--sound/soc/codecs/wm9712.h3
-rw-r--r--sound/soc/codecs/wm9713.c131
-rw-r--r--sound/soc/codecs/wm9713.h3
-rw-r--r--sound/soc/davinci/davinci-evm.c109
-rw-r--r--sound/soc/davinci/davinci-i2s.c50
-rw-r--r--sound/soc/davinci/davinci-i2s.h2
-rw-r--r--sound/soc/davinci/davinci-mcasp.c34
-rw-r--r--sound/soc/davinci/davinci-mcasp.h2
-rw-r--r--sound/soc/davinci/davinci-pcm.c45
-rw-r--r--sound/soc/davinci/davinci-pcm.h3
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c29
-rw-r--r--sound/soc/davinci/davinci-vcif.c25
-rw-r--r--sound/soc/davinci/davinci-vcif.h28
-rw-r--r--sound/soc/ep93xx/Kconfig16
-rw-r--r--sound/soc/ep93xx/Makefile4
-rw-r--r--sound/soc/ep93xx/ep93xx-ac97.c468
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c34
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.h18
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c37
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.h2
-rw-r--r--sound/soc/ep93xx/simone.c89
-rw-r--r--sound/soc/ep93xx/snappercl15.c24
-rw-r--r--sound/soc/fsl/Kconfig27
-rw-r--r--sound/soc/fsl/Makefile11
-rw-r--r--sound/soc/fsl/efika-audio-fabric.c20
-rw-r--r--sound/soc/fsl/fsl_dma.c458
-rw-r--r--sound/soc/fsl/fsl_dma.h20
-rw-r--r--sound/soc/fsl/fsl_ssi.c298
-rw-r--r--sound/soc/fsl/fsl_ssi.h26
-rw-r--r--sound/soc/fsl/mpc5200_dma.c66
-rw-r--r--sound/soc/fsl/mpc5200_dma.h5
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c34
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.h2
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c19
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c660
-rw-r--r--sound/soc/fsl/p1022_ds.c591
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c21
-rw-r--r--sound/soc/fsl/soc-of-simple.c172
-rw-r--r--sound/soc/imx/Kconfig16
-rw-r--r--sound/soc/imx/Makefile10
-rw-r--r--sound/soc/imx/eukrea-tlv320.c16
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c43
-rw-r--r--sound/soc/imx/imx-pcm-fiq.c68
-rw-r--r--sound/soc/imx/imx-ssi.c148
-rw-r--r--sound/soc/imx/imx-ssi.h7
-rw-r--r--sound/soc/imx/phycore-ac97.c19
-rw-r--r--sound/soc/imx/wm1133-ev1.c27
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c104
-rw-r--r--sound/soc/jz4740/jz4740-i2s.h2
-rw-r--r--sound/soc/jz4740/jz4740-pcm.c18
-rw-r--r--sound/soc/jz4740/jz4740-pcm.h2
-rw-r--r--sound/soc/jz4740/qi_lb60.c25
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c69
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.h17
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c55
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.h17
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c24
-rw-r--r--sound/soc/nuc900/nuc900-ac97.c13
-rw-r--r--sound/soc/nuc900/nuc900-audio.c16
-rw-r--r--sound/soc/nuc900/nuc900-audio.h4
-rw-r--r--sound/soc/nuc900/nuc900-pcm.c38
-rw-r--r--sound/soc/omap/am3517evm.c29
-rw-r--r--sound/soc/omap/ams-delta.c98
-rw-r--r--sound/soc/omap/igep0020.c26
-rw-r--r--sound/soc/omap/mcpdm.c19
-rw-r--r--sound/soc/omap/mcpdm.h2
-rw-r--r--sound/soc/omap/n810.c42
-rw-r--r--sound/soc/omap/omap-mcbsp.c125
-rw-r--r--sound/soc/omap/omap-mcbsp.h2
-rw-r--r--sound/soc/omap/omap-mcpdm.c71
-rw-r--r--sound/soc/omap/omap-mcpdm.h29
-rw-r--r--sound/soc/omap/omap-pcm.c47
-rw-r--r--sound/soc/omap/omap-pcm.h2
-rw-r--r--sound/soc/omap/omap2evm.c29
-rw-r--r--sound/soc/omap/omap3beagle.c27
-rw-r--r--sound/soc/omap/omap3evm.c34
-rw-r--r--sound/soc/omap/omap3pandora.c36
-rw-r--r--sound/soc/omap/osk5912.c24
-rw-r--r--sound/soc/omap/overo.c22
-rw-r--r--sound/soc/omap/rx51.c41
-rw-r--r--sound/soc/omap/sdp3430.c60
-rw-r--r--sound/soc/omap/sdp4430.c27
-rw-r--r--sound/soc/omap/zoom2.c68
-rw-r--r--sound/soc/pxa/Kconfig18
-rw-r--r--sound/soc/pxa/Makefile4
-rw-r--r--sound/soc/pxa/corgi.c28
-rw-r--r--sound/soc/pxa/e740_wm9705.c29
-rw-r--r--sound/soc/pxa/e750_wm9705.c26
-rw-r--r--sound/soc/pxa/e800_wm9712.c26
-rw-r--r--sound/soc/pxa/em-x270.c22
-rw-r--r--sound/soc/pxa/imote2.c20
-rw-r--r--sound/soc/pxa/magician.c35
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c33
-rw-r--r--sound/soc/pxa/palm27x.c27
-rw-r--r--sound/soc/pxa/poodle.c29
-rw-r--r--sound/soc/pxa/pxa-ssp.c174
-rw-r--r--sound/soc/pxa/pxa-ssp.h2
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c46
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.h2
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c91
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.h2
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c46
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.h19
-rw-r--r--sound/soc/pxa/raumfeld.c114
-rw-r--r--sound/soc/pxa/saarb.c200
-rw-r--r--sound/soc/pxa/spitz.c26
-rw-r--r--sound/soc/pxa/tavorevb3.c200
-rw-r--r--sound/soc/pxa/tosa.c27
-rw-r--r--sound/soc/pxa/z2.c26
-rw-r--r--sound/soc/pxa/zylonite.c40
-rw-r--r--sound/soc/s3c24xx/Kconfig37
-rw-r--r--sound/soc/s3c24xx/Makefile10
-rw-r--r--sound/soc/s3c24xx/aquila_wm8994.c295
-rw-r--r--sound/soc/s3c24xx/goni_wm8994.c298
-rw-r--r--sound/soc/s3c24xx/jive_wm8750.c23
-rw-r--r--sound/soc/s3c24xx/ln2440sbc_alc650.c17
-rw-r--r--sound/soc/s3c24xx/neo1973_gta02_wm8753.c58
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c37
-rw-r--r--sound/soc/s3c24xx/rx1950_uda1380.c333
-rw-r--r--sound/soc/s3c24xx/s3c-ac97.c36
-rw-r--r--sound/soc/s3c24xx/s3c-ac97.h2
-rw-r--r--sound/soc/s3c24xx/s3c-dma.c46
-rw-r--r--sound/soc/s3c24xx/s3c-dma.h1
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c50
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.h13
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.c54
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.h3
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c54
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.h2
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c40
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.h2
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec.c15
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec.h4
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_hermes.c25
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c21
-rw-r--r--sound/soc/s3c24xx/s3c24xx_uda134x.c21
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s-v4.c135
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c206
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h3
-rw-r--r--sound/soc/s3c24xx/smartq_wm8987.c15
-rw-r--r--sound/soc/s3c24xx/smdk2443_wm9710.c17
-rw-r--r--sound/soc/s3c24xx/smdk64xx_wm8580.c68
-rw-r--r--sound/soc/s3c24xx/smdk_spdif.c223
-rw-r--r--sound/soc/s3c24xx/smdk_wm9713.c42
-rw-r--r--sound/soc/s3c24xx/spdif.c501
-rw-r--r--sound/soc/s3c24xx/spdif.h19
-rw-r--r--sound/soc/s6000/s6000-i2s.c56
-rw-r--r--sound/soc/s6000/s6000-i2s.h2
-rw-r--r--sound/soc/s6000/s6000-pcm.c100
-rw-r--r--sound/soc/s6000/s6000-pcm.h2
-rw-r--r--sound/soc/s6000/s6105-ipcam.c31
-rw-r--r--sound/soc/sh/Kconfig11
-rw-r--r--sound/soc/sh/Makefile2
-rw-r--r--sound/soc/sh/dma-sh7760.c53
-rw-r--r--sound/soc/sh/fsi-ak4642.c31
-rw-r--r--sound/soc/sh/fsi-da7210.c24
-rw-r--r--sound/soc/sh/fsi-hdmi.c60
-rw-r--r--sound/soc/sh/fsi.c606
-rw-r--r--sound/soc/sh/hac.c46
-rw-r--r--sound/soc/sh/migor.c29
-rw-r--r--sound/soc/sh/sh7760-ac97.c25
-rw-r--r--sound/soc/sh/siu.h6
-rw-r--r--sound/soc/sh/siu_dai.c97
-rw-r--r--sound/soc/sh/siu_pcm.c32
-rw-r--r--sound/soc/sh/ssi.c55
-rw-r--r--sound/soc/soc-cache.c198
-rw-r--r--sound/soc/soc-core.c1821
-rw-r--r--sound/soc/soc-dapm.c88
-rw-r--r--sound/soc/soc-jack.c21
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c55
-rw-r--r--sound/soc/txx9/txx9aclc-generic.c24
-rw-r--r--sound/soc/txx9/txx9aclc.c141
-rw-r--r--sound/soc/txx9/txx9aclc.h13
-rw-r--r--sound/synth/emux/emux_hwdep.c3
-rw-r--r--sound/usb/Kconfig2
-rw-r--r--sound/usb/caiaq/audio.c175
-rw-r--r--sound/usb/caiaq/control.c208
-rw-r--r--sound/usb/caiaq/device.c10
-rw-r--r--sound/usb/caiaq/device.h6
-rw-r--r--sound/usb/caiaq/input.c248
-rw-r--r--sound/usb/card.c31
-rw-r--r--sound/usb/endpoint.c2
-rw-r--r--sound/usb/helper.c17
-rw-r--r--sound/usb/midi.c16
-rw-r--r--sound/usb/mixer.c9
-rw-r--r--sound/usb/mixer_quirks.c1
-rw-r--r--sound/usb/pcm.c4
-rw-r--r--sound/usb/proc.c2
-rw-r--r--sound/usb/quirks-table.h184
-rw-r--r--sound/usb/quirks.c2
-rw-r--r--sound/usb/urb.c2
-rw-r--r--sound/usb/usbaudio.h2
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c6
479 files changed, 37901 insertions, 19477 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 7f4dcebda9c6..d0eb696d32e8 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -300,6 +300,74 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
300 control correctly. If you have problems regarding this, try 300 control correctly. If you have problems regarding this, try
301 another ALSA compliant mixer (alsamixer works). 301 another ALSA compliant mixer (alsamixer works).
302 302
303 Module snd-azt1605
304 ------------------
305
306 Module for Aztech Sound Galaxy soundcards based on the Aztech AZT1605
307 chipset.
308
309 port - port # for BASE (0x220,0x240,0x260,0x280)
310 wss_port - port # for WSS (0x530,0x604,0xe80,0xf40)
311 irq - IRQ # for WSS (7,9,10,11)
312 dma1 - DMA # for WSS playback (0,1,3)
313 dma2 - DMA # for WSS capture (0,1), -1 = disabled (default)
314 mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
315 mpu_irq - IRQ # for MPU-401 UART (3,5,7,9), -1 = disabled (default)
316 fm_port - port # for OPL3 (0x388), -1 = disabled (default)
317
318 This module supports multiple cards. It does not support autoprobe: port,
319 wss_port, irq and dma1 have to be specified. The other values are
320 optional.
321
322 "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
323 or the value stored in the card's EEPROM for cards that have an EEPROM and
324 their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
325 be choosen freely from the options enumerated above.
326
327 If dma2 is specified and different from dma1, the card will operate in
328 full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
329 enable capture since only channels 0 and 1 are available for capture.
330
331 Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
332 mpu_port=0x330 mpu_irq=9 fm_port=0x388".
333
334 Whatever IRQ and DMA channels you pick, be sure to reserve them for
335 legacy ISA in your BIOS.
336
337 Module snd-azt2316
338 ------------------
339
340 Module for Aztech Sound Galaxy soundcards based on the Aztech AZT2316
341 chipset.
342
343 port - port # for BASE (0x220,0x240,0x260,0x280)
344 wss_port - port # for WSS (0x530,0x604,0xe80,0xf40)
345 irq - IRQ # for WSS (7,9,10,11)
346 dma1 - DMA # for WSS playback (0,1,3)
347 dma2 - DMA # for WSS capture (0,1), -1 = disabled (default)
348 mpu_port - port # for MPU-401 UART (0x300,0x330), -1 = disabled (default)
349 mpu_irq - IRQ # for MPU-401 UART (5,7,9,10), -1 = disabled (default)
350 fm_port - port # for OPL3 (0x388), -1 = disabled (default)
351
352 This module supports multiple cards. It does not support autoprobe: port,
353 wss_port, irq and dma1 have to be specified. The other values are
354 optional.
355
356 "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
357 or the value stored in the card's EEPROM for cards that have an EEPROM and
358 their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
359 be choosen freely from the options enumerated above.
360
361 If dma2 is specified and different from dma1, the card will operate in
362 full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
363 enable capture since only channels 0 and 1 are available for capture.
364
365 Generic settings are "port=0x220 wss_port=0x530 irq=10 dma1=1 dma2=0
366 mpu_port=0x330 mpu_irq=9 fm_port=0x388".
367
368 Whatever IRQ and DMA channels you pick, be sure to reserve them for
369 legacy ISA in your BIOS.
370
303 Module snd-aw2 371 Module snd-aw2
304 -------------- 372 --------------
305 373
@@ -1641,20 +1709,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1641 1709
1642 This card is also known as Audio Excel DSP 16 or Zoltrix AV302. 1710 This card is also known as Audio Excel DSP 16 or Zoltrix AV302.
1643 1711
1644 Module snd-sgalaxy
1645 ------------------
1646
1647 Module for Aztech Sound Galaxy sound card.
1648
1649 sbport - Port # for SB16 interface (0x220,0x240)
1650 wssport - Port # for WSS interface (0x530,0xe80,0xf40,0x604)
1651 irq - IRQ # (7,9,10,11)
1652 dma1 - DMA #
1653
1654 This module supports multiple cards.
1655
1656 The power-management is supported.
1657
1658 Module snd-sscape 1712 Module snd-sscape
1659 ----------------- 1713 -----------------
1660 1714
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
index 278cc2122ea0..c82beb007634 100644
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ b/Documentation/sound/alsa/HD-Audio.txt
@@ -57,9 +57,11 @@ dead. However, this detection isn't perfect on some devices. In such
57a case, you can change the default method via `position_fix` option. 57a case, you can change the default method via `position_fix` option.
58 58
59`position_fix=1` means to use LPIB method explicitly. 59`position_fix=1` means to use LPIB method explicitly.
60`position_fix=2` means to use the position-buffer. 0 is the default 60`position_fix=2` means to use the position-buffer.
61value, the automatic check and fallback to LPIB as described in the 61`position_fix=3` means to use a combination of both methods, needed
62above. If you get a problem of repeated sounds, this option might 62for some VIA and ATI controllers. 0 is the default value for all other
63controllers, the automatic check and fallback to LPIB as described in
64the above. If you get a problem of repeated sounds, this option might
63help. 65help.
64 66
65In addition to that, every controller is known to be broken regarding 67In addition to that, every controller is known to be broken regarding
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
index 8b7201e4c79c..de40e9c787e1 100644
--- a/arch/arm/mach-davinci/devices.c
+++ b/arch/arm/mach-davinci/devices.c
@@ -295,6 +295,18 @@ static void davinci_init_wdt(void)
295 295
296/*-------------------------------------------------------------------------*/ 296/*-------------------------------------------------------------------------*/
297 297
298struct platform_device davinci_pcm_device = {
299 .name = "davinci-pcm-audio",
300 .id = -1,
301};
302
303static void davinci_init_pcm(void)
304{
305 platform_device_register(&davinci_pcm_device);
306}
307
308/*-------------------------------------------------------------------------*/
309
298struct davinci_timer_instance davinci_timer_instance[2] = { 310struct davinci_timer_instance davinci_timer_instance[2] = {
299 { 311 {
300 .base = DAVINCI_TIMER0_BASE, 312 .base = DAVINCI_TIMER0_BASE,
@@ -315,6 +327,7 @@ static int __init davinci_init_devices(void)
315 /* please keep these calls, and their implementations above, 327 /* please keep these calls, and their implementations above,
316 * in alphabetical order so they're easier to sort through. 328 * in alphabetical order so they're easier to sort through.
317 */ 329 */
330 davinci_init_pcm();
318 davinci_init_wdt(); 331 davinci_init_wdt();
319 332
320 return 0; 333 return 0;
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 4cb55d3902ff..ffdf87be2958 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -776,9 +776,15 @@ static struct platform_device ep93xx_i2s_device = {
776 .resource = ep93xx_i2s_resource, 776 .resource = ep93xx_i2s_resource,
777}; 777};
778 778
779static struct platform_device ep93xx_pcm_device = {
780 .name = "ep93xx-pcm-audio",
781 .id = -1,
782};
783
779void __init ep93xx_register_i2s(void) 784void __init ep93xx_register_i2s(void)
780{ 785{
781 platform_device_register(&ep93xx_i2s_device); 786 platform_device_register(&ep93xx_i2s_device);
787 platform_device_register(&ep93xx_pcm_device);
782} 788}
783 789
784#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \ 790#define EP93XX_SYSCON_DEVCFG_I2S_MASK (EP93XX_SYSCON_DEVCFG_I2SONSSP | \
@@ -826,6 +832,40 @@ void ep93xx_i2s_release(void)
826} 832}
827EXPORT_SYMBOL(ep93xx_i2s_release); 833EXPORT_SYMBOL(ep93xx_i2s_release);
828 834
835/*************************************************************************
836 * EP93xx AC97 audio peripheral handling
837 *************************************************************************/
838static struct resource ep93xx_ac97_resources[] = {
839 {
840 .start = EP93XX_AAC_PHYS_BASE,
841 .end = EP93XX_AAC_PHYS_BASE + 0xb0 - 1,
842 .flags = IORESOURCE_MEM,
843 },
844 {
845 .start = IRQ_EP93XX_AACINTR,
846 .end = IRQ_EP93XX_AACINTR,
847 .flags = IORESOURCE_IRQ,
848 },
849};
850
851static struct platform_device ep93xx_ac97_device = {
852 .name = "ep93xx-ac97",
853 .id = -1,
854 .num_resources = ARRAY_SIZE(ep93xx_ac97_resources),
855 .resource = ep93xx_ac97_resources,
856};
857
858void __init ep93xx_register_ac97(void)
859{
860 /*
861 * Make sure that the AC97 pins are not used by I2S.
862 */
863 ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97);
864
865 platform_device_register(&ep93xx_ac97_device);
866 platform_device_register(&ep93xx_pcm_device);
867}
868
829extern void ep93xx_gpio_init(void); 869extern void ep93xx_gpio_init(void);
830 870
831void __init ep93xx_init_devices(void) 871void __init ep93xx_init_devices(void)
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index c54b3e56ba63..9ac4d1055097 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -105,6 +105,7 @@
105#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc) 105#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc)
106#define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8) 106#define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8)
107 107
108#define EP93XX_AAC_PHYS_BASE EP93XX_APB_PHYS(0x00080000)
108#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000) 109#define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000)
109 110
110#define EP93XX_SPI_PHYS_BASE EP93XX_APB_PHYS(0x000a0000) 111#define EP93XX_SPI_PHYS_BASE EP93XX_APB_PHYS(0x000a0000)
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 3330b36d79e6..50660455b1d8 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -61,6 +61,7 @@ void ep93xx_keypad_release_gpio(struct platform_device *pdev);
61void ep93xx_register_i2s(void); 61void ep93xx_register_i2s(void);
62int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config); 62int ep93xx_i2s_acquire(unsigned i2s_pins, unsigned i2s_config);
63void ep93xx_i2s_release(void); 63void ep93xx_i2s_release(void);
64void ep93xx_register_ac97(void);
64 65
65void ep93xx_init_devices(void); 66void ep93xx_init_devices(void);
66extern struct sys_timer ep93xx_timer; 67extern struct sys_timer ep93xx_timer;
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index f22ce8db7947..d96dc1c5da20 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -61,6 +61,7 @@ static void __init simone_init_machine(void)
61 ep93xx_register_fb(&simone_fb_info); 61 ep93xx_register_fb(&simone_fb_info);
62 ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, 62 ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info,
63 ARRAY_SIZE(simone_i2c_board_info)); 63 ARRAY_SIZE(simone_i2c_board_info));
64 ep93xx_register_ac97();
64} 65}
65 66
66MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board") 67MACHINE_START(SIM_ONE, "Simplemachines Sim.One Board")
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index 1c82d4290dad..51ff23b72d3a 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -903,10 +903,16 @@ static struct platform_device kirkwood_i2s_device = {
903 }, 903 },
904}; 904};
905 905
906static struct platform_device kirkwood_pcm_device = {
907 .name = "kirkwood-pcm-audio",
908 .id = -1,
909};
910
906void __init kirkwood_audio_init(void) 911void __init kirkwood_audio_init(void)
907{ 912{
908 kirkwood_clk_ctrl |= CGC_AUDIO; 913 kirkwood_clk_ctrl |= CGC_AUDIO;
909 platform_device_register(&kirkwood_i2s_device); 914 platform_device_register(&kirkwood_i2s_device);
915 platform_device_register(&kirkwood_pcm_device);
910} 916}
911 917
912/***************************************************************************** 918/*****************************************************************************
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c
index aa0725608fb1..b583121b04b9 100644
--- a/arch/arm/mach-omap1/devices.c
+++ b/arch/arm/mach-omap1/devices.c
@@ -25,6 +25,7 @@
25#include <mach/gpio.h> 25#include <mach/gpio.h>
26#include <plat/mmc.h> 26#include <plat/mmc.h>
27#include <plat/omap7xx.h> 27#include <plat/omap7xx.h>
28#include <plat/mcbsp.h>
28 29
29/*-------------------------------------------------------------------------*/ 30/*-------------------------------------------------------------------------*/
30 31
@@ -195,6 +196,30 @@ static inline void omap_init_spi100k(void)
195 196
196static inline void omap_init_sti(void) {} 197static inline void omap_init_sti(void) {}
197 198
199#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
200
201static struct platform_device omap_pcm = {
202 .name = "omap-pcm-audio",
203 .id = -1,
204};
205
206OMAP_MCBSP_PLATFORM_DEVICE(1);
207OMAP_MCBSP_PLATFORM_DEVICE(2);
208OMAP_MCBSP_PLATFORM_DEVICE(3);
209
210static void omap_init_audio(void)
211{
212 platform_device_register(&omap_mcbsp1);
213 platform_device_register(&omap_mcbsp2);
214 if (!cpu_is_omap7xx())
215 platform_device_register(&omap_mcbsp3);
216 platform_device_register(&omap_pcm);
217}
218
219#else
220static inline void omap_init_audio(void) {}
221#endif
222
198/*-------------------------------------------------------------------------*/ 223/*-------------------------------------------------------------------------*/
199 224
200/* 225/*
@@ -227,6 +252,7 @@ static int __init omap1_init_devices(void)
227 omap_init_rtc(); 252 omap_init_rtc();
228 omap_init_spi100k(); 253 omap_init_spi100k();
229 omap_init_sti(); 254 omap_init_sti();
255 omap_init_audio();
230 256
231 return 0; 257 return 0;
232} 258}
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index ce28a851dcd3..63d786bccb67 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -23,6 +23,7 @@
23#include <linux/gpio.h> 23#include <linux/gpio.h>
24#include <linux/gpio_keys.h> 24#include <linux/gpio_keys.h>
25#include <linux/mmc/host.h> 25#include <linux/mmc/host.h>
26#include <sound/tlv320aic3x.h>
26 27
27#include <plat/mcspi.h> 28#include <plat/mcspi.h>
28#include <plat/board.h> 29#include <plat/board.h>
@@ -689,7 +690,6 @@ static struct twl4030_power_data rx51_t2scripts_data __initdata = {
689}; 690};
690 691
691 692
692
693static struct twl4030_platform_data rx51_twldata __initdata = { 693static struct twl4030_platform_data rx51_twldata __initdata = {
694 .irq_base = TWL4030_IRQ_BASE, 694 .irq_base = TWL4030_IRQ_BASE,
695 .irq_end = TWL4030_IRQ_END, 695 .irq_end = TWL4030_IRQ_END,
@@ -710,10 +710,6 @@ static struct twl4030_platform_data rx51_twldata __initdata = {
710 .vio = &rx51_vio, 710 .vio = &rx51_vio,
711}; 711};
712 712
713static struct aic3x_pdata rx51_aic3x_data __initdata = {
714 .gpio_reset = 60,
715};
716
717static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata = { 713static struct tpa6130a2_platform_data rx51_tpa6130a2_data __initdata = {
718 .id = TPA6130A2, 714 .id = TPA6130A2,
719 .power_gpio = 98, 715 .power_gpio = 98,
@@ -728,6 +724,17 @@ static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_1[] = {
728 }, 724 },
729}; 725};
730 726
727/* Audio setup data */
728static struct aic3x_setup_data rx51_aic34_setup = {
729 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
730 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
731};
732
733static struct aic3x_pdata rx51_aic3x_data = {
734 .setup = &rx51_aic34_setup,
735 .gpio_reset = 60,
736};
737
731static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = { 738static struct i2c_board_info __initdata rx51_peripherals_i2c_board_info_2[] = {
732 { 739 {
733 I2C_BOARD_INFO("tlv320aic3x", 0x18), 740 I2C_BOARD_INFO("tlv320aic3x", 0x18),
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c
index 189a6d1600b2..bc8232845d7a 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -26,6 +26,8 @@
26#include <plat/common.h> 26#include <plat/common.h>
27#include <plat/usb.h> 27#include <plat/usb.h>
28 28
29#include <mach/board-zoom.h>
30
29#include "mux.h" 31#include "mux.h"
30#include "hsmmc.h" 32#include "hsmmc.h"
31 33
@@ -238,6 +240,11 @@ static int zoom_twl_gpio_setup(struct device *dev,
238 return 0; 240 return 0;
239} 241}
240 242
243/* EXTMUTE callback function */
244void zoom2_set_hs_extmute(int mute)
245{
246 gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
247}
241 248
242static int zoom_batt_table[] = { 249static int zoom_batt_table[] = {
243/* 0 C*/ 250/* 0 C*/
@@ -307,6 +314,11 @@ static struct i2c_board_info __initdata zoom_i2c_boardinfo[] = {
307 314
308static int __init omap_i2c_init(void) 315static int __init omap_i2c_init(void)
309{ 316{
317 if (machine_is_omap_zoom2()) {
318 zoom_audio_data.ramp_delay_value = 3; /* 161 ms */
319 zoom_audio_data.hs_extmute = 1;
320 zoom_audio_data.set_hs_extmute = zoom2_set_hs_extmute;
321 }
310 omap_register_i2c_bus(1, 2400, zoom_i2c_boardinfo, 322 omap_register_i2c_bus(1, 2400, zoom_i2c_boardinfo,
311 ARRAY_SIZE(zoom_i2c_boardinfo)); 323 ARRAY_SIZE(zoom_i2c_boardinfo));
312 omap_register_i2c_bus(2, 400, NULL, 0); 324 omap_register_i2c_bus(2, 400, NULL, 0);
diff --git a/arch/arm/mach-omap2/board-zoom2.c b/arch/arm/mach-omap2/board-zoom2.c
index 24bbd0def64f..4ccbc32386a0 100644
--- a/arch/arm/mach-omap2/board-zoom2.c
+++ b/arch/arm/mach-omap2/board-zoom2.c
@@ -14,6 +14,7 @@
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/input.h> 15#include <linux/input.h>
16#include <linux/gpio.h> 16#include <linux/gpio.h>
17#include <linux/i2c/twl.h>
17 18
18#include <asm/mach-types.h> 19#include <asm/mach-types.h>
19#include <asm/mach/arch.h> 20#include <asm/mach/arch.h>
@@ -34,41 +35,6 @@ static void __init omap_zoom2_init_irq(void)
34 omap_gpio_init(); 35 omap_gpio_init();
35} 36}
36 37
37/* REVISIT: These audio entries can be removed once MFD code is merged */
38#if 0
39
40static struct twl4030_madc_platform_data zoom2_madc_data = {
41 .irq_line = 1,
42};
43
44static struct twl4030_codec_audio_data zoom2_audio_data = {
45 .audio_mclk = 26000000,
46};
47
48static struct twl4030_codec_data zoom2_codec_data = {
49 .audio_mclk = 26000000,
50 .audio = &zoom2_audio_data,
51};
52
53static struct twl4030_platform_data zoom2_twldata = {
54 .irq_base = TWL4030_IRQ_BASE,
55 .irq_end = TWL4030_IRQ_END,
56
57 /* platform_data for children goes here */
58 .bci = &zoom2_bci_data,
59 .madc = &zoom2_madc_data,
60 .usb = &zoom2_usb_data,
61 .gpio = &zoom2_gpio_data,
62 .keypad = &zoom2_kp_twl4030_data,
63 .codec = &zoom2_codec_data,
64 .vmmc1 = &zoom2_vmmc1,
65 .vmmc2 = &zoom2_vmmc2,
66 .vsim = &zoom2_vsim,
67
68};
69
70#endif
71
72#ifdef CONFIG_OMAP_MUX 38#ifdef CONFIG_OMAP_MUX
73static struct omap_board_mux board_mux[] __initdata = { 39static struct omap_board_mux board_mux[] __initdata = {
74 /* WLAN IRQ - GPIO 162 */ 40 /* WLAN IRQ - GPIO 162 */
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index b27e7cbb3f29..c5cf1ba08a6f 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -25,6 +25,7 @@
25#include <plat/control.h> 25#include <plat/control.h>
26#include <plat/tc.h> 26#include <plat/tc.h>
27#include <plat/board.h> 27#include <plat/board.h>
28#include <plat/mcbsp.h>
28#include <mach/gpio.h> 29#include <mach/gpio.h>
29#include <plat/mmc.h> 30#include <plat/mmc.h>
30#include <plat/dma.h> 31#include <plat/dma.h>
@@ -235,6 +236,43 @@ static inline void omap_init_mbox(void) { }
235 236
236static inline void omap_init_sti(void) {} 237static inline void omap_init_sti(void) {}
237 238
239#if defined(CONFIG_SND_SOC) || defined(CONFIG_SND_SOC_MODULE)
240
241static struct platform_device omap_pcm = {
242 .name = "omap-pcm-audio",
243 .id = -1,
244};
245
246/*
247 * OMAP2420 has 2 McBSP ports
248 * OMAP2430 has 5 McBSP ports
249 * OMAP3 has 5 McBSP ports
250 * OMAP4 has 4 McBSP ports
251 */
252OMAP_MCBSP_PLATFORM_DEVICE(1);
253OMAP_MCBSP_PLATFORM_DEVICE(2);
254OMAP_MCBSP_PLATFORM_DEVICE(3);
255OMAP_MCBSP_PLATFORM_DEVICE(4);
256OMAP_MCBSP_PLATFORM_DEVICE(5);
257
258static void omap_init_audio(void)
259{
260 platform_device_register(&omap_mcbsp1);
261 platform_device_register(&omap_mcbsp2);
262 if (cpu_is_omap243x() || cpu_is_omap34xx() || cpu_is_omap44xx()) {
263 platform_device_register(&omap_mcbsp3);
264 platform_device_register(&omap_mcbsp4);
265 }
266 if (cpu_is_omap243x() || cpu_is_omap34xx())
267 platform_device_register(&omap_mcbsp5);
268
269 platform_device_register(&omap_pcm);
270}
271
272#else
273static inline void omap_init_audio(void) {}
274#endif
275
238#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE) 276#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
239 277
240#include <plat/mcspi.h> 278#include <plat/mcspi.h>
@@ -917,6 +955,7 @@ static int __init omap2_init_devices(void)
917 * in alphabetical order so they're easier to sort through. 955 * in alphabetical order so they're easier to sort through.
918 */ 956 */
919 omap_hsmmc_reset(); 957 omap_hsmmc_reset();
958 omap_init_audio();
920 omap_init_camera(); 959 omap_init_camera();
921 omap_init_mbox(); 960 omap_init_mbox();
922 omap_init_mcspi(); 961 omap_init_mcspi();
diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h
index 3af69d2c3dcd..80591fda8f8f 100644
--- a/arch/arm/mach-omap2/include/mach/board-zoom.h
+++ b/arch/arm/mach-omap2/include/mach/board-zoom.h
@@ -9,3 +9,5 @@
9extern void __init board_nand_init(struct mtd_partition *, u8 nr_parts, u8 cs); 9extern void __init board_nand_init(struct mtd_partition *, u8 nr_parts, u8 cs);
10extern int __init zoom_debugboard_init(void); 10extern int __init zoom_debugboard_init(void);
11extern void __init zoom_peripherals_init(void); 11extern void __init zoom_peripherals_init(void);
12
13#define ZOOM2_HEADSET_EXTMUTE_GPIO 153
diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
index 08b410343870..aaa1166df964 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -382,6 +382,31 @@ struct platform_device pxa_device_i2s = {
382 .num_resources = ARRAY_SIZE(pxai2s_resources), 382 .num_resources = ARRAY_SIZE(pxai2s_resources),
383}; 383};
384 384
385struct platform_device pxa_device_asoc_ssp1 = {
386 .name = "pxa-ssp-dai",
387 .id = 0,
388};
389
390struct platform_device pxa_device_asoc_ssp2= {
391 .name = "pxa-ssp-dai",
392 .id = 1,
393};
394
395struct platform_device pxa_device_asoc_ssp3 = {
396 .name = "pxa-ssp-dai",
397 .id = 2,
398};
399
400struct platform_device pxa_device_asoc_ssp4 = {
401 .name = "pxa-ssp-dai",
402 .id = 3,
403};
404
405struct platform_device pxa_device_asoc_platform = {
406 .name = "pxa-pcm-audio",
407 .id = -1,
408};
409
385static u64 pxaficp_dmamask = ~(u32)0; 410static u64 pxaficp_dmamask = ~(u32)0;
386 411
387struct platform_device pxa_device_ficp = { 412struct platform_device pxa_device_ficp = {
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 715e8bd02e24..2fd5a8b35757 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -39,4 +39,10 @@ extern struct platform_device pxa3xx_device_i2c_power;
39 39
40extern struct platform_device pxa3xx_device_gcu; 40extern struct platform_device pxa3xx_device_gcu;
41 41
42extern struct platform_device pxa_device_asoc_platform;
43extern struct platform_device pxa_device_asoc_ssp1;
44extern struct platform_device pxa_device_asoc_ssp2;
45extern struct platform_device pxa_device_asoc_ssp3;
46extern struct platform_device pxa_device_asoc_ssp4;
47
42void __init pxa_register_device(struct platform_device *dev, void *data); 48void __init pxa_register_device(struct platform_device *dev, void *data);
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 12e5b9f01e6f..d1fbf29d561c 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -385,6 +385,10 @@ static struct platform_device *devices[] __initdata = {
385 &pxa27x_device_udc, 385 &pxa27x_device_udc,
386 &pxa_device_pmu, 386 &pxa_device_pmu,
387 &pxa_device_i2s, 387 &pxa_device_i2s,
388 &pxa_device_asoc_ssp1,
389 &pxa_device_asoc_ssp2,
390 &pxa_device_asoc_ssp3,
391 &pxa_device_asoc_platform,
388 &sa1100_device_rtc, 392 &sa1100_device_rtc,
389 &pxa_device_rtc, 393 &pxa_device_rtc,
390 &pxa27x_device_ssp1, 394 &pxa27x_device_ssp1,
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index c85c3a7abd31..d1c747cdacf8 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -593,6 +593,11 @@ static struct platform_device *devices[] __initdata = {
593 &pxa27x_device_udc, 593 &pxa27x_device_udc,
594 &pxa_device_pmu, 594 &pxa_device_pmu,
595 &pxa_device_i2s, 595 &pxa_device_i2s,
596 &pxa_device_asoc_ssp1,
597 &pxa_device_asoc_ssp2,
598 &pxa_device_asoc_ssp3,
599 &pxa_device_asoc_ssp4,
600 &pxa_device_asoc_platform,
596 &sa1100_device_rtc, 601 &sa1100_device_rtc,
597 &pxa_device_rtc, 602 &pxa_device_rtc,
598 &pxa27x_device_ssp1, 603 &pxa27x_device_ssp1,
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index f25fb6245bd7..702f7a68e87d 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -45,6 +45,16 @@ int wm9713_irq;
45int lcd_id; 45int lcd_id;
46int lcd_orientation; 46int lcd_orientation;
47 47
48struct platform_device pxa_device_wm9713_audio = {
49 .name = "wm9713-codec",
50 .id = -1,
51};
52
53static void __init zylonite_init_wm9713_audio(void)
54{
55 platform_device_register(&pxa_device_wm9713_audio);
56}
57
48static struct resource smc91x_resources[] = { 58static struct resource smc91x_resources[] = {
49 [0] = { 59 [0] = {
50 .start = ZYLONITE_ETH_PHYS + 0x300, 60 .start = ZYLONITE_ETH_PHYS + 0x300,
@@ -408,6 +418,7 @@ static void __init zylonite_init(void)
408 zylonite_init_nand(); 418 zylonite_init_nand();
409 zylonite_init_leds(); 419 zylonite_init_leds();
410 zylonite_init_ohci(); 420 zylonite_init_ohci();
421 zylonite_init_wm9713_audio();
411} 422}
412 423
413MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)") 424MACHINE_START(ZYLONITE, "PXA3xx Platform Development Kit (aka Zylonite)")
diff --git a/arch/arm/mach-s3c64xx/dev-audio.c b/arch/arm/mach-s3c64xx/dev-audio.c
index 9648fbc36eec..3838335f125b 100644
--- a/arch/arm/mach-s3c64xx/dev-audio.c
+++ b/arch/arm/mach-s3c64xx/dev-audio.c
@@ -43,8 +43,10 @@ static int s3c64xx_i2sv3_cfg_gpio(struct platform_device *pdev)
43 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); 43 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK);
44 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); 44 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI);
45 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); 45 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0);
46 break;
46 default: 47 default:
47 printk(KERN_DEBUG "Invalid I2S Controller number!"); 48 printk(KERN_DEBUG "Invalid I2S Controller number: %d\n",
49 pdev->id);
48 return -EINVAL; 50 return -EINVAL;
49 } 51 }
50 52
@@ -184,7 +186,8 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
184 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT); 186 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_PCM1_SOUT);
185 break; 187 break;
186 default: 188 default:
187 printk(KERN_DEBUG "Invalid PCM Controller number!"); 189 printk(KERN_DEBUG "Invalid PCM Controller number: %d\n",
190 pdev->id);
188 return -EINVAL; 191 return -EINVAL;
189 } 192 }
190 193
@@ -333,3 +336,16 @@ void __init s3c64xx_ac97_setup_gpio(int num)
333 else 336 else
334 s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe; 337 s3c_ac97_pdata.cfg_gpio = s3c64xx_ac97_cfg_gpe;
335} 338}
339
340static u64 s3c_device_audio_dmamask = 0xffffffffUL;
341
342struct platform_device s3c_device_pcm = {
343 .name = "s3c24xx-pcm-audio",
344 .id = -1,
345 .dev = {
346 .dma_mask = &s3c_device_audio_dmamask,
347 .coherent_dma_mask = 0xffffffffUL
348 }
349};
350EXPORT_SYMBOL(s3c_device_pcm);
351
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index ec8865c03a19..77488facfe4c 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -283,6 +283,7 @@ static struct platform_device *smdk6410_devices[] __initdata = {
283 &s3c_device_fb, 283 &s3c_device_fb,
284 &s3c_device_ohci, 284 &s3c_device_ohci,
285 &s3c_device_usb_hsotg, 285 &s3c_device_usb_hsotg,
286 &s3c_device_pcm,
286 &s3c64xx_device_iisv4, 287 &s3c64xx_device_iisv4,
287 &samsung_device_keypad, 288 &samsung_device_keypad,
288 289
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index b4ff6a11a8f2..5b20103e68eb 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -30,6 +30,13 @@
30#include <mach/hardware.h> 30#include <mach/hardware.h>
31#include <plat/clock.h> 31#include <plat/clock.h>
32 32
33/* macro for building platform_device for McBSP ports */
34#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr) \
35static struct platform_device omap_mcbsp##port_nr = { \
36 .name = "omap-mcbsp-dai", \
37 .id = OMAP_MCBSP##port_nr, \
38}
39
33#define OMAP7XX_MCBSP1_BASE 0xfffb1000 40#define OMAP7XX_MCBSP1_BASE 0xfffb1000
34#define OMAP7XX_MCBSP2_BASE 0xfffb1800 41#define OMAP7XX_MCBSP2_BASE 0xfffb1800
35 42
diff --git a/arch/arm/plat-s3c24xx/devs.c b/arch/arm/plat-s3c24xx/devs.c
index 452e18438b41..2f91057a0c02 100644
--- a/arch/arm/plat-s3c24xx/devs.c
+++ b/arch/arm/plat-s3c24xx/devs.c
@@ -247,7 +247,7 @@ static struct resource s3c_iis_resource[] = {
247static u64 s3c_device_iis_dmamask = 0xffffffffUL; 247static u64 s3c_device_iis_dmamask = 0xffffffffUL;
248 248
249struct platform_device s3c_device_iis = { 249struct platform_device s3c_device_iis = {
250 .name = "s3c2410-iis", 250 .name = "s3c24xx-iis",
251 .id = -1, 251 .id = -1,
252 .num_resources = ARRAY_SIZE(s3c_iis_resource), 252 .num_resources = ARRAY_SIZE(s3c_iis_resource),
253 .resource = s3c_iis_resource, 253 .resource = s3c_iis_resource,
@@ -259,6 +259,21 @@ struct platform_device s3c_device_iis = {
259 259
260EXPORT_SYMBOL(s3c_device_iis); 260EXPORT_SYMBOL(s3c_device_iis);
261 261
262/* ASoC PCM DMA */
263
264static u64 s3c_device_audio_dmamask = 0xffffffffUL;
265
266struct platform_device s3c_device_pcm = {
267 .name = "s3c24xx-pcm-audio",
268 .id = -1,
269 .dev = {
270 .dma_mask = &s3c_device_audio_dmamask,
271 .coherent_dma_mask = 0xffffffffUL
272 }
273};
274
275EXPORT_SYMBOL(s3c_device_pcm);
276
262/* RTC */ 277/* RTC */
263 278
264static struct resource s3c_rtc_resource[] = { 279static struct resource s3c_rtc_resource[] = {
@@ -481,19 +496,30 @@ static struct resource s3c_ac97_resource[] = {
481 }, 496 },
482}; 497};
483 498
484static u64 s3c_device_ac97_dmamask = 0xffffffffUL;
485
486struct platform_device s3c_device_ac97 = { 499struct platform_device s3c_device_ac97 = {
487 .name = "s3c-ac97", 500 .name = "s3c-ac97",
488 .id = -1, 501 .id = -1,
489 .num_resources = ARRAY_SIZE(s3c_ac97_resource), 502 .num_resources = ARRAY_SIZE(s3c_ac97_resource),
490 .resource = s3c_ac97_resource, 503 .resource = s3c_ac97_resource,
491 .dev = { 504 .dev = {
492 .dma_mask = &s3c_device_ac97_dmamask, 505 .dma_mask = &s3c_device_audio_dmamask,
493 .coherent_dma_mask = 0xffffffffUL 506 .coherent_dma_mask = 0xffffffffUL
494 } 507 }
495}; 508};
496 509
497EXPORT_SYMBOL(s3c_device_ac97); 510EXPORT_SYMBOL(s3c_device_ac97);
498 511
512/* ASoC I2S */
513
514struct platform_device s3c2412_device_iis = {
515 .name = "s3c2412-iis",
516 .id = -1,
517 .dev = {
518 .dma_mask = &s3c_device_audio_dmamask,
519 .coherent_dma_mask = 0xffffffffUL
520 }
521};
522
523EXPORT_SYMBOL(s3c2412_device_iis);
524
499#endif // CONFIG_CPU_S32440 525#endif // CONFIG_CPU_S32440
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index 7d448e138792..c8b94279bad1 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -32,6 +32,8 @@ extern struct platform_device s3c64xx_device_iisv4;
32extern struct platform_device s3c64xx_device_spi0; 32extern struct platform_device s3c64xx_device_spi0;
33extern struct platform_device s3c64xx_device_spi1; 33extern struct platform_device s3c64xx_device_spi1;
34 34
35extern struct platform_device s3c_device_pcm;
36
35extern struct platform_device s3c64xx_device_pcm0; 37extern struct platform_device s3c64xx_device_pcm0;
36extern struct platform_device s3c64xx_device_pcm1; 38extern struct platform_device s3c64xx_device_pcm1;
37 39
diff --git a/arch/mips/alchemy/devboards/db1200/platform.c b/arch/mips/alchemy/devboards/db1200/platform.c
index 3fa34c3abc04..fbb55935b99e 100644
--- a/arch/mips/alchemy/devboards/db1200/platform.c
+++ b/arch/mips/alchemy/devboards/db1200/platform.c
@@ -429,6 +429,11 @@ static struct platform_device db1200_audio_dev = {
429 .resource = au1200_psc1_res, 429 .resource = au1200_psc1_res,
430}; 430};
431 431
432static struct platform_device db1200_stac_dev = {
433 .name = "ac97-codec",
434 .id = 1, /* on PSC1 */
435};
436
432static struct platform_device *db1200_devs[] __initdata = { 437static struct platform_device *db1200_devs[] __initdata = {
433 NULL, /* PSC0, selected by S6.8 */ 438 NULL, /* PSC0, selected by S6.8 */
434 &db1200_ide_dev, 439 &db1200_ide_dev,
@@ -436,6 +441,7 @@ static struct platform_device *db1200_devs[] __initdata = {
436 &db1200_rtc_dev, 441 &db1200_rtc_dev,
437 &db1200_nand_dev, 442 &db1200_nand_dev,
438 &db1200_audio_dev, 443 &db1200_audio_dev,
444 &db1200_stac_dev,
439}; 445};
440 446
441static int __init db1200_dev_init(void) 447static int __init db1200_dev_init(void)
diff --git a/arch/powerpc/boot/dts/mpc8610_hpcd.dts b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
index 9535ce68caae..83c3218cb4da 100644
--- a/arch/powerpc/boot/dts/mpc8610_hpcd.dts
+++ b/arch/powerpc/boot/dts/mpc8610_hpcd.dts
@@ -286,6 +286,7 @@
286 286
287 ssi@16100 { 287 ssi@16100 {
288 compatible = "fsl,mpc8610-ssi"; 288 compatible = "fsl,mpc8610-ssi";
289 status = "disabled";
289 cell-index = <1>; 290 cell-index = <1>;
290 reg = <0x16100 0x100>; 291 reg = <0x16100 0x100>;
291 interrupt-parent = <&mpic>; 292 interrupt-parent = <&mpic>;
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index c3b113b2ca31..3aeb5949cfef 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -124,6 +124,9 @@ CONFIG_I2C_CPM=m
124CONFIG_I2C_MPC=y 124CONFIG_I2C_MPC=y
125# CONFIG_HWMON is not set 125# CONFIG_HWMON is not set
126CONFIG_VIDEO_OUTPUT_CONTROL=y 126CONFIG_VIDEO_OUTPUT_CONTROL=y
127CONFIG_FB=y
128CONFIG_FB_FSL_DIU=y
129# CONFIG_VGA_CONSOLE is not set
127CONFIG_SOUND=y 130CONFIG_SOUND=y
128CONFIG_SND=y 131CONFIG_SND=y
129# CONFIG_SND_SUPPORT_OLD_API is not set 132# CONFIG_SND_SUPPORT_OLD_API is not set
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index a075da2ea3fb..d62c8016f4bc 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -126,6 +126,9 @@ CONFIG_I2C_CPM=m
126CONFIG_I2C_MPC=y 126CONFIG_I2C_MPC=y
127# CONFIG_HWMON is not set 127# CONFIG_HWMON is not set
128CONFIG_VIDEO_OUTPUT_CONTROL=y 128CONFIG_VIDEO_OUTPUT_CONTROL=y
129CONFIG_FB=y
130CONFIG_FB_FSL_DIU=y
131# CONFIG_VGA_CONSOLE is not set
129CONFIG_SOUND=y 132CONFIG_SOUND=y
130CONFIG_SND=y 133CONFIG_SND=y
131# CONFIG_SND_SUPPORT_OLD_API is not set 134# CONFIG_SND_SUPPORT_OLD_API is not set
diff --git a/arch/powerpc/include/asm/immap_86xx.h b/arch/powerpc/include/asm/fsl_guts.h
index 0f165e59c326..bebd12463ec9 100644
--- a/arch/powerpc/include/asm/immap_86xx.h
+++ b/arch/powerpc/include/asm/fsl_guts.h
@@ -1,5 +1,5 @@
1/** 1/**
2 * MPC86xx Internal Memory Map 2 * Freecale 85xx and 86xx Global Utilties register set
3 * 3 *
4 * Authors: Jeff Brown 4 * Authors: Jeff Brown
5 * Timur Tabi <timur@freescale.com> 5 * Timur Tabi <timur@freescale.com>
@@ -10,73 +10,112 @@
10 * under the terms of the GNU General Public License as published by the 10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your 11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. 12 * option) any later version.
13 *
14 * This header file defines structures for various 86xx SOC devices that are
15 * used by multiple source files.
16 */ 13 */
17 14
18#ifndef __ASM_POWERPC_IMMAP_86XX_H__ 15#ifndef __ASM_POWERPC_FSL_GUTS_H__
19#define __ASM_POWERPC_IMMAP_86XX_H__ 16#define __ASM_POWERPC_FSL_GUTS_H__
20#ifdef __KERNEL__ 17#ifdef __KERNEL__
21 18
22/* Global Utility Registers */ 19/*
23struct ccsr_guts { 20 * These #ifdefs are safe because it's not possible to build a kernel that
21 * runs on e500 and e600 cores.
22 */
23
24#if !defined(CONFIG_PPC_85xx) && !defined(CONFIG_PPC_86xx)
25#error Only 85xx and 86xx SOCs are supported
26#endif
27
28/**
29 * Global Utility Registers.
30 *
31 * Not all registers defined in this structure are available on all chips, so
32 * you are expected to know whether a given register actually exists on your
33 * chip before you access it.
34 *
35 * Also, some registers are similar on different chips but have slightly
36 * different names. In these cases, one name is chosen to avoid extraneous
37 * #ifdefs.
38 */
39#ifdef CONFIG_PPC_85xx
40struct ccsr_guts_85xx {
41#else
42struct ccsr_guts_86xx {
43#endif
24 __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */ 44 __be32 porpllsr; /* 0x.0000 - POR PLL Ratio Status Register */
25 __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */ 45 __be32 porbmsr; /* 0x.0004 - POR Boot Mode Status Register */
26 __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */ 46 __be32 porimpscr; /* 0x.0008 - POR I/O Impedance Status and Control Register */
27 __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */ 47 __be32 pordevsr; /* 0x.000c - POR I/O Device Status Register */
28 __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */ 48 __be32 pordbgmsr; /* 0x.0010 - POR Debug Mode Status Register */
29 u8 res1[0x20 - 0x14]; 49 __be32 pordevsr2; /* 0x.0014 - POR device status register 2 */
50 u8 res018[0x20 - 0x18];
30 __be32 porcir; /* 0x.0020 - POR Configuration Information Register */ 51 __be32 porcir; /* 0x.0020 - POR Configuration Information Register */
31 u8 res2[0x30 - 0x24]; 52 u8 res024[0x30 - 0x24];
32 __be32 gpiocr; /* 0x.0030 - GPIO Control Register */ 53 __be32 gpiocr; /* 0x.0030 - GPIO Control Register */
33 u8 res3[0x40 - 0x34]; 54 u8 res034[0x40 - 0x34];
34 __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */ 55 __be32 gpoutdr; /* 0x.0040 - General-Purpose Output Data Register */
35 u8 res4[0x50 - 0x44]; 56 u8 res044[0x50 - 0x44];
36 __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */ 57 __be32 gpindr; /* 0x.0050 - General-Purpose Input Data Register */
37 u8 res5[0x60 - 0x54]; 58 u8 res054[0x60 - 0x54];
38 __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */ 59 __be32 pmuxcr; /* 0x.0060 - Alternate Function Signal Multiplex Control */
39 u8 res6[0x70 - 0x64]; 60 __be32 pmuxcr2; /* 0x.0064 - Alternate function signal multiplex control 2 */
61 __be32 dmuxcr; /* 0x.0068 - DMA Mux Control Register */
62 u8 res06c[0x70 - 0x6c];
40 __be32 devdisr; /* 0x.0070 - Device Disable Control */ 63 __be32 devdisr; /* 0x.0070 - Device Disable Control */
41 __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */ 64 __be32 devdisr2; /* 0x.0074 - Device Disable Control 2 */
42 u8 res7[0x80 - 0x78]; 65 u8 res078[0x7c - 0x78];
66 __be32 pmjcr; /* 0x.007c - 4 Power Management Jog Control Register */
43 __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */ 67 __be32 powmgtcsr; /* 0x.0080 - Power Management Status and Control Register */
44 u8 res8[0x90 - 0x84]; 68 __be32 pmrccr; /* 0x.0084 - Power Management Reset Counter Configuration Register */
69 __be32 pmpdccr; /* 0x.0088 - Power Management Power Down Counter Configuration Register */
70 __be32 pmcdr; /* 0x.008c - 4Power management clock disable register */
45 __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */ 71 __be32 mcpsumr; /* 0x.0090 - Machine Check Summary Register */
46 __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */ 72 __be32 rstrscr; /* 0x.0094 - Reset Request Status and Control Register */
47 u8 res9[0xA0 - 0x98]; 73 __be32 ectrstcr; /* 0x.0098 - Exception reset control register */
74 __be32 autorstsr; /* 0x.009c - Automatic reset status register */
48 __be32 pvr; /* 0x.00a0 - Processor Version Register */ 75 __be32 pvr; /* 0x.00a0 - Processor Version Register */
49 __be32 svr; /* 0x.00a4 - System Version Register */ 76 __be32 svr; /* 0x.00a4 - System Version Register */
50 u8 res10[0xB0 - 0xA8]; 77 u8 res0a8[0xb0 - 0xa8];
51 __be32 rstcr; /* 0x.00b0 - Reset Control Register */ 78 __be32 rstcr; /* 0x.00b0 - Reset Control Register */
52 u8 res11[0xC0 - 0xB4]; 79 u8 res0b4[0xc0 - 0xb4];
80#ifdef CONFIG_PPC_85xx
81 __be32 iovselsr; /* 0x.00c0 - I/O voltage select status register */
82#else
53 __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */ 83 __be32 elbcvselcr; /* 0x.00c0 - eLBC Voltage Select Ctrl Reg */
54 u8 res12[0x800 - 0xC4]; 84#endif
85 u8 res0c4[0x224 - 0xc4];
86 __be32 iodelay1; /* 0x.0224 - IO delay control register 1 */
87 __be32 iodelay2; /* 0x.0228 - IO delay control register 2 */
88 u8 res22c[0x800 - 0x22c];
55 __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */ 89 __be32 clkdvdr; /* 0x.0800 - Clock Divide Register */
56 u8 res13[0x900 - 0x804]; 90 u8 res804[0x900 - 0x804];
57 __be32 ircr; /* 0x.0900 - Infrared Control Register */ 91 __be32 ircr; /* 0x.0900 - Infrared Control Register */
58 u8 res14[0x908 - 0x904]; 92 u8 res904[0x908 - 0x904];
59 __be32 dmacr; /* 0x.0908 - DMA Control Register */ 93 __be32 dmacr; /* 0x.0908 - DMA Control Register */
60 u8 res15[0x914 - 0x90C]; 94 u8 res90c[0x914 - 0x90c];
61 __be32 elbccr; /* 0x.0914 - eLBC Control Register */ 95 __be32 elbccr; /* 0x.0914 - eLBC Control Register */
62 u8 res16[0xB20 - 0x918]; 96 u8 res918[0xb20 - 0x918];
63 __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */ 97 __be32 ddr1clkdr; /* 0x.0b20 - DDR1 Clock Disable Register */
64 __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */ 98 __be32 ddr2clkdr; /* 0x.0b24 - DDR2 Clock Disable Register */
65 __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */ 99 __be32 ddrclkdr; /* 0x.0b28 - DDR Clock Disable Register */
66 u8 res17[0xE00 - 0xB2C]; 100 u8 resb2c[0xe00 - 0xb2c];
67 __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */ 101 __be32 clkocr; /* 0x.0e00 - Clock Out Select Register */
68 u8 res18[0xE10 - 0xE04]; 102 u8 rese04[0xe10 - 0xe04];
69 __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */ 103 __be32 ddrdllcr; /* 0x.0e10 - DDR DLL Control Register */
70 u8 res19[0xE20 - 0xE14]; 104 u8 rese14[0xe20 - 0xe14];
71 __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */ 105 __be32 lbcdllcr; /* 0x.0e20 - LBC DLL Control Register */
72 u8 res20[0xF04 - 0xE24]; 106 __be32 cpfor; /* 0x.0e24 - L2 charge pump fuse override register */
107 u8 rese28[0xf04 - 0xe28];
73 __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */ 108 __be32 srds1cr0; /* 0x.0f04 - SerDes1 Control Register 0 */
74 __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */ 109 __be32 srds1cr1; /* 0x.0f08 - SerDes1 Control Register 0 */
75 u8 res21[0xF40 - 0xF0C]; 110 u8 resf0c[0xf2c - 0xf0c];
76 __be32 srds2cr0; /* 0x.0f40 - SerDes1 Control Register 0 */ 111 __be32 itcr; /* 0x.0f2c - Internal transaction control register */
77 __be32 srds2cr1; /* 0x.0f44 - SerDes1 Control Register 0 */ 112 u8 resf30[0xf40 - 0xf30];
113 __be32 srds2cr0; /* 0x.0f40 - SerDes2 Control Register 0 */
114 __be32 srds2cr1; /* 0x.0f44 - SerDes2 Control Register 0 */
78} __attribute__ ((packed)); 115} __attribute__ ((packed));
79 116
117#ifdef CONFIG_PPC_86xx
118
80#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */ 119#define CCSR_GUTS_DMACR_DEV_SSI 0 /* DMA controller/channel set to SSI */
81#define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */ 120#define CCSR_GUTS_DMACR_DEV_IR 1 /* DMA controller/channel set to IR */
82 121
@@ -93,7 +132,7 @@ struct ccsr_guts {
93 * ch: The channel on the DMA controller (0, 1, 2, or 3) 132 * ch: The channel on the DMA controller (0, 1, 2, or 3)
94 * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx) 133 * device: The device to set as the source (CCSR_GUTS_DMACR_DEV_xx)
95 */ 134 */
96static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts, 135static inline void guts_set_dmacr(struct ccsr_guts_86xx __iomem *guts,
97 unsigned int co, unsigned int ch, unsigned int device) 136 unsigned int co, unsigned int ch, unsigned int device)
98{ 137{
99 unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch)); 138 unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
@@ -129,7 +168,7 @@ static inline void guts_set_dmacr(struct ccsr_guts __iomem *guts,
129 * ch: The channel on the DMA controller (0, 1, 2, or 3) 168 * ch: The channel on the DMA controller (0, 1, 2, or 3)
130 * value: the new value for the bit (0 or 1) 169 * value: the new value for the bit (0 or 1)
131 */ 170 */
132static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts, 171static inline void guts_set_pmuxcr_dma(struct ccsr_guts_86xx __iomem *guts,
133 unsigned int co, unsigned int ch, unsigned int value) 172 unsigned int co, unsigned int ch, unsigned int value)
134{ 173{
135 if ((ch == 0) || (ch == 3)) { 174 if ((ch == 0) || (ch == 3)) {
@@ -152,5 +191,7 @@ static inline void guts_set_pmuxcr_dma(struct ccsr_guts __iomem *guts,
152#define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF 191#define CCSR_GUTS_CLKDVDR_SSICLK_MASK 0x000000FF
153#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK) 192#define CCSR_GUTS_CLKDVDR_SSICLK(x) ((x) & CCSR_GUTS_CLKDVDR_SSICLK_MASK)
154 193
155#endif /* __ASM_POWERPC_IMMAP_86XX_H__ */ 194#endif
156#endif /* __KERNEL__ */ 195
196#endif
197#endif
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 2b390d19a1d1..7eb5c40c069f 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -8,7 +8,6 @@
8 * Copyright 2010 Freescale Semiconductor, Inc. 8 * Copyright 2010 Freescale Semiconductor, Inc.
9 * 9 *
10 * This file is taken from the Freescale P1022DS BSP, with modifications: 10 * This file is taken from the Freescale P1022DS BSP, with modifications:
11 * 1) No DIU support (pending rewrite of DIU code)
12 * 2) No AMP support 11 * 2) No AMP support
13 * 3) No PCI endpoint support 12 * 3) No PCI endpoint support
14 * 13 *
@@ -20,12 +19,211 @@
20#include <linux/pci.h> 19#include <linux/pci.h>
21#include <linux/of_platform.h> 20#include <linux/of_platform.h>
22#include <linux/memblock.h> 21#include <linux/memblock.h>
23 22#include <asm/div64.h>
24#include <asm/mpic.h> 23#include <asm/mpic.h>
25#include <asm/swiotlb.h> 24#include <asm/swiotlb.h>
26 25
27#include <sysdev/fsl_soc.h> 26#include <sysdev/fsl_soc.h>
28#include <sysdev/fsl_pci.h> 27#include <sysdev/fsl_pci.h>
28#include <asm/fsl_guts.h>
29
30#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
31
32/*
33 * Board-specific initialization of the DIU. This code should probably be
34 * executed when the DIU is opened, rather than in arch code, but the DIU
35 * driver does not have a mechanism for this (yet).
36 *
37 * This is especially problematic on the P1022DS because the local bus (eLBC)
38 * and the DIU video signals share the same pins, which means that enabling the
39 * DIU will disable access to NOR flash.
40 */
41
42/* DIU Pixel Clock bits of the CLKDVDR Global Utilities register */
43#define CLKDVDR_PXCKEN 0x80000000
44#define CLKDVDR_PXCKINV 0x10000000
45#define CLKDVDR_PXCKDLY 0x06000000
46#define CLKDVDR_PXCLK_MASK 0x00FF0000
47
48/* Some ngPIXIS register definitions */
49#define PX_BRDCFG1_DVIEN 0x80
50#define PX_BRDCFG1_DFPEN 0x40
51#define PX_BRDCFG1_BACKLIGHT 0x20
52#define PX_BRDCFG1_DDCEN 0x10
53
54/*
55 * DIU Area Descriptor
56 *
57 * Note that we need to byte-swap the value before it's written to the AD
58 * register. So even though the registers don't look like they're in the same
59 * bit positions as they are on the MPC8610, the same value is written to the
60 * AD register on the MPC8610 and on the P1022.
61 */
62#define AD_BYTE_F 0x10000000
63#define AD_ALPHA_C_MASK 0x0E000000
64#define AD_ALPHA_C_SHIFT 25
65#define AD_BLUE_C_MASK 0x01800000
66#define AD_BLUE_C_SHIFT 23
67#define AD_GREEN_C_MASK 0x00600000
68#define AD_GREEN_C_SHIFT 21
69#define AD_RED_C_MASK 0x00180000
70#define AD_RED_C_SHIFT 19
71#define AD_PALETTE 0x00040000
72#define AD_PIXEL_S_MASK 0x00030000
73#define AD_PIXEL_S_SHIFT 16
74#define AD_COMP_3_MASK 0x0000F000
75#define AD_COMP_3_SHIFT 12
76#define AD_COMP_2_MASK 0x00000F00
77#define AD_COMP_2_SHIFT 8
78#define AD_COMP_1_MASK 0x000000F0
79#define AD_COMP_1_SHIFT 4
80#define AD_COMP_0_MASK 0x0000000F
81#define AD_COMP_0_SHIFT 0
82
83#define MAKE_AD(alpha, red, blue, green, size, c0, c1, c2, c3) \
84 cpu_to_le32(AD_BYTE_F | (alpha << AD_ALPHA_C_SHIFT) | \
85 (blue << AD_BLUE_C_SHIFT) | (green << AD_GREEN_C_SHIFT) | \
86 (red << AD_RED_C_SHIFT) | (c3 << AD_COMP_3_SHIFT) | \
87 (c2 << AD_COMP_2_SHIFT) | (c1 << AD_COMP_1_SHIFT) | \
88 (c0 << AD_COMP_0_SHIFT) | (size << AD_PIXEL_S_SHIFT))
89
90/**
91 * p1022ds_get_pixel_format: return the Area Descriptor for a given pixel depth
92 *
93 * The Area Descriptor is a 32-bit value that determine which bits in each
94 * pixel are to be used for each color.
95 */
96static unsigned int p1022ds_get_pixel_format(unsigned int bits_per_pixel,
97 int monitor_port)
98{
99 switch (bits_per_pixel) {
100 case 32:
101 /* 0x88883316 */
102 return MAKE_AD(3, 2, 0, 1, 3, 8, 8, 8, 8);
103 case 24:
104 /* 0x88082219 */
105 return MAKE_AD(4, 0, 1, 2, 2, 0, 8, 8, 8);
106 case 16:
107 /* 0x65053118 */
108 return MAKE_AD(4, 2, 1, 0, 1, 5, 6, 5, 0);
109 default:
110 pr_err("fsl-diu: unsupported pixel depth %u\n", bits_per_pixel);
111 return 0;
112 }
113}
114
115/**
116 * p1022ds_set_gamma_table: update the gamma table, if necessary
117 *
118 * On some boards, the gamma table for some ports may need to be modified.
119 * This is not the case on the P1022DS, so we do nothing.
120*/
121static void p1022ds_set_gamma_table(int monitor_port, char *gamma_table_base)
122{
123}
124
125/**
126 * p1022ds_set_monitor_port: switch the output to a different monitor port
127 *
128 */
129static void p1022ds_set_monitor_port(int monitor_port)
130{
131 struct device_node *pixis_node;
132 u8 __iomem *brdcfg1;
133
134 pixis_node = of_find_compatible_node(NULL, NULL, "fsl,p1022ds-pixis");
135 if (!pixis_node) {
136 pr_err("p1022ds: missing ngPIXIS node\n");
137 return;
138 }
139
140 brdcfg1 = of_iomap(pixis_node, 0);
141 if (!brdcfg1) {
142 pr_err("p1022ds: could not map ngPIXIS registers\n");
143 return;
144 }
145 brdcfg1 += 9; /* BRDCFG1 is at offset 9 in the ngPIXIS */
146
147 switch (monitor_port) {
148 case 0: /* DVI */
149 /* Enable the DVI port, disable the DFP and the backlight */
150 clrsetbits_8(brdcfg1, PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT,
151 PX_BRDCFG1_DVIEN);
152 break;
153 case 1: /* Single link LVDS */
154 /* Enable the DFP port, disable the DVI and the backlight */
155 clrsetbits_8(brdcfg1, PX_BRDCFG1_DVIEN | PX_BRDCFG1_BACKLIGHT,
156 PX_BRDCFG1_DFPEN);
157 break;
158 default:
159 pr_err("p1022ds: unsupported monitor port %i\n", monitor_port);
160 }
161}
162
163/**
164 * p1022ds_set_pixel_clock: program the DIU's clock
165 *
166 * @pixclock: the wavelength, in picoseconds, of the clock
167 */
168void p1022ds_set_pixel_clock(unsigned int pixclock)
169{
170 struct device_node *guts_np = NULL;
171 struct ccsr_guts_85xx __iomem *guts;
172 unsigned long freq;
173 u64 temp;
174 u32 pxclk;
175
176 /* Map the global utilities registers. */
177 guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
178 if (!guts_np) {
179 pr_err("p1022ds: missing global utilties device node\n");
180 return;
181 }
182
183 guts = of_iomap(guts_np, 0);
184 of_node_put(guts_np);
185 if (!guts) {
186 pr_err("p1022ds: could not map global utilties device\n");
187 return;
188 }
189
190 /* Convert pixclock from a wavelength to a frequency */
191 temp = 1000000000000ULL;
192 do_div(temp, pixclock);
193 freq = temp;
194
195 /* pixclk is the ratio of the platform clock to the pixel clock */
196 pxclk = DIV_ROUND_CLOSEST(fsl_get_sys_freq(), freq);
197
198 /* Disable the pixel clock, and set it to non-inverted and no delay */
199 clrbits32(&guts->clkdvdr,
200 CLKDVDR_PXCKEN | CLKDVDR_PXCKDLY | CLKDVDR_PXCLK_MASK);
201
202 /* Enable the clock and set the pxclk */
203 setbits32(&guts->clkdvdr, CLKDVDR_PXCKEN | (pxclk << 16));
204}
205
206/**
207 * p1022ds_show_monitor_port: show the current monitor
208 *
209 * This function returns a string indicating whether the current monitor is
210 * set to DVI or LVDS.
211 */
212ssize_t p1022ds_show_monitor_port(int monitor_port, char *buf)
213{
214 return sprintf(buf, "%c0 - DVI\n%c1 - Single link LVDS\n",
215 monitor_port == 0 ? '*' : ' ', monitor_port == 1 ? '*' : ' ');
216}
217
218/**
219 * p1022ds_set_sysfs_monitor_port: set the monitor port for sysfs
220 */
221int p1022ds_set_sysfs_monitor_port(int val)
222{
223 return val < 2 ? val : 0;
224}
225
226#endif
29 227
30void __init p1022_ds_pic_init(void) 228void __init p1022_ds_pic_init(void)
31{ 229{
@@ -92,6 +290,15 @@ static void __init p1022_ds_setup_arch(void)
92 } 290 }
93#endif 291#endif
94 292
293#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
294 diu_ops.get_pixel_format = p1022ds_get_pixel_format;
295 diu_ops.set_gamma_table = p1022ds_set_gamma_table;
296 diu_ops.set_monitor_port = p1022ds_set_monitor_port;
297 diu_ops.set_pixel_clock = p1022ds_set_pixel_clock;
298 diu_ops.show_monitor_port = p1022ds_show_monitor_port;
299 diu_ops.set_sysfs_monitor_port = p1022ds_set_sysfs_monitor_port;
300#endif
301
95#ifdef CONFIG_SMP 302#ifdef CONFIG_SMP
96 mpc85xx_smp_init(); 303 mpc85xx_smp_init();
97#endif 304#endif
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index 156ccc960015..d551ed8dea95 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -551,7 +551,7 @@ static struct resource siu_resources[] = {
551}; 551};
552 552
553static struct platform_device siu_device = { 553static struct platform_device siu_device = {
554 .name = "sh_siu", 554 .name = "siu-pcm-audio",
555 .id = -1, 555 .id = -1,
556 .dev = { 556 .dev = {
557 .platform_data = &siu_platform_data, 557 .platform_data = &siu_platform_data,
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index 4f9b2afc24e8..014dd4ad0d4f 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -271,7 +271,7 @@ static struct platform_driver twl4030_vibra_driver = {
271 .probe = twl4030_vibra_probe, 271 .probe = twl4030_vibra_probe,
272 .remove = __devexit_p(twl4030_vibra_remove), 272 .remove = __devexit_p(twl4030_vibra_remove),
273 .driver = { 273 .driver = {
274 .name = "twl4030_codec_vibra", 274 .name = "twl4030-vibra",
275 .owner = THIS_MODULE, 275 .owner = THIS_MODULE,
276#ifdef CONFIG_PM 276#ifdef CONFIG_PM
277 .pm = &twl4030_vibra_pm_ops, 277 .pm = &twl4030_vibra_pm_ops,
@@ -291,7 +291,7 @@ static void __exit twl4030_vibra_exit(void)
291} 291}
292module_exit(twl4030_vibra_exit); 292module_exit(twl4030_vibra_exit);
293 293
294MODULE_ALIAS("platform:twl4030_codec_vibra"); 294MODULE_ALIAS("platform:twl4030-vibra");
295 295
296MODULE_DESCRIPTION("TWL4030 Vibra driver"); 296MODULE_DESCRIPTION("TWL4030 Vibra driver");
297MODULE_LICENSE("GPL"); 297MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 720e099e506d..5d0fb60a4c14 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -698,17 +698,17 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
698 698
699 if (twl_has_codec() && pdata->codec && twl_class_is_4030()) { 699 if (twl_has_codec() && pdata->codec && twl_class_is_4030()) {
700 sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; 700 sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
701 child = add_child(sub_chip_id, "twl4030_codec", 701 child = add_child(sub_chip_id, "twl4030-audio",
702 pdata->codec, sizeof(*pdata->codec), 702 pdata->codec, sizeof(*pdata->codec),
703 false, 0, 0); 703 false, 0, 0);
704 if (IS_ERR(child)) 704 if (IS_ERR(child))
705 return PTR_ERR(child); 705 return PTR_ERR(child);
706 } 706 }
707 707
708 /* Phoenix*/ 708 /* Phoenix codec driver is probed directly atm */
709 if (twl_has_codec() && pdata->codec && twl_class_is_6030()) { 709 if (twl_has_codec() && pdata->codec && twl_class_is_6030()) {
710 sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid; 710 sub_chip_id = twl_map[TWL_MODULE_AUDIO_VOICE].sid;
711 child = add_child(sub_chip_id, "twl6040_codec", 711 child = add_child(sub_chip_id, "twl6040-codec",
712 pdata->codec, sizeof(*pdata->codec), 712 pdata->codec, sizeof(*pdata->codec),
713 false, 0, 0); 713 false, 0, 0);
714 if (IS_ERR(child)) 714 if (IS_ERR(child))
diff --git a/drivers/mfd/twl4030-codec.c b/drivers/mfd/twl4030-codec.c
index add6f67d8032..9a4b196d6deb 100644
--- a/drivers/mfd/twl4030-codec.c
+++ b/drivers/mfd/twl4030-codec.c
@@ -207,14 +207,14 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
207 207
208 if (pdata->audio) { 208 if (pdata->audio) {
209 cell = &codec->cells[childs]; 209 cell = &codec->cells[childs];
210 cell->name = "twl4030_codec_audio"; 210 cell->name = "twl4030-codec";
211 cell->platform_data = pdata->audio; 211 cell->platform_data = pdata->audio;
212 cell->data_size = sizeof(*pdata->audio); 212 cell->data_size = sizeof(*pdata->audio);
213 childs++; 213 childs++;
214 } 214 }
215 if (pdata->vibra) { 215 if (pdata->vibra) {
216 cell = &codec->cells[childs]; 216 cell = &codec->cells[childs];
217 cell->name = "twl4030_codec_vibra"; 217 cell->name = "twl4030-vibra";
218 cell->platform_data = pdata->vibra; 218 cell->platform_data = pdata->vibra;
219 cell->data_size = sizeof(*pdata->vibra); 219 cell->data_size = sizeof(*pdata->vibra);
220 childs++; 220 childs++;
@@ -249,14 +249,14 @@ static int __devexit twl4030_codec_remove(struct platform_device *pdev)
249 return 0; 249 return 0;
250} 250}
251 251
252MODULE_ALIAS("platform:twl4030_codec"); 252MODULE_ALIAS("platform:twl4030-audio");
253 253
254static struct platform_driver twl4030_codec_driver = { 254static struct platform_driver twl4030_codec_driver = {
255 .probe = twl4030_codec_probe, 255 .probe = twl4030_codec_probe,
256 .remove = __devexit_p(twl4030_codec_remove), 256 .remove = __devexit_p(twl4030_codec_remove),
257 .driver = { 257 .driver = {
258 .owner = THIS_MODULE, 258 .owner = THIS_MODULE,
259 .name = "twl4030_codec", 259 .name = "twl4030-audio",
260 }, 260 },
261}; 261};
262 262
diff --git a/drivers/staging/xgifb/TODO b/drivers/staging/xgifb/TODO
index 7d71019b84c2..c85ff5e9e700 100644
--- a/drivers/staging/xgifb/TODO
+++ b/drivers/staging/xgifb/TODO
@@ -12,4 +12,4 @@ TODO:
12- get rid of non-linux related stuff 12- get rid of non-linux related stuff
13 13
14Please send patches to: 14Please send patches to:
15Arnaud Patard <apatard@mandriva.com> 15Arnaud Patard <arnaud.patard@rtp-net.org>
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index dc06ff134559..596ef6b922bf 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1919,6 +1919,9 @@ config FB_SH_MOBILE_HDMI
1919 tristate "SuperH Mobile HDMI controller support" 1919 tristate "SuperH Mobile HDMI controller support"
1920 depends on FB_SH_MOBILE_LCDC 1920 depends on FB_SH_MOBILE_LCDC
1921 select FB_MODE_HELPERS 1921 select FB_MODE_HELPERS
1922 select SOUND
1923 select SND
1924 select SND_SOC
1922 ---help--- 1925 ---help---
1923 Driver for the on-chip SH-Mobile HDMI controller. 1926 Driver for the on-chip SH-Mobile HDMI controller.
1924 1927
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c
index 2fde08cc66bf..ef989d94511c 100644
--- a/drivers/video/sh_mobile_hdmi.c
+++ b/drivers/video/sh_mobile_hdmi.c
@@ -22,6 +22,8 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23#include <linux/types.h> 23#include <linux/types.h>
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <sound/soc-dapm.h>
26#include <sound/initval.h>
25 27
26#include <video/sh_mobile_hdmi.h> 28#include <video/sh_mobile_hdmi.h>
27#include <video/sh_mobile_lcdc.h> 29#include <video/sh_mobile_lcdc.h>
@@ -222,6 +224,58 @@ static u8 hdmi_read(struct sh_hdmi *hdmi, u8 reg)
222 return ioread8(hdmi->base + reg); 224 return ioread8(hdmi->base + reg);
223} 225}
224 226
227/*
228 * HDMI sound
229 */
230static unsigned int sh_hdmi_snd_read(struct snd_soc_codec *codec,
231 unsigned int reg)
232{
233 struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
234
235 return hdmi_read(hdmi, reg);
236}
237
238static int sh_hdmi_snd_write(struct snd_soc_codec *codec,
239 unsigned int reg,
240 unsigned int value)
241{
242 struct sh_hdmi *hdmi = snd_soc_codec_get_drvdata(codec);
243
244 hdmi_write(hdmi, value, reg);
245 return 0;
246}
247
248static struct snd_soc_dai_driver sh_hdmi_dai = {
249 .name = "sh_mobile_hdmi-hifi",
250 .playback = {
251 .stream_name = "Playback",
252 .channels_min = 2,
253 .channels_max = 8,
254 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
255 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
256 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
257 SNDRV_PCM_RATE_192000,
258 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
259 },
260};
261
262static int sh_hdmi_snd_probe(struct snd_soc_codec *codec)
263{
264 dev_info(codec->dev, "SH Mobile HDMI Audio Codec");
265
266 return 0;
267}
268
269static struct snd_soc_codec_driver soc_codec_dev_sh_hdmi = {
270 .probe = sh_hdmi_snd_probe,
271 .read = sh_hdmi_snd_read,
272 .write = sh_hdmi_snd_write,
273};
274
275/*
276 * HDMI video
277 */
278
225/* External video parameter settings */ 279/* External video parameter settings */
226static void hdmi_external_video_param(struct sh_hdmi *hdmi) 280static void hdmi_external_video_param(struct sh_hdmi *hdmi)
227{ 281{
@@ -318,6 +372,9 @@ static void sh_hdmi_video_config(struct sh_hdmi *hdmi)
318 */ 372 */
319static void sh_hdmi_audio_config(struct sh_hdmi *hdmi) 373static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
320{ 374{
375 u8 data;
376 struct sh_mobile_hdmi_info *pdata = hdmi->dev->platform_data;
377
321 /* 378 /*
322 * [7:4] L/R data swap control 379 * [7:4] L/R data swap control
323 * [3:0] appropriate N[19:16] 380 * [3:0] appropriate N[19:16]
@@ -335,7 +392,23 @@ static void sh_hdmi_audio_config(struct sh_hdmi *hdmi)
335 * [6:5] set required down sampling rate if required 392 * [6:5] set required down sampling rate if required
336 * [4:3] set required audio source 393 * [4:3] set required audio source
337 */ 394 */
338 hdmi_write(hdmi, 0x00, HDMI_AUDIO_SETTING_1); 395 switch (pdata->flags & HDMI_SND_SRC_MASK) {
396 default:
397 /* fall through */
398 case HDMI_SND_SRC_I2S:
399 data = 0x0 << 3;
400 break;
401 case HDMI_SND_SRC_SPDIF:
402 data = 0x1 << 3;
403 break;
404 case HDMI_SND_SRC_DSD:
405 data = 0x2 << 3;
406 break;
407 case HDMI_SND_SRC_HBR:
408 data = 0x3 << 3;
409 break;
410 }
411 hdmi_write(hdmi, data, HDMI_AUDIO_SETTING_1);
339 412
340 /* [3:0] set sending channel number for channel status */ 413 /* [3:0] set sending channel number for channel status */
341 hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2); 414 hdmi_write(hdmi, 0x40, HDMI_AUDIO_SETTING_2);
@@ -891,6 +964,11 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
891 return -ENOMEM; 964 return -ENOMEM;
892 } 965 }
893 966
967 ret = snd_soc_register_codec(&pdev->dev,
968 &soc_codec_dev_sh_hdmi, &sh_hdmi_dai, 1);
969 if (ret < 0)
970 goto esndreg;
971
894 hdmi->dev = &pdev->dev; 972 hdmi->dev = &pdev->dev;
895 973
896 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick"); 974 hdmi->hdmi_clk = clk_get(&pdev->dev, "ick");
@@ -976,6 +1054,8 @@ eclkenable:
976erate: 1054erate:
977 clk_put(hdmi->hdmi_clk); 1055 clk_put(hdmi->hdmi_clk);
978egetclk: 1056egetclk:
1057 snd_soc_unregister_codec(&pdev->dev);
1058esndreg:
979 kfree(hdmi); 1059 kfree(hdmi);
980 1060
981 return ret; 1061 return ret;
@@ -988,6 +1068,8 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
988 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1068 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
989 int irq = platform_get_irq(pdev, 0); 1069 int irq = platform_get_irq(pdev, 0);
990 1070
1071 snd_soc_unregister_codec(&pdev->dev);
1072
991 pdata->lcd_chan->board_cfg.display_on = NULL; 1073 pdata->lcd_chan->board_cfg.display_on = NULL;
992 pdata->lcd_chan->board_cfg.display_off = NULL; 1074 pdata->lcd_chan->board_cfg.display_off = NULL;
993 pdata->lcd_chan->board_cfg.board_data = NULL; 1075 pdata->lcd_chan->board_cfg.board_data = NULL;
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 6de90bfc6acd..4793d8a7f480 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -553,8 +553,12 @@ extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
553extern int twl4030_remove_script(u8 flags); 553extern int twl4030_remove_script(u8 flags);
554 554
555struct twl4030_codec_audio_data { 555struct twl4030_codec_audio_data {
556 unsigned int audio_mclk; 556 unsigned int audio_mclk; /* not used, will be removed */
557 unsigned int digimic_delay; /* in ms */
557 unsigned int ramp_delay_value; 558 unsigned int ramp_delay_value;
559 unsigned int offset_cncl_path;
560 unsigned int check_defaults:1;
561 unsigned int reset_registers:1;
558 unsigned int hs_extmute:1; 562 unsigned int hs_extmute:1;
559 void (*set_hs_extmute)(int mute); 563 void (*set_hs_extmute)(int mute);
560}; 564};
diff --git a/include/sound/core.h b/include/sound/core.h
index df26ebbfa9c6..1fa2407c966f 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -177,7 +177,7 @@ int snd_power_wait(struct snd_card *card, unsigned int power_state);
177#define snd_power_lock(card) do { (void)(card); } while (0) 177#define snd_power_lock(card) do { (void)(card); } while (0)
178#define snd_power_unlock(card) do { (void)(card); } while (0) 178#define snd_power_unlock(card) do { (void)(card); } while (0)
179static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; } 179static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
180#define snd_power_get_state(card) SNDRV_CTL_POWER_D0 180#define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; })
181#define snd_power_change_state(card, state) do { (void)(card); } while (0) 181#define snd_power_change_state(card, state) do { (void)(card); } while (0)
182 182
183#endif /* CONFIG_PM */ 183#endif /* CONFIG_PM */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 7dc97d12253c..4f865df42f0f 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -438,6 +438,8 @@
438#define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */ 438#define CCCA_CURRADDR_MASK 0x00ffffff /* Current address of the selected channel */
439#define CCCA_CURRADDR 0x18000008 439#define CCCA_CURRADDR 0x18000008
440 440
441/* undefine CCR to avoid conflict with the definition for SH */
442#undef CCR
441#define CCR 0x09 /* Cache control register */ 443#define CCR 0x09 /* Cache control register */
442#define CCR_CACHEINVALIDSIZE 0x07190009 444#define CCR_CACHEINVALIDSIZE 0x07190009
443#define CCR_CACHEINVALIDSIZE_MASK 0xfe000000 /* Number of invalid samples cache for this channel */ 445#define CCR_CACHEINVALIDSIZE_MASK 0xfe000000 /* Number of invalid samples cache for this channel */
diff --git a/include/sound/jack.h b/include/sound/jack.h
index d90b9fa32707..c140fc7cbd3f 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -47,6 +47,9 @@ enum snd_jack_types {
47 SND_JACK_BTN_0 = 0x4000, 47 SND_JACK_BTN_0 = 0x4000,
48 SND_JACK_BTN_1 = 0x2000, 48 SND_JACK_BTN_1 = 0x2000,
49 SND_JACK_BTN_2 = 0x1000, 49 SND_JACK_BTN_2 = 0x1000,
50 SND_JACK_BTN_3 = 0x0800,
51 SND_JACK_BTN_4 = 0x0400,
52 SND_JACK_BTN_5 = 0x0200,
50}; 53};
51 54
52struct snd_jack { 55struct snd_jack {
@@ -55,7 +58,7 @@ struct snd_jack {
55 int type; 58 int type;
56 const char *id; 59 const char *id;
57 char name[100]; 60 char name[100];
58 unsigned int key[3]; /* Keep in sync with definitions above */ 61 unsigned int key[6]; /* Keep in sync with definitions above */
59 void *private_data; 62 void *private_data;
60 void (*private_free)(struct snd_jack *); 63 void (*private_free)(struct snd_jack *);
61}; 64};
diff --git a/include/sound/max98088.h b/include/sound/max98088.h
new file mode 100644
index 000000000000..c3ba8239182d
--- /dev/null
+++ b/include/sound/max98088.h
@@ -0,0 +1,50 @@
1/*
2 * Platform data for MAX98088
3 *
4 * Copyright 2010 Maxim Integrated Products
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 *
11 */
12
13#ifndef __SOUND_MAX98088_PDATA_H__
14#define __SOUND_MAX98088_PDATA_H__
15
16/* Equalizer filter response configuration */
17struct max98088_eq_cfg {
18 const char *name;
19 unsigned int rate;
20 u16 band1[5];
21 u16 band2[5];
22 u16 band3[5];
23 u16 band4[5];
24 u16 band5[5];
25};
26
27/* codec platform data */
28struct max98088_pdata {
29
30 /* Equalizers for DAI1 and DAI2 */
31 struct max98088_eq_cfg *eq_cfg;
32 unsigned int eq_cfgcnt;
33
34 /* Receiver output can be configured as power amplifier or LINE out */
35 /* Set receiver_mode to:
36 * 0 = amplifier output, or
37 * 1 = LINE level output
38 */
39 unsigned int receiver_mode:1;
40
41 /* Analog/digital microphone configuration:
42 * 0 = analog microphone input (normal setting)
43 * 1 = digital microphone input
44 */
45 unsigned int digmic_left_mode:1;
46 unsigned int digmic_right_mode:1;
47
48};
49
50#endif
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 85f1c6bf8566..dfd9b76b1853 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -278,6 +278,7 @@ struct snd_pcm_runtime {
278 snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */ 278 snd_pcm_uframes_t hw_ptr_base; /* Position at buffer restart */
279 snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */ 279 snd_pcm_uframes_t hw_ptr_interrupt; /* Position at interrupt time */
280 unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */ 280 unsigned long hw_ptr_jiffies; /* Time when hw_ptr is updated */
281 unsigned long hw_ptr_buffer_jiffies; /* buffer time in jiffies */
281 snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */ 282 snd_pcm_sframes_t delay; /* extra delay; typically FIFO size */
282 283
283 /* -- HW params -- */ 284 /* -- HW params -- */
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 9d51d6f35893..fa60cbda90a4 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -114,7 +114,4 @@ struct sh_fsi_platform_info {
114 int (*set_rate)(int is_porta, int rate); /* for master mode */ 114 int (*set_rate)(int is_porta, int rate); /* for master mode */
115}; 115};
116 116
117extern struct snd_soc_dai fsi_soc_dai[2];
118extern struct snd_soc_platform fsi_soc_platform;
119
120#endif /* __SOUND_FSI_H */ 117#endif /* __SOUND_FSI_H */
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 377693a14385..e7b680248006 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -91,15 +91,17 @@ struct snd_pcm_substream;
91 SNDRV_PCM_FMTBIT_S32_LE |\ 91 SNDRV_PCM_FMTBIT_S32_LE |\
92 SNDRV_PCM_FMTBIT_S32_BE) 92 SNDRV_PCM_FMTBIT_S32_BE)
93 93
94struct snd_soc_dai_ops; 94struct snd_soc_dai_driver;
95struct snd_soc_dai; 95struct snd_soc_dai;
96struct snd_ac97_bus_ops; 96struct snd_ac97_bus_ops;
97 97
98/* Digital Audio Interface registration */ 98/* Digital Audio Interface registration */
99int snd_soc_register_dai(struct snd_soc_dai *dai); 99int snd_soc_register_dai(struct device *dev,
100void snd_soc_unregister_dai(struct snd_soc_dai *dai); 100 struct snd_soc_dai_driver *dai_drv);
101int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count); 101void snd_soc_unregister_dai(struct device *dev);
102void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count); 102int snd_soc_register_dais(struct device *dev,
103 struct snd_soc_dai_driver *dai_drv, size_t count);
104void snd_soc_unregister_dais(struct device *dev, size_t count);
103 105
104/* Digital Audio Interface clocking API.*/ 106/* Digital Audio Interface clocking API.*/
105int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 107int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
@@ -126,16 +128,6 @@ int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
126/* Digital Audio Interface mute */ 128/* Digital Audio Interface mute */
127int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); 129int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
128 130
129/*
130 * Digital Audio Interface.
131 *
132 * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
133 * operations and capabilities. Codec and platform drivers will register this
134 * structure for every DAI they have.
135 *
136 * This structure covers the clocking, formating and ALSA operations for each
137 * interface.
138 */
139struct snd_soc_dai_ops { 131struct snd_soc_dai_ops {
140 /* 132 /*
141 * DAI clocking configuration, all optional. 133 * DAI clocking configuration, all optional.
@@ -191,24 +183,24 @@ struct snd_soc_dai_ops {
191}; 183};
192 184
193/* 185/*
194 * Digital Audio Interface runtime data. 186 * Digital Audio Interface Driver.
195 * 187 *
196 * Holds runtime data for a DAI. 188 * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97
189 * operations and capabilities. Codec and platform drivers will register this
190 * structure for every DAI they have.
191 *
192 * This structure covers the clocking, formating and ALSA operations for each
193 * interface.
197 */ 194 */
198struct snd_soc_dai { 195struct snd_soc_dai_driver {
199 /* DAI description */ 196 /* DAI description */
200 char *name; 197 const char *name;
201 unsigned int id; 198 unsigned int id;
202 int ac97_control; 199 int ac97_control;
203 200
204 struct device *dev; 201 /* DAI driver callbacks */
205 void *ac97_pdata; /* platform_data for the ac97 codec */ 202 int (*probe)(struct snd_soc_dai *dai);
206 203 int (*remove)(struct snd_soc_dai *dai);
207 /* DAI callbacks */
208 int (*probe)(struct platform_device *pdev,
209 struct snd_soc_dai *dai);
210 void (*remove)(struct platform_device *pdev,
211 struct snd_soc_dai *dai);
212 int (*suspend)(struct snd_soc_dai *dai); 204 int (*suspend)(struct snd_soc_dai *dai);
213 int (*resume)(struct snd_soc_dai *dai); 205 int (*resume)(struct snd_soc_dai *dai);
214 206
@@ -219,26 +211,51 @@ struct snd_soc_dai {
219 struct snd_soc_pcm_stream capture; 211 struct snd_soc_pcm_stream capture;
220 struct snd_soc_pcm_stream playback; 212 struct snd_soc_pcm_stream playback;
221 unsigned int symmetric_rates:1; 213 unsigned int symmetric_rates:1;
214};
215
216/*
217 * Digital Audio Interface runtime data.
218 *
219 * Holds runtime data for a DAI.
220 */
221struct snd_soc_dai {
222 const char *name;
223 int id;
224 struct device *dev;
225 void *ac97_pdata; /* platform_data for the ac97 codec */
226
227 /* driver ops */
228 struct snd_soc_dai_driver *driver;
222 229
223 /* DAI runtime info */ 230 /* DAI runtime info */
224 struct snd_soc_codec *codec; 231 unsigned int capture_active:1; /* stream is in use */
232 unsigned int playback_active:1; /* stream is in use */
233 unsigned int symmetric_rates:1;
234 struct snd_pcm_runtime *runtime;
225 unsigned int active; 235 unsigned int active;
226 unsigned char pop_wait:1; 236 unsigned char pop_wait:1;
237 unsigned char probed:1;
227 238
228 /* DAI private data */ 239 /* DAI DMA data */
229 void *private_data; 240 void *playback_dma_data;
241 void *capture_dma_data;
230 242
231 /* parent platform */ 243 /* parent platform/codec */
232 struct snd_soc_platform *platform; 244 union {
245 struct snd_soc_platform *platform;
246 struct snd_soc_codec *codec;
247 };
248 struct snd_soc_card *card;
233 249
234 struct list_head list; 250 struct list_head list;
251 struct list_head card_list;
235}; 252};
236 253
237static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, 254static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
238 const struct snd_pcm_substream *ss) 255 const struct snd_pcm_substream *ss)
239{ 256{
240 return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 257 return (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
241 dai->playback.dma_data : dai->capture.dma_data; 258 dai->playback_dma_data : dai->capture_dma_data;
242} 259}
243 260
244static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai, 261static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
@@ -246,9 +263,20 @@ static inline void snd_soc_dai_set_dma_data(struct snd_soc_dai *dai,
246 void *data) 263 void *data)
247{ 264{
248 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK) 265 if (ss->stream == SNDRV_PCM_STREAM_PLAYBACK)
249 dai->playback.dma_data = data; 266 dai->playback_dma_data = data;
250 else 267 else
251 dai->capture.dma_data = data; 268 dai->capture_dma_data = data;
269}
270
271static inline void snd_soc_dai_set_drvdata(struct snd_soc_dai *dai,
272 void *data)
273{
274 dev_set_drvdata(dai->dev, data);
275}
276
277static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai)
278{
279 return dev_get_drvdata(dai->dev);
252} 280}
253 281
254#endif 282#endif
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index c5d9987bc897..8fd3b41b763f 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -172,9 +172,19 @@
172#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \ 172#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
173{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ 173{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
174 .reg = wreg, .shift = wshift, .invert = winvert } 174 .reg = wreg, .shift = wshift, .invert = winvert }
175#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
176 wevent, wflags) \
177{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
178 .reg = wreg, .shift = wshift, .invert = winvert, \
179 .event = wevent, .event_flags = wflags }
175#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \ 180#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
176{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ 181{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
177 .reg = wreg, .shift = wshift, .invert = winvert } 182 .reg = wreg, .shift = wshift, .invert = winvert }
183#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
184 wevent, wflags) \
185{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
186 .reg = wreg, .shift = wshift, .invert = winvert, \
187 .event = wevent, .event_flags = wflags }
178#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ 188#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
179{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ 189{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
180 .shift = wshift, .invert = winvert} 190 .shift = wshift, .invert = winvert}
@@ -322,14 +332,14 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
322 332
323/* dapm path setup */ 333/* dapm path setup */
324int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); 334int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
325void snd_soc_dapm_free(struct snd_soc_device *socdev); 335void snd_soc_dapm_free(struct snd_soc_codec *codec);
326int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, 336int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
327 const struct snd_soc_dapm_route *route, int num); 337 const struct snd_soc_dapm_route *route, int num);
328 338
329/* dapm events */ 339/* dapm events */
330int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream, 340int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
331 int event); 341 const char *stream, int event);
332void snd_soc_dapm_shutdown(struct snd_soc_device *socdev); 342void snd_soc_dapm_shutdown(struct snd_soc_card *card);
333 343
334/* dapm sys fs - used by the core */ 344/* dapm sys fs - used by the core */
335int snd_soc_dapm_sys_add(struct device *dev); 345int snd_soc_dapm_sys_add(struct device *dev);
diff --git a/include/sound/soc-of-simple.h b/include/sound/soc-of-simple.h
deleted file mode 100644
index a064e1934a56..000000000000
--- a/include/sound/soc-of-simple.h
+++ /dev/null
@@ -1,25 +0,0 @@
1/*
2 * OF helpers for ALSA SoC
3 *
4 * Copyright (C) 2008, Secret Lab Technologies Ltd.
5 */
6
7#ifndef _INCLUDE_SOC_OF_H_
8#define _INCLUDE_SOC_OF_H_
9
10#if defined(CONFIG_SND_SOC_OF_SIMPLE) || defined(CONFIG_SND_SOC_OF_SIMPLE_MODULE)
11
12#include <linux/of.h>
13#include <sound/soc.h>
14
15int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
16 void *codec_data, struct snd_soc_dai *dai,
17 struct device_node *node);
18
19int of_snd_soc_register_platform(struct snd_soc_platform *platform,
20 struct device_node *node,
21 struct snd_soc_dai *cpu_dai);
22
23#endif
24
25#endif /* _INCLUDE_SOC_OF_H_ */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 65e9d03ed4f5..5c3bce83f28a 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -214,10 +214,10 @@
214 * @OFF: Power Off. No restrictions on transition times. 214 * @OFF: Power Off. No restrictions on transition times.
215 */ 215 */
216enum snd_soc_bias_level { 216enum snd_soc_bias_level {
217 SND_SOC_BIAS_ON,
218 SND_SOC_BIAS_PREPARE,
219 SND_SOC_BIAS_STANDBY,
220 SND_SOC_BIAS_OFF, 217 SND_SOC_BIAS_OFF,
218 SND_SOC_BIAS_STANDBY,
219 SND_SOC_BIAS_PREPARE,
220 SND_SOC_BIAS_ON,
221}; 221};
222 222
223struct snd_jack; 223struct snd_jack;
@@ -228,13 +228,17 @@ struct snd_soc_ops;
228struct snd_soc_dai_mode; 228struct snd_soc_dai_mode;
229struct snd_soc_pcm_runtime; 229struct snd_soc_pcm_runtime;
230struct snd_soc_dai; 230struct snd_soc_dai;
231struct snd_soc_dai_driver;
231struct snd_soc_platform; 232struct snd_soc_platform;
232struct snd_soc_dai_link; 233struct snd_soc_dai_link;
234struct snd_soc_platform_driver;
233struct snd_soc_codec; 235struct snd_soc_codec;
236struct snd_soc_codec_driver;
234struct soc_enum; 237struct soc_enum;
235struct snd_soc_ac97_ops; 238struct snd_soc_ac97_ops;
236struct snd_soc_jack; 239struct snd_soc_jack;
237struct snd_soc_jack_pin; 240struct snd_soc_jack_pin;
241
238#ifdef CONFIG_GPIOLIB 242#ifdef CONFIG_GPIOLIB
239struct snd_soc_jack_gpio; 243struct snd_soc_jack_gpio;
240#endif 244#endif
@@ -249,19 +253,18 @@ enum snd_soc_control_type {
249 SND_SOC_SPI, 253 SND_SOC_SPI,
250}; 254};
251 255
252int snd_soc_register_platform(struct snd_soc_platform *platform); 256int snd_soc_register_platform(struct device *dev,
253void snd_soc_unregister_platform(struct snd_soc_platform *platform); 257 struct snd_soc_platform_driver *platform_drv);
254int snd_soc_register_codec(struct snd_soc_codec *codec); 258void snd_soc_unregister_platform(struct device *dev);
255void snd_soc_unregister_codec(struct snd_soc_codec *codec); 259int snd_soc_register_codec(struct device *dev,
260 struct snd_soc_codec_driver *codec_drv,
261 struct snd_soc_dai_driver *dai_drv, int num_dai);
262void snd_soc_unregister_codec(struct device *dev);
256int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); 263int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg);
257int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, 264int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
258 int addr_bits, int data_bits, 265 int addr_bits, int data_bits,
259 enum snd_soc_control_type control); 266 enum snd_soc_control_type control);
260 267
261/* pcm <-> DAI connect */
262void snd_soc_free_pcms(struct snd_soc_device *socdev);
263int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
264
265/* Utility functions to get clock rates from various things */ 268/* Utility functions to get clock rates from various things */
266int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); 269int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots);
267int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); 270int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params);
@@ -273,7 +276,7 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
273 const struct snd_pcm_hardware *hw); 276 const struct snd_pcm_hardware *hw);
274 277
275/* Jack reporting */ 278/* Jack reporting */
276int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, 279int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
277 struct snd_soc_jack *jack); 280 struct snd_soc_jack *jack);
278void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); 281void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
279int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, 282int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
@@ -382,7 +385,7 @@ struct snd_soc_jack_gpio {
382 int invert; 385 int invert;
383 int debounce_time; 386 int debounce_time;
384 struct snd_soc_jack *jack; 387 struct snd_soc_jack *jack;
385 struct work_struct work; 388 struct delayed_work work;
386 389
387 int (*jack_status_check)(void); 390 int (*jack_status_check)(void);
388}; 391};
@@ -390,7 +393,7 @@ struct snd_soc_jack_gpio {
390 393
391struct snd_soc_jack { 394struct snd_soc_jack {
392 struct snd_jack *jack; 395 struct snd_jack *jack;
393 struct snd_soc_card *card; 396 struct snd_soc_codec *codec;
394 struct list_head pins; 397 struct list_head pins;
395 int status; 398 int status;
396 struct blocking_notifier_head notifier; 399 struct blocking_notifier_head notifier;
@@ -398,15 +401,13 @@ struct snd_soc_jack {
398 401
399/* SoC PCM stream information */ 402/* SoC PCM stream information */
400struct snd_soc_pcm_stream { 403struct snd_soc_pcm_stream {
401 char *stream_name; 404 const char *stream_name;
402 u64 formats; /* SNDRV_PCM_FMTBIT_* */ 405 u64 formats; /* SNDRV_PCM_FMTBIT_* */
403 unsigned int rates; /* SNDRV_PCM_RATE_* */ 406 unsigned int rates; /* SNDRV_PCM_RATE_* */
404 unsigned int rate_min; /* min rate */ 407 unsigned int rate_min; /* min rate */
405 unsigned int rate_max; /* max rate */ 408 unsigned int rate_max; /* max rate */
406 unsigned int channels_min; /* min channels */ 409 unsigned int channels_min; /* min channels */
407 unsigned int channels_max; /* max channels */ 410 unsigned int channels_max; /* max channels */
408 unsigned int active; /* stream is in use */
409 void *dma_data; /* used by platform code */
410}; 411};
411 412
412/* SoC audio ops */ 413/* SoC audio ops */
@@ -419,44 +420,36 @@ struct snd_soc_ops {
419 int (*trigger)(struct snd_pcm_substream *, int); 420 int (*trigger)(struct snd_pcm_substream *, int);
420}; 421};
421 422
422/* SoC Audio Codec */ 423/* SoC Audio Codec device */
423struct snd_soc_codec { 424struct snd_soc_codec {
424 char *name; 425 const char *name;
425 struct module *owner; 426 int id;
426 struct mutex mutex;
427 struct device *dev; 427 struct device *dev;
428 struct snd_soc_device *socdev; 428 struct snd_soc_codec_driver *driver;
429 429
430 struct mutex mutex;
431 struct snd_soc_card *card;
430 struct list_head list; 432 struct list_head list;
431 433 struct list_head card_list;
432 /* callbacks */ 434 int num_dai;
433 int (*set_bias_level)(struct snd_soc_codec *,
434 enum snd_soc_bias_level level);
435 435
436 /* runtime */ 436 /* runtime */
437 struct snd_card *card;
438 struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ 437 struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
439 unsigned int active; 438 unsigned int active;
440 unsigned int pcm_devs; 439 unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
441 void *drvdata; 440 unsigned int cache_only:1; /* Suppress writes to hardware */
441 unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
442 unsigned int suspended:1; /* Codec is in suspend PM state */
443 unsigned int probed:1; /* Codec has been probed */
444 unsigned int ac97_registered:1; /* Codec has been AC97 registered */
445 unsigned int ac97_created:1; /* Codec has been created by SoC */
446 unsigned int sysfs_registered:1; /* codec has been sysfs registered */
442 447
443 /* codec IO */ 448 /* codec IO */
444 void *control_data; /* codec control (i2c/3wire) data */ 449 void *control_data; /* codec control (i2c/3wire) data */
445 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
446 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
447 int (*display_register)(struct snd_soc_codec *, char *,
448 size_t, unsigned int);
449 int (*volatile_register)(unsigned int);
450 int (*readable_register)(unsigned int);
451 hw_write_t hw_write; 450 hw_write_t hw_write;
452 unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int); 451 unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int);
453 void *reg_cache; 452 void *reg_cache;
454 short reg_cache_size;
455 short reg_cache_step;
456
457 unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */
458 unsigned int cache_only:1; /* Suppress writes to hardware */
459 unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
460 453
461 /* dapm */ 454 /* dapm */
462 u32 pop_time; 455 u32 pop_time;
@@ -466,10 +459,6 @@ struct snd_soc_codec {
466 enum snd_soc_bias_level suspend_bias_level; 459 enum snd_soc_bias_level suspend_bias_level;
467 struct delayed_work delayed_work; 460 struct delayed_work delayed_work;
468 461
469 /* codec DAI's */
470 struct snd_soc_dai *dai;
471 unsigned int num_dai;
472
473#ifdef CONFIG_DEBUG_FS 462#ifdef CONFIG_DEBUG_FS
474 struct dentry *debugfs_codec_root; 463 struct dentry *debugfs_codec_root;
475 struct dentry *debugfs_reg; 464 struct dentry *debugfs_reg;
@@ -478,23 +467,40 @@ struct snd_soc_codec {
478#endif 467#endif
479}; 468};
480 469
481/* codec device */ 470/* codec driver */
482struct snd_soc_codec_device { 471struct snd_soc_codec_driver {
483 int (*probe)(struct platform_device *pdev); 472
484 int (*remove)(struct platform_device *pdev); 473 /* driver ops */
485 int (*suspend)(struct platform_device *pdev, pm_message_t state); 474 int (*probe)(struct snd_soc_codec *);
486 int (*resume)(struct platform_device *pdev); 475 int (*remove)(struct snd_soc_codec *);
476 int (*suspend)(struct snd_soc_codec *,
477 pm_message_t state);
478 int (*resume)(struct snd_soc_codec *);
479
480 /* codec IO */
481 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
482 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
483 int (*display_register)(struct snd_soc_codec *, char *,
484 size_t, unsigned int);
485 int (*volatile_register)(unsigned int);
486 int (*readable_register)(unsigned int);
487 short reg_cache_size;
488 short reg_cache_step;
489 short reg_word_size;
490 const void *reg_cache_default;
491
492 /* codec bias level */
493 int (*set_bias_level)(struct snd_soc_codec *,
494 enum snd_soc_bias_level level);
487}; 495};
488 496
489/* SoC platform interface */ 497/* SoC platform interface */
490struct snd_soc_platform { 498struct snd_soc_platform_driver {
491 char *name;
492 struct list_head list;
493 499
494 int (*probe)(struct platform_device *pdev); 500 int (*probe)(struct snd_soc_platform *);
495 int (*remove)(struct platform_device *pdev); 501 int (*remove)(struct snd_soc_platform *);
496 int (*suspend)(struct snd_soc_dai_link *dai_link); 502 int (*suspend)(struct snd_soc_dai *dai);
497 int (*resume)(struct snd_soc_dai_link *dai_link); 503 int (*resume)(struct snd_soc_dai *dai);
498 504
499 /* pcm creation and destruction */ 505 /* pcm creation and destruction */
500 int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, 506 int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
@@ -509,23 +515,31 @@ struct snd_soc_platform {
509 struct snd_soc_dai *); 515 struct snd_soc_dai *);
510 516
511 /* platform stream ops */ 517 /* platform stream ops */
512 struct snd_pcm_ops *pcm_ops; 518 struct snd_pcm_ops *ops;
513}; 519};
514 520
515/* SoC machine DAI configuration, glues a codec and cpu DAI together */ 521struct snd_soc_platform {
516struct snd_soc_dai_link { 522 const char *name;
517 char *name; /* Codec name */ 523 int id;
518 char *stream_name; /* Stream name */ 524 struct device *dev;
525 struct snd_soc_platform_driver *driver;
519 526
520 /* DAI */ 527 unsigned int suspended:1; /* platform is suspended */
521 struct snd_soc_dai *codec_dai; 528 unsigned int probed:1;
522 struct snd_soc_dai *cpu_dai;
523 529
524 /* machine stream operations */ 530 struct snd_soc_card *card;
525 struct snd_soc_ops *ops; 531 struct list_head list;
532 struct list_head card_list;
533};
526 534
527 /* codec/machine specific init - e.g. add machine controls */ 535struct snd_soc_dai_link {
528 int (*init)(struct snd_soc_codec *codec); 536 /* config - must be set by machine driver */
537 const char *name; /* Codec name */
538 const char *stream_name; /* Stream name */
539 const char *codec_name; /* for multi-codec */
540 const char *platform_name; /* for multi-platform */
541 const char *cpu_dai_name;
542 const char *codec_dai_name;
529 543
530 /* Keep DAI active over suspend */ 544 /* Keep DAI active over suspend */
531 unsigned int ignore_suspend:1; 545 unsigned int ignore_suspend:1;
@@ -533,21 +547,24 @@ struct snd_soc_dai_link {
533 /* Symmetry requirements */ 547 /* Symmetry requirements */
534 unsigned int symmetric_rates:1; 548 unsigned int symmetric_rates:1;
535 549
536 /* Symmetry data - only valid if symmetry is being enforced */ 550 /* codec/machine specific init - e.g. add machine controls */
537 unsigned int rate; 551 int (*init)(struct snd_soc_pcm_runtime *rtd);
538 552
539 /* DAI pcm */ 553 /* machine stream operations */
540 struct snd_pcm *pcm; 554 struct snd_soc_ops *ops;
541}; 555};
542 556
543/* SoC card */ 557/* SoC card */
544struct snd_soc_card { 558struct snd_soc_card {
545 char *name; 559 const char *name;
546 struct device *dev; 560 struct device *dev;
561 struct snd_card *snd_card;
562 struct module *owner;
547 563
548 struct list_head list; 564 struct list_head list;
565 struct mutex mutex;
549 566
550 int instantiated; 567 bool instantiated;
551 568
552 int (*probe)(struct platform_device *pdev); 569 int (*probe)(struct platform_device *pdev);
553 int (*remove)(struct platform_device *pdev); 570 int (*remove)(struct platform_device *pdev);
@@ -568,28 +585,38 @@ struct snd_soc_card {
568 /* CPU <--> Codec DAI links */ 585 /* CPU <--> Codec DAI links */
569 struct snd_soc_dai_link *dai_link; 586 struct snd_soc_dai_link *dai_link;
570 int num_links; 587 int num_links;
588 struct snd_soc_pcm_runtime *rtd;
589 int num_rtd;
571 590
572 struct snd_soc_device *socdev;
573
574 struct snd_soc_codec *codec;
575
576 struct snd_soc_platform *platform;
577 struct delayed_work delayed_work;
578 struct work_struct deferred_resume_work; 591 struct work_struct deferred_resume_work;
592
593 /* lists of probed devices belonging to this card */
594 struct list_head codec_dev_list;
595 struct list_head platform_dev_list;
596 struct list_head dai_dev_list;
579}; 597};
580 598
581/* SoC Device - the audio subsystem */ 599/* SoC machine DAI configuration, glues a codec and cpu DAI together */
582struct snd_soc_device { 600struct snd_soc_pcm_runtime {
583 struct device *dev; 601 struct device dev;
584 struct snd_soc_card *card; 602 struct snd_soc_card *card;
585 struct snd_soc_codec_device *codec_dev; 603 struct snd_soc_dai_link *dai_link;
586 void *codec_data; 604
587}; 605 unsigned int complete:1;
606 unsigned int dev_registered:1;
607
608 /* Symmetry data - only valid if symmetry is being enforced */
609 unsigned int rate;
610 long pmdown_time;
588 611
589/* runtime channel data */ 612 /* runtime devices */
590struct snd_soc_pcm_runtime { 613 struct snd_pcm *pcm;
591 struct snd_soc_dai_link *dai; 614 struct snd_soc_codec *codec;
592 struct snd_soc_device *socdev; 615 struct snd_soc_platform *platform;
616 struct snd_soc_dai *codec_dai;
617 struct snd_soc_dai *cpu_dai;
618
619 struct delayed_work delayed_work;
593}; 620};
594 621
595/* mixer control */ 622/* mixer control */
@@ -615,24 +642,48 @@ struct soc_enum {
615static inline unsigned int snd_soc_read(struct snd_soc_codec *codec, 642static inline unsigned int snd_soc_read(struct snd_soc_codec *codec,
616 unsigned int reg) 643 unsigned int reg)
617{ 644{
618 return codec->read(codec, reg); 645 return codec->driver->read(codec, reg);
619} 646}
620 647
621static inline unsigned int snd_soc_write(struct snd_soc_codec *codec, 648static inline unsigned int snd_soc_write(struct snd_soc_codec *codec,
622 unsigned int reg, unsigned int val) 649 unsigned int reg, unsigned int val)
623{ 650{
624 return codec->write(codec, reg, val); 651 return codec->driver->write(codec, reg, val);
625} 652}
626 653
654/* device driver data */
655
627static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec, 656static inline void snd_soc_codec_set_drvdata(struct snd_soc_codec *codec,
628 void *data) 657 void *data)
629{ 658{
630 codec->drvdata = data; 659 dev_set_drvdata(codec->dev, data);
631} 660}
632 661
633static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec) 662static inline void *snd_soc_codec_get_drvdata(struct snd_soc_codec *codec)
634{ 663{
635 return codec->drvdata; 664 return dev_get_drvdata(codec->dev);
665}
666
667static inline void snd_soc_platform_set_drvdata(struct snd_soc_platform *platform,
668 void *data)
669{
670 dev_set_drvdata(platform->dev, data);
671}
672
673static inline void *snd_soc_platform_get_drvdata(struct snd_soc_platform *platform)
674{
675 return dev_get_drvdata(platform->dev);
676}
677
678static inline void snd_soc_pcm_set_drvdata(struct snd_soc_pcm_runtime *rtd,
679 void *data)
680{
681 dev_set_drvdata(&rtd->dev, data);
682}
683
684static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
685{
686 return dev_get_drvdata(&rtd->dev);
636} 687}
637 688
638#include <sound/soc-dai.h> 689#include <sound/soc-dai.h>
diff --git a/include/sound/tlv.h b/include/sound/tlv.h
index 9fd5b19ccf5c..7067e2dfb0b9 100644
--- a/include/sound/tlv.h
+++ b/include/sound/tlv.h
@@ -38,9 +38,11 @@
38#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */ 38#define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */
39#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */ 39#define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */
40 40
41#define TLV_DB_SCALE_MASK 0xffff
42#define TLV_DB_SCALE_MUTE 0x10000
41#define TLV_DB_SCALE_ITEM(min, step, mute) \ 43#define TLV_DB_SCALE_ITEM(min, step, mute) \
42 SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \ 44 SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \
43 (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0) 45 (min), ((step) & TLV_DB_SCALE_MASK) | ((mute) ? TLV_DB_SCALE_MUTE : 0)
44#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ 46#define DECLARE_TLV_DB_SCALE(name, min, step, mute) \
45 unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } 47 unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) }
46 48
diff --git a/include/sound/tlv320aic3x.h b/include/sound/tlv320aic3x.h
index b1a5f34e5cfa..99e0308bf2c2 100644
--- a/include/sound/tlv320aic3x.h
+++ b/include/sound/tlv320aic3x.h
@@ -10,8 +10,49 @@
10#ifndef __TLV320AIC3x_H__ 10#ifndef __TLV320AIC3x_H__
11#define __TLV320AIC3x_H__ 11#define __TLV320AIC3x_H__
12 12
13/* GPIO API */
14enum {
15 AIC3X_GPIO1_FUNC_DISABLED = 0,
16 AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1,
17 AIC3X_GPIO1_FUNC_CLOCK_MUX = 2,
18 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3,
19 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4,
20 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5,
21 AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6,
22 AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7,
23 AIC3X_GPIO1_FUNC_INPUT = 8,
24 AIC3X_GPIO1_FUNC_OUTPUT = 9,
25 AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10,
26 AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11,
27 AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12,
28 AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13,
29 AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14,
30 AIC3X_GPIO1_FUNC_ALL_IRQ = 16
31};
32
33enum {
34 AIC3X_GPIO2_FUNC_DISABLED = 0,
35 AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2,
36 AIC3X_GPIO2_FUNC_INPUT = 3,
37 AIC3X_GPIO2_FUNC_OUTPUT = 4,
38 AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5,
39 AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8,
40 AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9,
41 AIC3X_GPIO2_FUNC_ALL_IRQ = 10,
42 AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11,
43 AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12,
44 AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13,
45 AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14,
46 AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15
47};
48
49struct aic3x_setup_data {
50 unsigned int gpio_func[2];
51};
52
13struct aic3x_pdata { 53struct aic3x_pdata {
14 int gpio_reset; /* < 0 if not used */ 54 int gpio_reset; /* < 0 if not used */
55 struct aic3x_setup_data *setup;
15}; 56};
16 57
17#endif \ No newline at end of file 58#endif
diff --git a/include/sound/wm8962.h b/include/sound/wm8962.h
new file mode 100644
index 000000000000..2b5306c503fb
--- /dev/null
+++ b/include/sound/wm8962.h
@@ -0,0 +1,32 @@
1/*
2 * wm8962.h -- WM8962 Soc Audio driver platform data
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _WM8962_PDATA_H
10#define _WM8962_PDATA_H
11
12#define WM8962_MAX_GPIO 6
13
14/* Use to set GPIO default values to zero */
15#define WM8962_GPIO_SET 0x10000
16
17struct wm8962_pdata {
18 int gpio_base;
19 u32 gpio_init[WM8962_MAX_GPIO];
20
21 /* Setup for microphone detection, raw value to be written to
22 * R48(0x30) - only microphone related bits will be updated.
23 * Detection may be enabled here for use with signals brought
24 * out on the GPIOs. */
25 u32 mic_cfg;
26
27 bool irq_active_low;
28
29 bool spk_mono; /* Speaker outputs tied together as mono */
30};
31
32#endif
diff --git a/include/video/sh_mobile_hdmi.h b/include/video/sh_mobile_hdmi.h
index 577cf18cce89..1e1aa54ab2e4 100644
--- a/include/video/sh_mobile_hdmi.h
+++ b/include/video/sh_mobile_hdmi.h
@@ -14,9 +14,25 @@
14struct sh_mobile_lcdc_chan_cfg; 14struct sh_mobile_lcdc_chan_cfg;
15struct device; 15struct device;
16 16
17/*
18 * flags format
19 *
20 * 0x0000000A
21 *
22 * A: Audio source select
23 */
24
25/* Audio source select */
26#define HDMI_SND_SRC_MASK (0xF << 0)
27#define HDMI_SND_SRC_I2S (0 << 0) /* default */
28#define HDMI_SND_SRC_SPDIF (1 << 0)
29#define HDMI_SND_SRC_DSD (2 << 0)
30#define HDMI_SND_SRC_HBR (3 << 0)
31
17struct sh_mobile_hdmi_info { 32struct sh_mobile_hdmi_info {
18 struct sh_mobile_lcdc_chan_cfg *lcd_chan; 33 struct sh_mobile_lcdc_chan_cfg *lcd_chan;
19 struct device *lcd_dev; 34 struct device *lcd_dev;
35 unsigned int flags;
20}; 36};
21 37
22#endif 38#endif
diff --git a/sound/core/init.c b/sound/core/init.c
index f7c3df8b521b..57b792e2439a 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -604,11 +604,16 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
604 return -EEXIST; 604 return -EEXIST;
605 } 605 }
606 for (idx = 0; idx < snd_ecards_limit; idx++) { 606 for (idx = 0; idx < snd_ecards_limit; idx++) {
607 if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) 607 if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
608 goto __exist; 608 if (card == snd_cards[idx])
609 goto __ok;
610 else
611 goto __exist;
612 }
609 } 613 }
610 strcpy(card->id, buf1); 614 strcpy(card->id, buf1);
611 snd_info_card_id_change(card); 615 snd_info_card_id_change(card);
616__ok:
612 mutex_unlock(&snd_card_mutex); 617 mutex_unlock(&snd_card_mutex);
613 618
614 return count; 619 return count;
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index f50ebf20df96..822dd56993ca 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -77,7 +77,7 @@ static int snd_mixer_oss_release(struct inode *inode, struct file *file)
77 struct snd_mixer_oss_file *fmixer; 77 struct snd_mixer_oss_file *fmixer;
78 78
79 if (file->private_data) { 79 if (file->private_data) {
80 fmixer = (struct snd_mixer_oss_file *) file->private_data; 80 fmixer = file->private_data;
81 module_put(fmixer->card->module); 81 module_put(fmixer->card->module);
82 snd_card_file_remove(fmixer->card, file); 82 snd_card_file_remove(fmixer->card, file);
83 kfree(fmixer); 83 kfree(fmixer);
@@ -368,7 +368,7 @@ static int snd_mixer_oss_ioctl1(struct snd_mixer_oss_file *fmixer, unsigned int
368 368
369static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 369static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
370{ 370{
371 return snd_mixer_oss_ioctl1((struct snd_mixer_oss_file *) file->private_data, cmd, arg); 371 return snd_mixer_oss_ioctl1(file->private_data, cmd, arg);
372} 372}
373 373
374int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg) 374int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg)
@@ -582,7 +582,7 @@ static int snd_mixer_oss_get_volume1(struct snd_mixer_oss_file *fmixer,
582 struct snd_mixer_oss_slot *pslot, 582 struct snd_mixer_oss_slot *pslot,
583 int *left, int *right) 583 int *left, int *right)
584{ 584{
585 struct slot *slot = (struct slot *)pslot->private_data; 585 struct slot *slot = pslot->private_data;
586 586
587 *left = *right = 100; 587 *left = *right = 100;
588 if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) { 588 if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
@@ -618,8 +618,10 @@ static void snd_mixer_oss_put_volume1_vol(struct snd_mixer_oss_file *fmixer,
618 if (numid == ID_UNKNOWN) 618 if (numid == ID_UNKNOWN)
619 return; 619 return;
620 down_read(&card->controls_rwsem); 620 down_read(&card->controls_rwsem);
621 if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) 621 if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
622 up_read(&card->controls_rwsem);
622 return; 623 return;
624 }
623 uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); 625 uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
624 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); 626 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
625 if (uinfo == NULL || uctl == NULL) 627 if (uinfo == NULL || uctl == NULL)
@@ -658,7 +660,7 @@ static void snd_mixer_oss_put_volume1_sw(struct snd_mixer_oss_file *fmixer,
658 return; 660 return;
659 down_read(&card->controls_rwsem); 661 down_read(&card->controls_rwsem);
660 if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { 662 if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) {
661 up_read(&fmixer->card->controls_rwsem); 663 up_read(&card->controls_rwsem);
662 return; 664 return;
663 } 665 }
664 uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); 666 uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL);
@@ -691,7 +693,7 @@ static int snd_mixer_oss_put_volume1(struct snd_mixer_oss_file *fmixer,
691 struct snd_mixer_oss_slot *pslot, 693 struct snd_mixer_oss_slot *pslot,
692 int left, int right) 694 int left, int right)
693{ 695{
694 struct slot *slot = (struct slot *)pslot->private_data; 696 struct slot *slot = pslot->private_data;
695 697
696 if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) { 698 if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) {
697 snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right); 699 snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right);
@@ -740,7 +742,7 @@ static int snd_mixer_oss_get_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
740 struct snd_mixer_oss_slot *pslot, 742 struct snd_mixer_oss_slot *pslot,
741 int *active) 743 int *active)
742{ 744{
743 struct slot *slot = (struct slot *)pslot->private_data; 745 struct slot *slot = pslot->private_data;
744 int left, right; 746 int left, right;
745 747
746 left = right = 1; 748 left = right = 1;
@@ -753,7 +755,7 @@ static int snd_mixer_oss_get_recsrc1_route(struct snd_mixer_oss_file *fmixer,
753 struct snd_mixer_oss_slot *pslot, 755 struct snd_mixer_oss_slot *pslot,
754 int *active) 756 int *active)
755{ 757{
756 struct slot *slot = (struct slot *)pslot->private_data; 758 struct slot *slot = pslot->private_data;
757 int left, right; 759 int left, right;
758 760
759 left = right = 1; 761 left = right = 1;
@@ -766,7 +768,7 @@ static int snd_mixer_oss_put_recsrc1_sw(struct snd_mixer_oss_file *fmixer,
766 struct snd_mixer_oss_slot *pslot, 768 struct snd_mixer_oss_slot *pslot,
767 int active) 769 int active)
768{ 770{
769 struct slot *slot = (struct slot *)pslot->private_data; 771 struct slot *slot = pslot->private_data;
770 772
771 snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0); 773 snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0);
772 return 0; 774 return 0;
@@ -776,7 +778,7 @@ static int snd_mixer_oss_put_recsrc1_route(struct snd_mixer_oss_file *fmixer,
776 struct snd_mixer_oss_slot *pslot, 778 struct snd_mixer_oss_slot *pslot,
777 int active) 779 int active)
778{ 780{
779 struct slot *slot = (struct slot *)pslot->private_data; 781 struct slot *slot = pslot->private_data;
780 782
781 snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1); 783 snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1);
782 return 0; 784 return 0;
@@ -797,7 +799,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
797 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); 799 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
798 if (uinfo == NULL || uctl == NULL) { 800 if (uinfo == NULL || uctl == NULL) {
799 err = -ENOMEM; 801 err = -ENOMEM;
800 goto __unlock; 802 goto __free_only;
801 } 803 }
802 down_read(&card->controls_rwsem); 804 down_read(&card->controls_rwsem);
803 kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); 805 kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
@@ -813,7 +815,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
813 if (!(mixer->mask_recsrc & (1 << idx))) 815 if (!(mixer->mask_recsrc & (1 << idx)))
814 continue; 816 continue;
815 pslot = &mixer->slots[idx]; 817 pslot = &mixer->slots[idx];
816 slot = (struct slot *)pslot->private_data; 818 slot = pslot->private_data;
817 if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE) 819 if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE)
818 continue; 820 continue;
819 if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE)) 821 if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
@@ -826,6 +828,7 @@ static int snd_mixer_oss_get_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
826 err = 0; 828 err = 0;
827 __unlock: 829 __unlock:
828 up_read(&card->controls_rwsem); 830 up_read(&card->controls_rwsem);
831 __free_only:
829 kfree(uctl); 832 kfree(uctl);
830 kfree(uinfo); 833 kfree(uinfo);
831 return err; 834 return err;
@@ -847,7 +850,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
847 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); 850 uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
848 if (uinfo == NULL || uctl == NULL) { 851 if (uinfo == NULL || uctl == NULL) {
849 err = -ENOMEM; 852 err = -ENOMEM;
850 goto __unlock; 853 goto __free_only;
851 } 854 }
852 down_read(&card->controls_rwsem); 855 down_read(&card->controls_rwsem);
853 kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); 856 kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0);
@@ -861,7 +864,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
861 if (!(mixer->mask_recsrc & (1 << idx))) 864 if (!(mixer->mask_recsrc & (1 << idx)))
862 continue; 865 continue;
863 pslot = &mixer->slots[idx]; 866 pslot = &mixer->slots[idx];
864 slot = (struct slot *)pslot->private_data; 867 slot = pslot->private_data;
865 if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE) 868 if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE)
866 continue; 869 continue;
867 if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE)) 870 if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE))
@@ -880,6 +883,7 @@ static int snd_mixer_oss_put_recsrc2(struct snd_mixer_oss_file *fmixer, unsigned
880 err = 0; 883 err = 0;
881 __unlock: 884 __unlock:
882 up_read(&card->controls_rwsem); 885 up_read(&card->controls_rwsem);
886 __free_only:
883 kfree(uctl); 887 kfree(uctl);
884 kfree(uinfo); 888 kfree(uinfo);
885 return err; 889 return err;
@@ -925,7 +929,7 @@ static int snd_mixer_oss_build_test(struct snd_mixer_oss *mixer, struct slot *sl
925 929
926static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn) 930static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn)
927{ 931{
928 struct slot *p = (struct slot *)chn->private_data; 932 struct slot *p = chn->private_data;
929 if (p) { 933 if (p) {
930 if (p->allocated && p->assigned) { 934 if (p->allocated && p->assigned) {
931 kfree(p->assigned->name); 935 kfree(p->assigned->name);
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index ac242a377aea..6b4b1287b314 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -364,8 +364,7 @@ static void snd_pcm_stream_proc_info_read(struct snd_info_entry *entry,
364static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry, 364static void snd_pcm_substream_proc_info_read(struct snd_info_entry *entry,
365 struct snd_info_buffer *buffer) 365 struct snd_info_buffer *buffer)
366{ 366{
367 snd_pcm_proc_info_read((struct snd_pcm_substream *)entry->private_data, 367 snd_pcm_proc_info_read(entry->private_data, buffer);
368 buffer);
369} 368}
370 369
371static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, 370static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index e23e0e7ab26f..a1707cca9c66 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -334,11 +334,15 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
334 /* delta = "expected next hw_ptr" for in_interrupt != 0 */ 334 /* delta = "expected next hw_ptr" for in_interrupt != 0 */
335 delta = runtime->hw_ptr_interrupt + runtime->period_size; 335 delta = runtime->hw_ptr_interrupt + runtime->period_size;
336 if (delta > new_hw_ptr) { 336 if (delta > new_hw_ptr) {
337 hw_base += runtime->buffer_size; 337 /* check for double acknowledged interrupts */
338 if (hw_base >= runtime->boundary) 338 hdelta = jiffies - runtime->hw_ptr_jiffies;
339 hw_base = 0; 339 if (hdelta > runtime->hw_ptr_buffer_jiffies/2) {
340 new_hw_ptr = hw_base + pos; 340 hw_base += runtime->buffer_size;
341 goto __delta; 341 if (hw_base >= runtime->boundary)
342 hw_base = 0;
343 new_hw_ptr = hw_base + pos;
344 goto __delta;
345 }
342 } 346 }
343 } 347 }
344 /* new_hw_ptr might be lower than old_hw_ptr in case when */ 348 /* new_hw_ptr might be lower than old_hw_ptr in case when */
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index d4eb2ef80784..8bc7cb3db330 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -142,7 +142,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
142 142
143#ifdef RULES_DEBUG 143#ifdef RULES_DEBUG
144#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v 144#define HW_PARAM(v) [SNDRV_PCM_HW_PARAM_##v] = #v
145char *snd_pcm_hw_param_names[] = { 145static const char * const snd_pcm_hw_param_names[] = {
146 HW_PARAM(ACCESS), 146 HW_PARAM(ACCESS),
147 HW_PARAM(FORMAT), 147 HW_PARAM(FORMAT),
148 HW_PARAM(SUBFORMAT), 148 HW_PARAM(SUBFORMAT),
@@ -864,6 +864,8 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
864 struct snd_pcm_runtime *runtime = substream->runtime; 864 struct snd_pcm_runtime *runtime = substream->runtime;
865 snd_pcm_trigger_tstamp(substream); 865 snd_pcm_trigger_tstamp(substream);
866 runtime->hw_ptr_jiffies = jiffies; 866 runtime->hw_ptr_jiffies = jiffies;
867 runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) /
868 runtime->rate;
867 runtime->status->state = state; 869 runtime->status->state = state;
868 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 870 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
869 runtime->silence_size > 0) 871 runtime->silence_size > 0)
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 480c38623da8..c8961165277c 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -74,6 +74,25 @@ config SND_DUMMY
74 To compile this driver as a module, choose M here: the module 74 To compile this driver as a module, choose M here: the module
75 will be called snd-dummy. 75 will be called snd-dummy.
76 76
77config SND_ALOOP
78 tristate "Generic loopback driver (PCM)"
79 select SND_PCM
80 help
81 Say 'Y' or 'M' to include support for the PCM loopback device.
82 This module returns played samples back to the user space using
83 the standard ALSA PCM device. The devices are routed 0->1 and
84 1->0, where first number is the playback PCM device and second
85 number is the capture device. Module creates two PCM devices and
86 configured number of substreams (see the pcm_substreams module
87 parameter).
88
89 The looback device allow time sychronization with an external
90 timing source using the time shift universal control (+-20%
91 of system time).
92
93 To compile this driver as a module, choose M here: the module
94 will be called snd-aloop.
95
77config SND_VIRMIDI 96config SND_VIRMIDI
78 tristate "Virtual MIDI soundcard" 97 tristate "Virtual MIDI soundcard"
79 depends on SND_SEQUENCER 98 depends on SND_SEQUENCER
diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
index d4a07f9ff2c7..1a8440c8b138 100644
--- a/sound/drivers/Makefile
+++ b/sound/drivers/Makefile
@@ -4,6 +4,7 @@
4# 4#
5 5
6snd-dummy-objs := dummy.o 6snd-dummy-objs := dummy.o
7snd-aloop-objs := aloop.o
7snd-mtpav-objs := mtpav.o 8snd-mtpav-objs := mtpav.o
8snd-mts64-objs := mts64.o 9snd-mts64-objs := mts64.o
9snd-portman2x4-objs := portman2x4.o 10snd-portman2x4-objs := portman2x4.o
@@ -13,6 +14,7 @@ snd-ml403-ac97cr-objs := ml403-ac97cr.o pcm-indirect2.o
13 14
14# Toplevel Module Dependency 15# Toplevel Module Dependency
15obj-$(CONFIG_SND_DUMMY) += snd-dummy.o 16obj-$(CONFIG_SND_DUMMY) += snd-dummy.o
17obj-$(CONFIG_SND_ALOOP) += snd-aloop.o
16obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o 18obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o
17obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o 19obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
18obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o 20obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
new file mode 100644
index 000000000000..12b44b0b6777
--- /dev/null
+++ b/sound/drivers/aloop.c
@@ -0,0 +1,1258 @@
1/*
2 * Loopback soundcard
3 *
4 * Original code:
5 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
6 *
7 * More accurate positioning and full-duplex support:
8 * Copyright (c) Ahmet Ä°nan <ainan at mathematik.uni-freiburg.de>
9 *
10 * Major (almost complete) rewrite:
11 * Copyright (c) by Takashi Iwai <tiwai@suse.de>
12 *
13 * A next major update in 2010 (separate timers for playback and capture):
14 * Copyright (c) Jaroslav Kysela <perex@perex.cz>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32#include <linux/init.h>
33#include <linux/jiffies.h>
34#include <linux/slab.h>
35#include <linux/time.h>
36#include <linux/wait.h>
37#include <linux/moduleparam.h>
38#include <linux/platform_device.h>
39#include <sound/core.h>
40#include <sound/control.h>
41#include <sound/pcm.h>
42#include <sound/info.h>
43#include <sound/initval.h>
44
45MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
46MODULE_DESCRIPTION("A loopback soundcard");
47MODULE_LICENSE("GPL");
48MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}");
49
50#define MAX_PCM_SUBSTREAMS 8
51
52static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
53static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
54static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
55static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
56static int pcm_notify[SNDRV_CARDS];
57
58module_param_array(index, int, NULL, 0444);
59MODULE_PARM_DESC(index, "Index value for loopback soundcard.");
60module_param_array(id, charp, NULL, 0444);
61MODULE_PARM_DESC(id, "ID string for loopback soundcard.");
62module_param_array(enable, bool, NULL, 0444);
63MODULE_PARM_DESC(enable, "Enable this loopback soundcard.");
64module_param_array(pcm_substreams, int, NULL, 0444);
65MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-8) for loopback driver.");
66module_param_array(pcm_notify, int, NULL, 0444);
67MODULE_PARM_DESC(pcm_notify, "Break capture when PCM format/rate/channels changes.");
68
69#define NO_PITCH 100000
70
71struct loopback_pcm;
72
73struct loopback_cable {
74 spinlock_t lock;
75 struct loopback_pcm *streams[2];
76 struct snd_pcm_hardware hw;
77 /* flags */
78 unsigned int valid;
79 unsigned int running;
80 unsigned int pause;
81};
82
83struct loopback_setup {
84 unsigned int notify: 1;
85 unsigned int rate_shift;
86 unsigned int format;
87 unsigned int rate;
88 unsigned int channels;
89 struct snd_ctl_elem_id active_id;
90 struct snd_ctl_elem_id format_id;
91 struct snd_ctl_elem_id rate_id;
92 struct snd_ctl_elem_id channels_id;
93};
94
95struct loopback {
96 struct snd_card *card;
97 struct mutex cable_lock;
98 struct loopback_cable *cables[MAX_PCM_SUBSTREAMS][2];
99 struct snd_pcm *pcm[2];
100 struct loopback_setup setup[MAX_PCM_SUBSTREAMS][2];
101};
102
103struct loopback_pcm {
104 struct loopback *loopback;
105 struct snd_pcm_substream *substream;
106 struct loopback_cable *cable;
107 unsigned int pcm_buffer_size;
108 unsigned int buf_pos; /* position in buffer */
109 unsigned int silent_size;
110 /* PCM parameters */
111 unsigned int pcm_period_size;
112 unsigned int pcm_bps; /* bytes per second */
113 unsigned int pcm_salign; /* bytes per sample * channels */
114 unsigned int pcm_rate_shift; /* rate shift value */
115 /* flags */
116 unsigned int period_update_pending :1;
117 /* timer stuff */
118 unsigned int irq_pos; /* fractional IRQ position */
119 unsigned int period_size_frac;
120 unsigned long last_jiffies;
121 struct timer_list timer;
122};
123
124static struct platform_device *devices[SNDRV_CARDS];
125
126static inline unsigned int byte_pos(struct loopback_pcm *dpcm, unsigned int x)
127{
128 if (dpcm->pcm_rate_shift == NO_PITCH) {
129 x /= HZ;
130 } else {
131 x = div_u64(NO_PITCH * (unsigned long long)x,
132 HZ * (unsigned long long)dpcm->pcm_rate_shift);
133 }
134 return x - (x % dpcm->pcm_salign);
135}
136
137static inline unsigned int frac_pos(struct loopback_pcm *dpcm, unsigned int x)
138{
139 if (dpcm->pcm_rate_shift == NO_PITCH) { /* no pitch */
140 return x * HZ;
141 } else {
142 x = div_u64(dpcm->pcm_rate_shift * (unsigned long long)x * HZ,
143 NO_PITCH);
144 }
145 return x;
146}
147
148static inline struct loopback_setup *get_setup(struct loopback_pcm *dpcm)
149{
150 int device = dpcm->substream->pstr->pcm->device;
151
152 if (dpcm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
153 device ^= 1;
154 return &dpcm->loopback->setup[dpcm->substream->number][device];
155}
156
157static inline unsigned int get_notify(struct loopback_pcm *dpcm)
158{
159 return get_setup(dpcm)->notify;
160}
161
162static inline unsigned int get_rate_shift(struct loopback_pcm *dpcm)
163{
164 return get_setup(dpcm)->rate_shift;
165}
166
167static void loopback_timer_start(struct loopback_pcm *dpcm)
168{
169 unsigned long tick;
170 unsigned int rate_shift = get_rate_shift(dpcm);
171
172 if (rate_shift != dpcm->pcm_rate_shift) {
173 dpcm->pcm_rate_shift = rate_shift;
174 dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size);
175 }
176 if (dpcm->period_size_frac <= dpcm->irq_pos) {
177 dpcm->irq_pos %= dpcm->period_size_frac;
178 dpcm->period_update_pending = 1;
179 }
180 tick = dpcm->period_size_frac - dpcm->irq_pos;
181 tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
182 dpcm->timer.expires = jiffies + tick;
183 add_timer(&dpcm->timer);
184}
185
186static inline void loopback_timer_stop(struct loopback_pcm *dpcm)
187{
188 del_timer(&dpcm->timer);
189 dpcm->timer.expires = 0;
190}
191
192#define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK)
193#define CABLE_VALID_CAPTURE (1 << SNDRV_PCM_STREAM_CAPTURE)
194#define CABLE_VALID_BOTH (CABLE_VALID_PLAYBACK|CABLE_VALID_CAPTURE)
195
196static int loopback_check_format(struct loopback_cable *cable, int stream)
197{
198 struct snd_pcm_runtime *runtime, *cruntime;
199 struct loopback_setup *setup;
200 struct snd_card *card;
201 int check;
202
203 if (cable->valid != CABLE_VALID_BOTH) {
204 if (stream == SNDRV_PCM_STREAM_PLAYBACK)
205 goto __notify;
206 return 0;
207 }
208 runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
209 substream->runtime;
210 cruntime = cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
211 substream->runtime;
212 check = runtime->format != cruntime->format ||
213 runtime->rate != cruntime->rate ||
214 runtime->channels != cruntime->channels;
215 if (!check)
216 return 0;
217 if (stream == SNDRV_PCM_STREAM_CAPTURE) {
218 return -EIO;
219 } else {
220 snd_pcm_stop(cable->streams[SNDRV_PCM_STREAM_CAPTURE]->
221 substream, SNDRV_PCM_STATE_DRAINING);
222 __notify:
223 runtime = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->
224 substream->runtime;
225 setup = get_setup(cable->streams[SNDRV_PCM_STREAM_PLAYBACK]);
226 card = cable->streams[SNDRV_PCM_STREAM_PLAYBACK]->loopback->card;
227 if (setup->format != runtime->format) {
228 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
229 &setup->format_id);
230 setup->format = runtime->format;
231 }
232 if (setup->rate != runtime->rate) {
233 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
234 &setup->rate_id);
235 setup->rate = runtime->rate;
236 }
237 if (setup->channels != runtime->channels) {
238 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
239 &setup->channels_id);
240 setup->channels = runtime->channels;
241 }
242 }
243 return 0;
244}
245
246static void loopback_active_notify(struct loopback_pcm *dpcm)
247{
248 snd_ctl_notify(dpcm->loopback->card,
249 SNDRV_CTL_EVENT_MASK_VALUE,
250 &get_setup(dpcm)->active_id);
251}
252
253static int loopback_trigger(struct snd_pcm_substream *substream, int cmd)
254{
255 struct snd_pcm_runtime *runtime = substream->runtime;
256 struct loopback_pcm *dpcm = runtime->private_data;
257 struct loopback_cable *cable = dpcm->cable;
258 int err, stream = 1 << substream->stream;
259
260 switch (cmd) {
261 case SNDRV_PCM_TRIGGER_START:
262 err = loopback_check_format(cable, substream->stream);
263 if (err < 0)
264 return err;
265 dpcm->last_jiffies = jiffies;
266 dpcm->pcm_rate_shift = 0;
267 spin_lock(&cable->lock);
268 cable->running |= stream;
269 cable->pause &= ~stream;
270 spin_unlock(&cable->lock);
271 loopback_timer_start(dpcm);
272 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
273 loopback_active_notify(dpcm);
274 break;
275 case SNDRV_PCM_TRIGGER_STOP:
276 spin_lock(&cable->lock);
277 cable->running &= ~stream;
278 cable->pause &= ~stream;
279 spin_unlock(&cable->lock);
280 loopback_timer_stop(dpcm);
281 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
282 loopback_active_notify(dpcm);
283 break;
284 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
285 spin_lock(&cable->lock);
286 cable->pause |= stream;
287 spin_unlock(&cable->lock);
288 loopback_timer_stop(dpcm);
289 break;
290 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
291 spin_lock(&cable->lock);
292 dpcm->last_jiffies = jiffies;
293 cable->pause &= ~stream;
294 spin_unlock(&cable->lock);
295 loopback_timer_start(dpcm);
296 break;
297 default:
298 return -EINVAL;
299 }
300 return 0;
301}
302
303static void params_change_substream(struct loopback_pcm *dpcm,
304 struct snd_pcm_runtime *runtime)
305{
306 struct snd_pcm_runtime *dst_runtime;
307
308 if (dpcm == NULL || dpcm->substream == NULL)
309 return;
310 dst_runtime = dpcm->substream->runtime;
311 if (dst_runtime == NULL)
312 return;
313 dst_runtime->hw = dpcm->cable->hw;
314}
315
316static void params_change(struct snd_pcm_substream *substream)
317{
318 struct snd_pcm_runtime *runtime = substream->runtime;
319 struct loopback_pcm *dpcm = runtime->private_data;
320 struct loopback_cable *cable = dpcm->cable;
321
322 cable->hw.formats = (1ULL << runtime->format);
323 cable->hw.rate_min = runtime->rate;
324 cable->hw.rate_max = runtime->rate;
325 cable->hw.channels_min = runtime->channels;
326 cable->hw.channels_max = runtime->channels;
327 params_change_substream(cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
328 runtime);
329 params_change_substream(cable->streams[SNDRV_PCM_STREAM_CAPTURE],
330 runtime);
331}
332
333static int loopback_prepare(struct snd_pcm_substream *substream)
334{
335 struct snd_pcm_runtime *runtime = substream->runtime;
336 struct loopback_pcm *dpcm = runtime->private_data;
337 struct loopback_cable *cable = dpcm->cable;
338 int bps, salign;
339
340 salign = (snd_pcm_format_width(runtime->format) *
341 runtime->channels) / 8;
342 bps = salign * runtime->rate;
343 if (bps <= 0 || salign <= 0)
344 return -EINVAL;
345
346 dpcm->buf_pos = 0;
347 dpcm->pcm_buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
348 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
349 /* clear capture buffer */
350 dpcm->silent_size = dpcm->pcm_buffer_size;
351 snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
352 runtime->buffer_size * runtime->channels);
353 }
354
355 dpcm->irq_pos = 0;
356 dpcm->period_update_pending = 0;
357 dpcm->pcm_bps = bps;
358 dpcm->pcm_salign = salign;
359 dpcm->pcm_period_size = frames_to_bytes(runtime, runtime->period_size);
360
361 mutex_lock(&dpcm->loopback->cable_lock);
362 if (!(cable->valid & ~(1 << substream->stream)) ||
363 (get_setup(dpcm)->notify &&
364 substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
365 params_change(substream);
366 cable->valid |= 1 << substream->stream;
367 mutex_unlock(&dpcm->loopback->cable_lock);
368
369 return 0;
370}
371
372static void clear_capture_buf(struct loopback_pcm *dpcm, unsigned int bytes)
373{
374 struct snd_pcm_runtime *runtime = dpcm->substream->runtime;
375 char *dst = runtime->dma_area;
376 unsigned int dst_off = dpcm->buf_pos;
377
378 if (dpcm->silent_size >= dpcm->pcm_buffer_size)
379 return;
380 if (dpcm->silent_size + bytes > dpcm->pcm_buffer_size)
381 bytes = dpcm->pcm_buffer_size - dpcm->silent_size;
382
383 for (;;) {
384 unsigned int size = bytes;
385 if (dst_off + size > dpcm->pcm_buffer_size)
386 size = dpcm->pcm_buffer_size - dst_off;
387 snd_pcm_format_set_silence(runtime->format, dst + dst_off,
388 bytes_to_frames(runtime, size) *
389 runtime->channels);
390 dpcm->silent_size += size;
391 bytes -= size;
392 if (!bytes)
393 break;
394 dst_off = 0;
395 }
396}
397
398static void copy_play_buf(struct loopback_pcm *play,
399 struct loopback_pcm *capt,
400 unsigned int bytes)
401{
402 struct snd_pcm_runtime *runtime = play->substream->runtime;
403 char *src = runtime->dma_area;
404 char *dst = capt->substream->runtime->dma_area;
405 unsigned int src_off = play->buf_pos;
406 unsigned int dst_off = capt->buf_pos;
407 unsigned int clear_bytes = 0;
408
409 /* check if playback is draining, trim the capture copy size
410 * when our pointer is at the end of playback ring buffer */
411 if (runtime->status->state == SNDRV_PCM_STATE_DRAINING &&
412 snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) {
413 snd_pcm_uframes_t appl_ptr, appl_ptr1, diff;
414 appl_ptr = appl_ptr1 = runtime->control->appl_ptr;
415 appl_ptr1 -= appl_ptr1 % runtime->buffer_size;
416 appl_ptr1 += play->buf_pos / play->pcm_salign;
417 if (appl_ptr < appl_ptr1)
418 appl_ptr1 -= runtime->buffer_size;
419 diff = (appl_ptr - appl_ptr1) * play->pcm_salign;
420 if (diff < bytes) {
421 clear_bytes = bytes - diff;
422 bytes = diff;
423 }
424 }
425
426 for (;;) {
427 unsigned int size = bytes;
428 if (src_off + size > play->pcm_buffer_size)
429 size = play->pcm_buffer_size - src_off;
430 if (dst_off + size > capt->pcm_buffer_size)
431 size = capt->pcm_buffer_size - dst_off;
432 memcpy(dst + dst_off, src + src_off, size);
433 capt->silent_size = 0;
434 bytes -= size;
435 if (!bytes)
436 break;
437 src_off = (src_off + size) % play->pcm_buffer_size;
438 dst_off = (dst_off + size) % capt->pcm_buffer_size;
439 }
440
441 if (clear_bytes > 0) {
442 clear_capture_buf(capt, clear_bytes);
443 capt->silent_size = 0;
444 }
445}
446
447#define BYTEPOS_UPDATE_POSONLY 0
448#define BYTEPOS_UPDATE_CLEAR 1
449#define BYTEPOS_UPDATE_COPY 2
450
451static void loopback_bytepos_update(struct loopback_pcm *dpcm,
452 unsigned int delta,
453 unsigned int cmd)
454{
455 unsigned int count;
456 unsigned long last_pos;
457
458 last_pos = byte_pos(dpcm, dpcm->irq_pos);
459 dpcm->irq_pos += delta * dpcm->pcm_bps;
460 count = byte_pos(dpcm, dpcm->irq_pos) - last_pos;
461 if (!count)
462 return;
463 if (cmd == BYTEPOS_UPDATE_CLEAR)
464 clear_capture_buf(dpcm, count);
465 else if (cmd == BYTEPOS_UPDATE_COPY)
466 copy_play_buf(dpcm->cable->streams[SNDRV_PCM_STREAM_PLAYBACK],
467 dpcm->cable->streams[SNDRV_PCM_STREAM_CAPTURE],
468 count);
469 dpcm->buf_pos += count;
470 dpcm->buf_pos %= dpcm->pcm_buffer_size;
471 if (dpcm->irq_pos >= dpcm->period_size_frac) {
472 dpcm->irq_pos %= dpcm->period_size_frac;
473 dpcm->period_update_pending = 1;
474 }
475}
476
477static unsigned int loopback_pos_update(struct loopback_cable *cable)
478{
479 struct loopback_pcm *dpcm_play =
480 cable->streams[SNDRV_PCM_STREAM_PLAYBACK];
481 struct loopback_pcm *dpcm_capt =
482 cable->streams[SNDRV_PCM_STREAM_CAPTURE];
483 unsigned long delta_play = 0, delta_capt = 0;
484 unsigned int running;
485
486 spin_lock(&cable->lock);
487 running = cable->running ^ cable->pause;
488 if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
489 delta_play = jiffies - dpcm_play->last_jiffies;
490 dpcm_play->last_jiffies += delta_play;
491 }
492
493 if (running & (1 << SNDRV_PCM_STREAM_CAPTURE)) {
494 delta_capt = jiffies - dpcm_capt->last_jiffies;
495 dpcm_capt->last_jiffies += delta_capt;
496 }
497
498 if (delta_play == 0 && delta_capt == 0) {
499 spin_unlock(&cable->lock);
500 return running;
501 }
502
503 if (delta_play > delta_capt) {
504 loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
505 BYTEPOS_UPDATE_POSONLY);
506 delta_play = delta_capt;
507 } else if (delta_play < delta_capt) {
508 loopback_bytepos_update(dpcm_capt, delta_capt - delta_play,
509 BYTEPOS_UPDATE_CLEAR);
510 delta_capt = delta_play;
511 }
512
513 if (delta_play == 0 && delta_capt == 0) {
514 spin_unlock(&cable->lock);
515 return running;
516 }
517 /* note delta_capt == delta_play at this moment */
518 loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
519 loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
520 spin_unlock(&cable->lock);
521 return running;
522}
523
524static void loopback_timer_function(unsigned long data)
525{
526 struct loopback_pcm *dpcm = (struct loopback_pcm *)data;
527 unsigned int running;
528
529 running = loopback_pos_update(dpcm->cable);
530 if (running & (1 << dpcm->substream->stream)) {
531 loopback_timer_start(dpcm);
532 if (dpcm->period_update_pending) {
533 dpcm->period_update_pending = 0;
534 snd_pcm_period_elapsed(dpcm->substream);
535 }
536 }
537}
538
539static snd_pcm_uframes_t loopback_pointer(struct snd_pcm_substream *substream)
540{
541 struct snd_pcm_runtime *runtime = substream->runtime;
542 struct loopback_pcm *dpcm = runtime->private_data;
543
544 loopback_pos_update(dpcm->cable);
545 return bytes_to_frames(runtime, dpcm->buf_pos);
546}
547
548static struct snd_pcm_hardware loopback_pcm_hardware =
549{
550 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP |
551 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
552 .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
553 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE |
554 SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE),
555 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
556 .rate_min = 8000,
557 .rate_max = 192000,
558 .channels_min = 1,
559 .channels_max = 32,
560 .buffer_bytes_max = 2 * 1024 * 1024,
561 .period_bytes_min = 64,
562 /* note check overflow in frac_pos() using pcm_rate_shift before
563 changing period_bytes_max value */
564 .period_bytes_max = 1024 * 1024,
565 .periods_min = 1,
566 .periods_max = 1024,
567 .fifo_size = 0,
568};
569
570static void loopback_runtime_free(struct snd_pcm_runtime *runtime)
571{
572 struct loopback_pcm *dpcm = runtime->private_data;
573 kfree(dpcm);
574}
575
576static int loopback_hw_params(struct snd_pcm_substream *substream,
577 struct snd_pcm_hw_params *params)
578{
579 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
580}
581
582static int loopback_hw_free(struct snd_pcm_substream *substream)
583{
584 struct snd_pcm_runtime *runtime = substream->runtime;
585 struct loopback_pcm *dpcm = runtime->private_data;
586 struct loopback_cable *cable = dpcm->cable;
587
588 mutex_lock(&dpcm->loopback->cable_lock);
589 cable->valid &= ~(1 << substream->stream);
590 mutex_unlock(&dpcm->loopback->cable_lock);
591 return snd_pcm_lib_free_pages(substream);
592}
593
594static unsigned int get_cable_index(struct snd_pcm_substream *substream)
595{
596 if (!substream->pcm->device)
597 return substream->stream;
598 else
599 return !substream->stream;
600}
601
602static int rule_format(struct snd_pcm_hw_params *params,
603 struct snd_pcm_hw_rule *rule)
604{
605
606 struct snd_pcm_hardware *hw = rule->private;
607 struct snd_mask *maskp = hw_param_mask(params, rule->var);
608
609 maskp->bits[0] &= (u_int32_t)hw->formats;
610 maskp->bits[1] &= (u_int32_t)(hw->formats >> 32);
611 memset(maskp->bits + 2, 0, (SNDRV_MASK_MAX-64) / 8); /* clear rest */
612 if (! maskp->bits[0] && ! maskp->bits[1])
613 return -EINVAL;
614 return 0;
615}
616
617static int rule_rate(struct snd_pcm_hw_params *params,
618 struct snd_pcm_hw_rule *rule)
619{
620 struct snd_pcm_hardware *hw = rule->private;
621 struct snd_interval t;
622
623 t.min = hw->rate_min;
624 t.max = hw->rate_max;
625 t.openmin = t.openmax = 0;
626 t.integer = 0;
627 return snd_interval_refine(hw_param_interval(params, rule->var), &t);
628}
629
630static int rule_channels(struct snd_pcm_hw_params *params,
631 struct snd_pcm_hw_rule *rule)
632{
633 struct snd_pcm_hardware *hw = rule->private;
634 struct snd_interval t;
635
636 t.min = hw->channels_min;
637 t.max = hw->channels_max;
638 t.openmin = t.openmax = 0;
639 t.integer = 0;
640 return snd_interval_refine(hw_param_interval(params, rule->var), &t);
641}
642
643static int loopback_open(struct snd_pcm_substream *substream)
644{
645 struct snd_pcm_runtime *runtime = substream->runtime;
646 struct loopback *loopback = substream->private_data;
647 struct loopback_pcm *dpcm;
648 struct loopback_cable *cable;
649 int err = 0;
650 int dev = get_cable_index(substream);
651
652 mutex_lock(&loopback->cable_lock);
653 dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
654 if (!dpcm) {
655 err = -ENOMEM;
656 goto unlock;
657 }
658 dpcm->loopback = loopback;
659 dpcm->substream = substream;
660 setup_timer(&dpcm->timer, loopback_timer_function,
661 (unsigned long)dpcm);
662
663 cable = loopback->cables[substream->number][dev];
664 if (!cable) {
665 cable = kzalloc(sizeof(*cable), GFP_KERNEL);
666 if (!cable) {
667 kfree(dpcm);
668 err = -ENOMEM;
669 goto unlock;
670 }
671 spin_lock_init(&cable->lock);
672 cable->hw = loopback_pcm_hardware;
673 loopback->cables[substream->number][dev] = cable;
674 }
675 dpcm->cable = cable;
676 cable->streams[substream->stream] = dpcm;
677
678 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
679
680 /* use dynamic rules based on actual runtime->hw values */
681 /* note that the default rules created in the PCM midlevel code */
682 /* are cached -> they do not reflect the actual state */
683 err = snd_pcm_hw_rule_add(runtime, 0,
684 SNDRV_PCM_HW_PARAM_FORMAT,
685 rule_format, &runtime->hw,
686 SNDRV_PCM_HW_PARAM_FORMAT, -1);
687 if (err < 0)
688 goto unlock;
689 err = snd_pcm_hw_rule_add(runtime, 0,
690 SNDRV_PCM_HW_PARAM_RATE,
691 rule_rate, &runtime->hw,
692 SNDRV_PCM_HW_PARAM_RATE, -1);
693 if (err < 0)
694 goto unlock;
695 err = snd_pcm_hw_rule_add(runtime, 0,
696 SNDRV_PCM_HW_PARAM_CHANNELS,
697 rule_channels, &runtime->hw,
698 SNDRV_PCM_HW_PARAM_CHANNELS, -1);
699 if (err < 0)
700 goto unlock;
701
702 runtime->private_data = dpcm;
703 runtime->private_free = loopback_runtime_free;
704 if (get_notify(dpcm))
705 runtime->hw = loopback_pcm_hardware;
706 else
707 runtime->hw = cable->hw;
708 unlock:
709 mutex_unlock(&loopback->cable_lock);
710 return err;
711}
712
713static int loopback_close(struct snd_pcm_substream *substream)
714{
715 struct loopback *loopback = substream->private_data;
716 struct loopback_pcm *dpcm = substream->runtime->private_data;
717 struct loopback_cable *cable;
718 int dev = get_cable_index(substream);
719
720 loopback_timer_stop(dpcm);
721 mutex_lock(&loopback->cable_lock);
722 cable = loopback->cables[substream->number][dev];
723 if (cable->streams[!substream->stream]) {
724 /* other stream is still alive */
725 cable->streams[substream->stream] = NULL;
726 } else {
727 /* free the cable */
728 loopback->cables[substream->number][dev] = NULL;
729 kfree(cable);
730 }
731 mutex_unlock(&loopback->cable_lock);
732 return 0;
733}
734
735static struct snd_pcm_ops loopback_playback_ops = {
736 .open = loopback_open,
737 .close = loopback_close,
738 .ioctl = snd_pcm_lib_ioctl,
739 .hw_params = loopback_hw_params,
740 .hw_free = loopback_hw_free,
741 .prepare = loopback_prepare,
742 .trigger = loopback_trigger,
743 .pointer = loopback_pointer,
744};
745
746static struct snd_pcm_ops loopback_capture_ops = {
747 .open = loopback_open,
748 .close = loopback_close,
749 .ioctl = snd_pcm_lib_ioctl,
750 .hw_params = loopback_hw_params,
751 .hw_free = loopback_hw_free,
752 .prepare = loopback_prepare,
753 .trigger = loopback_trigger,
754 .pointer = loopback_pointer,
755};
756
757static int __devinit loopback_pcm_new(struct loopback *loopback,
758 int device, int substreams)
759{
760 struct snd_pcm *pcm;
761 int err;
762
763 err = snd_pcm_new(loopback->card, "Loopback PCM", device,
764 substreams, substreams, &pcm);
765 if (err < 0)
766 return err;
767 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_playback_ops);
768 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_capture_ops);
769
770 pcm->private_data = loopback;
771 pcm->info_flags = 0;
772 strcpy(pcm->name, "Loopback PCM");
773
774 loopback->pcm[device] = pcm;
775
776 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
777 snd_dma_continuous_data(GFP_KERNEL),
778 0, 2 * 1024 * 1024);
779 return 0;
780}
781
782static int loopback_rate_shift_info(struct snd_kcontrol *kcontrol,
783 struct snd_ctl_elem_info *uinfo)
784{
785 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
786 uinfo->count = 1;
787 uinfo->value.integer.min = 80000;
788 uinfo->value.integer.max = 120000;
789 uinfo->value.integer.step = 1;
790 return 0;
791}
792
793static int loopback_rate_shift_get(struct snd_kcontrol *kcontrol,
794 struct snd_ctl_elem_value *ucontrol)
795{
796 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
797
798 ucontrol->value.integer.value[0] =
799 loopback->setup[kcontrol->id.subdevice]
800 [kcontrol->id.device].rate_shift;
801 return 0;
802}
803
804static int loopback_rate_shift_put(struct snd_kcontrol *kcontrol,
805 struct snd_ctl_elem_value *ucontrol)
806{
807 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
808 unsigned int val;
809 int change = 0;
810
811 val = ucontrol->value.integer.value[0];
812 if (val < 80000)
813 val = 80000;
814 if (val > 120000)
815 val = 120000;
816 mutex_lock(&loopback->cable_lock);
817 if (val != loopback->setup[kcontrol->id.subdevice]
818 [kcontrol->id.device].rate_shift) {
819 loopback->setup[kcontrol->id.subdevice]
820 [kcontrol->id.device].rate_shift = val;
821 change = 1;
822 }
823 mutex_unlock(&loopback->cable_lock);
824 return change;
825}
826
827static int loopback_notify_get(struct snd_kcontrol *kcontrol,
828 struct snd_ctl_elem_value *ucontrol)
829{
830 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
831
832 ucontrol->value.integer.value[0] =
833 loopback->setup[kcontrol->id.subdevice]
834 [kcontrol->id.device].notify;
835 return 0;
836}
837
838static int loopback_notify_put(struct snd_kcontrol *kcontrol,
839 struct snd_ctl_elem_value *ucontrol)
840{
841 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
842 unsigned int val;
843 int change = 0;
844
845 val = ucontrol->value.integer.value[0] ? 1 : 0;
846 if (val != loopback->setup[kcontrol->id.subdevice]
847 [kcontrol->id.device].notify) {
848 loopback->setup[kcontrol->id.subdevice]
849 [kcontrol->id.device].notify = val;
850 change = 1;
851 }
852 return change;
853}
854
855static int loopback_active_get(struct snd_kcontrol *kcontrol,
856 struct snd_ctl_elem_value *ucontrol)
857{
858 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
859 struct loopback_cable *cable = loopback->cables
860 [kcontrol->id.subdevice][kcontrol->id.device ^ 1];
861 unsigned int val = 0;
862
863 if (cable != NULL)
864 val = (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ?
865 1 : 0;
866 ucontrol->value.integer.value[0] = val;
867 return 0;
868}
869
870static int loopback_format_info(struct snd_kcontrol *kcontrol,
871 struct snd_ctl_elem_info *uinfo)
872{
873 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
874 uinfo->count = 1;
875 uinfo->value.integer.min = 0;
876 uinfo->value.integer.max = SNDRV_PCM_FORMAT_LAST;
877 uinfo->value.integer.step = 1;
878 return 0;
879}
880
881static int loopback_format_get(struct snd_kcontrol *kcontrol,
882 struct snd_ctl_elem_value *ucontrol)
883{
884 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
885
886 ucontrol->value.integer.value[0] =
887 loopback->setup[kcontrol->id.subdevice]
888 [kcontrol->id.device].format;
889 return 0;
890}
891
892static int loopback_rate_info(struct snd_kcontrol *kcontrol,
893 struct snd_ctl_elem_info *uinfo)
894{
895 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
896 uinfo->count = 1;
897 uinfo->value.integer.min = 0;
898 uinfo->value.integer.max = 192000;
899 uinfo->value.integer.step = 1;
900 return 0;
901}
902
903static int loopback_rate_get(struct snd_kcontrol *kcontrol,
904 struct snd_ctl_elem_value *ucontrol)
905{
906 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
907
908 ucontrol->value.integer.value[0] =
909 loopback->setup[kcontrol->id.subdevice]
910 [kcontrol->id.device].rate;
911 return 0;
912}
913
914static int loopback_channels_info(struct snd_kcontrol *kcontrol,
915 struct snd_ctl_elem_info *uinfo)
916{
917 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
918 uinfo->count = 1;
919 uinfo->value.integer.min = 1;
920 uinfo->value.integer.max = 1024;
921 uinfo->value.integer.step = 1;
922 return 0;
923}
924
925static int loopback_channels_get(struct snd_kcontrol *kcontrol,
926 struct snd_ctl_elem_value *ucontrol)
927{
928 struct loopback *loopback = snd_kcontrol_chip(kcontrol);
929
930 ucontrol->value.integer.value[0] =
931 loopback->setup[kcontrol->id.subdevice]
932 [kcontrol->id.device].channels;
933 return 0;
934}
935
936static struct snd_kcontrol_new loopback_controls[] __devinitdata = {
937{
938 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
939 .name = "PCM Rate Shift 100000",
940 .info = loopback_rate_shift_info,
941 .get = loopback_rate_shift_get,
942 .put = loopback_rate_shift_put,
943},
944{
945 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
946 .name = "PCM Notify",
947 .info = snd_ctl_boolean_mono_info,
948 .get = loopback_notify_get,
949 .put = loopback_notify_put,
950},
951#define ACTIVE_IDX 2
952{
953 .access = SNDRV_CTL_ELEM_ACCESS_READ,
954 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
955 .name = "PCM Slave Active",
956 .info = snd_ctl_boolean_mono_info,
957 .get = loopback_active_get,
958},
959#define FORMAT_IDX 3
960{
961 .access = SNDRV_CTL_ELEM_ACCESS_READ,
962 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
963 .name = "PCM Slave Format",
964 .info = loopback_format_info,
965 .get = loopback_format_get
966},
967#define RATE_IDX 4
968{
969 .access = SNDRV_CTL_ELEM_ACCESS_READ,
970 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
971 .name = "PCM Slave Rate",
972 .info = loopback_rate_info,
973 .get = loopback_rate_get
974},
975#define CHANNELS_IDX 5
976{
977 .access = SNDRV_CTL_ELEM_ACCESS_READ,
978 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
979 .name = "PCM Slave Channels",
980 .info = loopback_channels_info,
981 .get = loopback_channels_get
982}
983};
984
985static int __devinit loopback_mixer_new(struct loopback *loopback, int notify)
986{
987 struct snd_card *card = loopback->card;
988 struct snd_pcm *pcm;
989 struct snd_kcontrol *kctl;
990 struct loopback_setup *setup;
991 int err, dev, substr, substr_count, idx;
992
993 strcpy(card->mixername, "Loopback Mixer");
994 for (dev = 0; dev < 2; dev++) {
995 pcm = loopback->pcm[dev];
996 substr_count =
997 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream_count;
998 for (substr = 0; substr < substr_count; substr++) {
999 setup = &loopback->setup[substr][dev];
1000 setup->notify = notify;
1001 setup->rate_shift = NO_PITCH;
1002 setup->format = SNDRV_PCM_FORMAT_S16_LE;
1003 setup->rate = 48000;
1004 setup->channels = 2;
1005 for (idx = 0; idx < ARRAY_SIZE(loopback_controls);
1006 idx++) {
1007 kctl = snd_ctl_new1(&loopback_controls[idx],
1008 loopback);
1009 if (!kctl)
1010 return -ENOMEM;
1011 kctl->id.device = dev;
1012 kctl->id.subdevice = substr;
1013 switch (idx) {
1014 case ACTIVE_IDX:
1015 setup->active_id = kctl->id;
1016 break;
1017 case FORMAT_IDX:
1018 setup->format_id = kctl->id;
1019 break;
1020 case RATE_IDX:
1021 setup->rate_id = kctl->id;
1022 break;
1023 case CHANNELS_IDX:
1024 setup->channels_id = kctl->id;
1025 break;
1026 default:
1027 break;
1028 }
1029 err = snd_ctl_add(card, kctl);
1030 if (err < 0)
1031 return err;
1032 }
1033 }
1034 }
1035 return 0;
1036}
1037
1038#ifdef CONFIG_PROC_FS
1039
1040static void print_dpcm_info(struct snd_info_buffer *buffer,
1041 struct loopback_pcm *dpcm,
1042 const char *id)
1043{
1044 snd_iprintf(buffer, " %s\n", id);
1045 if (dpcm == NULL) {
1046 snd_iprintf(buffer, " inactive\n");
1047 return;
1048 }
1049 snd_iprintf(buffer, " buffer_size:\t%u\n", dpcm->pcm_buffer_size);
1050 snd_iprintf(buffer, " buffer_pos:\t\t%u\n", dpcm->buf_pos);
1051 snd_iprintf(buffer, " silent_size:\t%u\n", dpcm->silent_size);
1052 snd_iprintf(buffer, " period_size:\t%u\n", dpcm->pcm_period_size);
1053 snd_iprintf(buffer, " bytes_per_sec:\t%u\n", dpcm->pcm_bps);
1054 snd_iprintf(buffer, " sample_align:\t%u\n", dpcm->pcm_salign);
1055 snd_iprintf(buffer, " rate_shift:\t\t%u\n", dpcm->pcm_rate_shift);
1056 snd_iprintf(buffer, " update_pending:\t%u\n",
1057 dpcm->period_update_pending);
1058 snd_iprintf(buffer, " irq_pos:\t\t%u\n", dpcm->irq_pos);
1059 snd_iprintf(buffer, " period_frac:\t%u\n", dpcm->period_size_frac);
1060 snd_iprintf(buffer, " last_jiffies:\t%lu (%lu)\n",
1061 dpcm->last_jiffies, jiffies);
1062 snd_iprintf(buffer, " timer_expires:\t%lu\n", dpcm->timer.expires);
1063}
1064
1065static void print_substream_info(struct snd_info_buffer *buffer,
1066 struct loopback *loopback,
1067 int sub,
1068 int num)
1069{
1070 struct loopback_cable *cable = loopback->cables[sub][num];
1071
1072 snd_iprintf(buffer, "Cable %i substream %i:\n", num, sub);
1073 if (cable == NULL) {
1074 snd_iprintf(buffer, " inactive\n");
1075 return;
1076 }
1077 snd_iprintf(buffer, " valid: %u\n", cable->valid);
1078 snd_iprintf(buffer, " running: %u\n", cable->running);
1079 snd_iprintf(buffer, " pause: %u\n", cable->pause);
1080 print_dpcm_info(buffer, cable->streams[0], "Playback");
1081 print_dpcm_info(buffer, cable->streams[1], "Capture");
1082}
1083
1084static void print_cable_info(struct snd_info_entry *entry,
1085 struct snd_info_buffer *buffer)
1086{
1087 struct loopback *loopback = entry->private_data;
1088 int sub, num;
1089
1090 mutex_lock(&loopback->cable_lock);
1091 num = entry->name[strlen(entry->name)-1];
1092 num = num == '0' ? 0 : 1;
1093 for (sub = 0; sub < MAX_PCM_SUBSTREAMS; sub++)
1094 print_substream_info(buffer, loopback, sub, num);
1095 mutex_unlock(&loopback->cable_lock);
1096}
1097
1098static int __devinit loopback_proc_new(struct loopback *loopback, int cidx)
1099{
1100 char name[32];
1101 struct snd_info_entry *entry;
1102 int err;
1103
1104 snprintf(name, sizeof(name), "cable#%d", cidx);
1105 err = snd_card_proc_new(loopback->card, name, &entry);
1106 if (err < 0)
1107 return err;
1108
1109 snd_info_set_text_ops(entry, loopback, print_cable_info);
1110 return 0;
1111}
1112
1113#else /* !CONFIG_PROC_FS */
1114
1115#define loopback_proc_new(loopback, cidx) do { } while (0)
1116
1117#endif
1118
1119static int __devinit loopback_probe(struct platform_device *devptr)
1120{
1121 struct snd_card *card;
1122 struct loopback *loopback;
1123 int dev = devptr->id;
1124 int err;
1125
1126 err = snd_card_create(index[dev], id[dev], THIS_MODULE,
1127 sizeof(struct loopback), &card);
1128 if (err < 0)
1129 return err;
1130 loopback = card->private_data;
1131
1132 if (pcm_substreams[dev] < 1)
1133 pcm_substreams[dev] = 1;
1134 if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS)
1135 pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
1136
1137 loopback->card = card;
1138 mutex_init(&loopback->cable_lock);
1139
1140 err = loopback_pcm_new(loopback, 0, pcm_substreams[dev]);
1141 if (err < 0)
1142 goto __nodev;
1143 err = loopback_pcm_new(loopback, 1, pcm_substreams[dev]);
1144 if (err < 0)
1145 goto __nodev;
1146 err = loopback_mixer_new(loopback, pcm_notify[dev] ? 1 : 0);
1147 if (err < 0)
1148 goto __nodev;
1149 loopback_proc_new(loopback, 0);
1150 loopback_proc_new(loopback, 1);
1151 strcpy(card->driver, "Loopback");
1152 strcpy(card->shortname, "Loopback");
1153 sprintf(card->longname, "Loopback %i", dev + 1);
1154 err = snd_card_register(card);
1155 if (!err) {
1156 platform_set_drvdata(devptr, card);
1157 return 0;
1158 }
1159 __nodev:
1160 snd_card_free(card);
1161 return err;
1162}
1163
1164static int __devexit loopback_remove(struct platform_device *devptr)
1165{
1166 snd_card_free(platform_get_drvdata(devptr));
1167 platform_set_drvdata(devptr, NULL);
1168 return 0;
1169}
1170
1171#ifdef CONFIG_PM
1172static int loopback_suspend(struct platform_device *pdev,
1173 pm_message_t state)
1174{
1175 struct snd_card *card = platform_get_drvdata(pdev);
1176 struct loopback *loopback = card->private_data;
1177
1178 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
1179
1180 snd_pcm_suspend_all(loopback->pcm[0]);
1181 snd_pcm_suspend_all(loopback->pcm[1]);
1182 return 0;
1183}
1184
1185static int loopback_resume(struct platform_device *pdev)
1186{
1187 struct snd_card *card = platform_get_drvdata(pdev);
1188
1189 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
1190 return 0;
1191}
1192#endif
1193
1194#define SND_LOOPBACK_DRIVER "snd_aloop"
1195
1196static struct platform_driver loopback_driver = {
1197 .probe = loopback_probe,
1198 .remove = __devexit_p(loopback_remove),
1199#ifdef CONFIG_PM
1200 .suspend = loopback_suspend,
1201 .resume = loopback_resume,
1202#endif
1203 .driver = {
1204 .name = SND_LOOPBACK_DRIVER
1205 },
1206};
1207
1208static void loopback_unregister_all(void)
1209{
1210 int i;
1211
1212 for (i = 0; i < ARRAY_SIZE(devices); ++i)
1213 platform_device_unregister(devices[i]);
1214 platform_driver_unregister(&loopback_driver);
1215}
1216
1217static int __init alsa_card_loopback_init(void)
1218{
1219 int i, err, cards;
1220
1221 err = platform_driver_register(&loopback_driver);
1222 if (err < 0)
1223 return err;
1224
1225
1226 cards = 0;
1227 for (i = 0; i < SNDRV_CARDS; i++) {
1228 struct platform_device *device;
1229 if (!enable[i])
1230 continue;
1231 device = platform_device_register_simple(SND_LOOPBACK_DRIVER,
1232 i, NULL, 0);
1233 if (IS_ERR(device))
1234 continue;
1235 if (!platform_get_drvdata(device)) {
1236 platform_device_unregister(device);
1237 continue;
1238 }
1239 devices[i] = device;
1240 cards++;
1241 }
1242 if (!cards) {
1243#ifdef MODULE
1244 printk(KERN_ERR "aloop: No loopback enabled\n");
1245#endif
1246 loopback_unregister_all();
1247 return -ENODEV;
1248 }
1249 return 0;
1250}
1251
1252static void __exit alsa_card_loopback_exit(void)
1253{
1254 loopback_unregister_all();
1255}
1256
1257module_init(alsa_card_loopback_init)
1258module_exit(alsa_card_loopback_exit)
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index 0e631c3221e3..f4cd49336f33 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -94,7 +94,7 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr)
94 sizeof(struct snd_card_virmidi), &card); 94 sizeof(struct snd_card_virmidi), &card);
95 if (err < 0) 95 if (err < 0)
96 return err; 96 return err;
97 vmidi = (struct snd_card_virmidi *)card->private_data; 97 vmidi = card->private_data;
98 vmidi->card = card; 98 vmidi->card = card;
99 99
100 if (midi_devs[dev] > MAX_MIDI_DEVICES) { 100 if (midi_devs[dev] > MAX_MIDI_DEVICES) {
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 42d7844ecd0b..57ccba88700d 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -878,7 +878,7 @@ static int build_deemphasis(struct snd_akm4xxx *ak, int num_emphs)
878static void proc_regs_read(struct snd_info_entry *entry, 878static void proc_regs_read(struct snd_info_entry *entry,
879 struct snd_info_buffer *buffer) 879 struct snd_info_buffer *buffer)
880{ 880{
881 struct snd_akm4xxx *ak = (struct snd_akm4xxx *)entry->private_data; 881 struct snd_akm4xxx *ak = entry->private_data;
882 int reg, val, chip; 882 int reg, val, chip;
883 for (chip = 0; chip < ak->num_chips; chip++) { 883 for (chip = 0; chip < ak->num_chips; chip++) {
884 for (reg = 0; reg < ak->total_regs; reg++) { 884 for (reg = 0; reg < ak->total_regs; reg++) {
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index c6990c680796..52064cfa91f3 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -77,6 +77,32 @@ config SND_ALS100
77 To compile this driver as a module, choose M here: the module 77 To compile this driver as a module, choose M here: the module
78 will be called snd-als100. 78 will be called snd-als100.
79 79
80config SND_AZT1605
81 tristate "Aztech AZT1605 Driver"
82 depends on SND
83 select SND_WSS_LIB
84 select SND_MPU401_UART
85 select SND_OPL3_LIB
86 help
87 Say Y here to include support for Aztech Sound Galaxy cards
88 based on the AZT1605 chipset.
89
90 To compile this driver as a module, choose M here: the module
91 will be called snd-azt1605.
92
93config SND_AZT2316
94 tristate "Aztech AZT2316 Driver"
95 depends on SND
96 select SND_WSS_LIB
97 select SND_MPU401_UART
98 select SND_OPL3_LIB
99 help
100 Say Y here to include support for Aztech Sound Galaxy cards
101 based on the AZT2316 chipset.
102
103 To compile this driver as a module, choose M here: the module
104 will be called snd-azt2316.
105
80config SND_AZT2320 106config SND_AZT2320
81 tristate "Aztech Systems AZT2320" 107 tristate "Aztech Systems AZT2320"
82 depends on PNP 108 depends on PNP
@@ -351,16 +377,6 @@ config SND_SB16_CSP
351 coprocessor can do variable tasks like various compression and 377 coprocessor can do variable tasks like various compression and
352 decompression algorithms. 378 decompression algorithms.
353 379
354config SND_SGALAXY
355 tristate "Aztech Sound Galaxy"
356 select SND_WSS_LIB
357 help
358 Say Y here to include support for Aztech Sound Galaxy
359 soundcards.
360
361 To compile this driver as a module, choose M here: the module
362 will be called snd-sgalaxy.
363
364config SND_SSCAPE 380config SND_SSCAPE
365 tristate "Ensoniq SoundScape driver" 381 tristate "Ensoniq SoundScape driver"
366 select SND_MPU401_UART 382 select SND_MPU401_UART
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index c73d30c4f462..8d781e419e2e 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -10,7 +10,6 @@ snd-cmi8330-objs := cmi8330.o
10snd-es18xx-objs := es18xx.o 10snd-es18xx-objs := es18xx.o
11snd-opl3sa2-objs := opl3sa2.o 11snd-opl3sa2-objs := opl3sa2.o
12snd-sc6000-objs := sc6000.o 12snd-sc6000-objs := sc6000.o
13snd-sgalaxy-objs := sgalaxy.o
14snd-sscape-objs := sscape.o 13snd-sscape-objs := sscape.o
15 14
16# Toplevel Module Dependency 15# Toplevel Module Dependency
@@ -21,8 +20,7 @@ obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
21obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o 20obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o
22obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o 21obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o
23obj-$(CONFIG_SND_SC6000) += snd-sc6000.o 22obj-$(CONFIG_SND_SC6000) += snd-sc6000.o
24obj-$(CONFIG_SND_SGALAXY) += snd-sgalaxy.o
25obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o 23obj-$(CONFIG_SND_SSCAPE) += snd-sscape.o
26 24
27obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ gus/ msnd/ opti9xx/ \ 25obj-$(CONFIG_SND) += ad1816a/ ad1848/ cs423x/ es1688/ galaxy/ gus/ msnd/ opti9xx/ \
28 sb/ wavefront/ wss/ 26 sb/ wavefront/ wss/
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index bbcbf92a8ebe..3cb75bc97699 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -162,7 +162,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
162 sizeof(struct snd_card_ad1816a), &card); 162 sizeof(struct snd_card_ad1816a), &card);
163 if (error < 0) 163 if (error < 0)
164 return error; 164 return error;
165 acard = (struct snd_card_ad1816a *)card->private_data; 165 acard = card->private_data;
166 166
167 if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) { 167 if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) {
168 snd_card_free(card); 168 snd_card_free(card);
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index f7aa637b0d18..aac8dc15c2fe 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -188,7 +188,7 @@ static int __devinit snd_card_azt2320_probe(int dev,
188 sizeof(struct snd_card_azt2320), &card); 188 sizeof(struct snd_card_azt2320), &card);
189 if (error < 0) 189 if (error < 0)
190 return error; 190 return error;
191 acard = (struct snd_card_azt2320 *)card->private_data; 191 acard = card->private_data;
192 192
193 if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) { 193 if ((error = snd_card_azt2320_pnp(dev, acard, pcard, pid))) {
194 snd_card_free(card); 194 snd_card_free(card);
diff --git a/sound/isa/galaxy/Makefile b/sound/isa/galaxy/Makefile
new file mode 100644
index 000000000000..e307066d4315
--- /dev/null
+++ b/sound/isa/galaxy/Makefile
@@ -0,0 +1,10 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-azt1605-objs := azt1605.o
7snd-azt2316-objs := azt2316.o
8
9obj-$(CONFIG_SND_AZT1605) += snd-azt1605.o
10obj-$(CONFIG_SND_AZT2316) += snd-azt2316.o
diff --git a/sound/isa/galaxy/azt1605.c b/sound/isa/galaxy/azt1605.c
new file mode 100644
index 000000000000..9a97643cb713
--- /dev/null
+++ b/sound/isa/galaxy/azt1605.c
@@ -0,0 +1,91 @@
1/*
2 * Aztech AZT1605 Driver
3 * Copyright (C) 2007,2010 Rene Herman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#define AZT1605
21
22#define CRD_NAME "Aztech AZT1605"
23#define DRV_NAME "AZT1605"
24#define DEV_NAME "azt1605"
25
26#define GALAXY_DSP_MAJOR 2
27#define GALAXY_DSP_MINOR 1
28
29#define GALAXY_CONFIG_SIZE 3
30
31/*
32 * 24-bit config register
33 */
34
35#define GALAXY_CONFIG_SBA_220 (0 << 0)
36#define GALAXY_CONFIG_SBA_240 (1 << 0)
37#define GALAXY_CONFIG_SBA_260 (2 << 0)
38#define GALAXY_CONFIG_SBA_280 (3 << 0)
39#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280
40
41#define GALAXY_CONFIG_MPUA_300 (0 << 2)
42#define GALAXY_CONFIG_MPUA_330 (1 << 2)
43
44#define GALAXY_CONFIG_MPU_ENABLE (1 << 3)
45
46#define GALAXY_CONFIG_GAME_ENABLE (1 << 4)
47
48#define GALAXY_CONFIG_CD_PANASONIC (1 << 5)
49#define GALAXY_CONFIG_CD_MITSUMI (1 << 6)
50#define GALAXY_CONFIG_CD_MASK (\
51 GALAXY_CONFIG_CD_PANASONIC | GALAXY_CONFIG_CD_MITSUMI)
52
53#define GALAXY_CONFIG_UNUSED (1 << 7)
54#define GALAXY_CONFIG_UNUSED_MASK GALAXY_CONFIG_UNUSED
55
56#define GALAXY_CONFIG_SBIRQ_2 (1 << 8)
57#define GALAXY_CONFIG_SBIRQ_3 (1 << 9)
58#define GALAXY_CONFIG_SBIRQ_5 (1 << 10)
59#define GALAXY_CONFIG_SBIRQ_7 (1 << 11)
60
61#define GALAXY_CONFIG_MPUIRQ_2 (1 << 12)
62#define GALAXY_CONFIG_MPUIRQ_3 (1 << 13)
63#define GALAXY_CONFIG_MPUIRQ_5 (1 << 14)
64#define GALAXY_CONFIG_MPUIRQ_7 (1 << 15)
65
66#define GALAXY_CONFIG_WSSA_530 (0 << 16)
67#define GALAXY_CONFIG_WSSA_604 (1 << 16)
68#define GALAXY_CONFIG_WSSA_E80 (2 << 16)
69#define GALAXY_CONFIG_WSSA_F40 (3 << 16)
70
71#define GALAXY_CONFIG_WSS_ENABLE (1 << 18)
72
73#define GALAXY_CONFIG_CDIRQ_11 (1 << 19)
74#define GALAXY_CONFIG_CDIRQ_12 (1 << 20)
75#define GALAXY_CONFIG_CDIRQ_15 (1 << 21)
76#define GALAXY_CONFIG_CDIRQ_MASK (\
77 GALAXY_CONFIG_CDIRQ_11 | GALAXY_CONFIG_CDIRQ_12 |\
78 GALAXY_CONFIG_CDIRQ_15)
79
80#define GALAXY_CONFIG_CDDMA_DISABLE (0 << 22)
81#define GALAXY_CONFIG_CDDMA_0 (1 << 22)
82#define GALAXY_CONFIG_CDDMA_1 (2 << 22)
83#define GALAXY_CONFIG_CDDMA_3 (3 << 22)
84#define GALAXY_CONFIG_CDDMA_MASK GALAXY_CONFIG_CDDMA_3
85
86#define GALAXY_CONFIG_MASK (\
87 GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CD_MASK |\
88 GALAXY_CONFIG_UNUSED_MASK | GALAXY_CONFIG_CDIRQ_MASK |\
89 GALAXY_CONFIG_CDDMA_MASK)
90
91#include "galaxy.c"
diff --git a/sound/isa/galaxy/azt2316.c b/sound/isa/galaxy/azt2316.c
new file mode 100644
index 000000000000..189441141df6
--- /dev/null
+++ b/sound/isa/galaxy/azt2316.c
@@ -0,0 +1,111 @@
1/*
2 * Aztech AZT2316 Driver
3 * Copyright (C) 2007,2010 Rene Herman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#define AZT2316
21
22#define CRD_NAME "Aztech AZT2316"
23#define DRV_NAME "AZT2316"
24#define DEV_NAME "azt2316"
25
26#define GALAXY_DSP_MAJOR 3
27#define GALAXY_DSP_MINOR 1
28
29#define GALAXY_CONFIG_SIZE 4
30
31/*
32 * 32-bit config register
33 */
34
35#define GALAXY_CONFIG_SBA_220 (0 << 0)
36#define GALAXY_CONFIG_SBA_240 (1 << 0)
37#define GALAXY_CONFIG_SBA_260 (2 << 0)
38#define GALAXY_CONFIG_SBA_280 (3 << 0)
39#define GALAXY_CONFIG_SBA_MASK GALAXY_CONFIG_SBA_280
40
41#define GALAXY_CONFIG_SBIRQ_2 (1 << 2)
42#define GALAXY_CONFIG_SBIRQ_5 (1 << 3)
43#define GALAXY_CONFIG_SBIRQ_7 (1 << 4)
44#define GALAXY_CONFIG_SBIRQ_10 (1 << 5)
45
46#define GALAXY_CONFIG_SBDMA_DISABLE (0 << 6)
47#define GALAXY_CONFIG_SBDMA_0 (1 << 6)
48#define GALAXY_CONFIG_SBDMA_1 (2 << 6)
49#define GALAXY_CONFIG_SBDMA_3 (3 << 6)
50
51#define GALAXY_CONFIG_WSSA_530 (0 << 8)
52#define GALAXY_CONFIG_WSSA_604 (1 << 8)
53#define GALAXY_CONFIG_WSSA_E80 (2 << 8)
54#define GALAXY_CONFIG_WSSA_F40 (3 << 8)
55
56#define GALAXY_CONFIG_WSS_ENABLE (1 << 10)
57
58#define GALAXY_CONFIG_GAME_ENABLE (1 << 11)
59
60#define GALAXY_CONFIG_MPUA_300 (0 << 12)
61#define GALAXY_CONFIG_MPUA_330 (1 << 12)
62
63#define GALAXY_CONFIG_MPU_ENABLE (1 << 13)
64
65#define GALAXY_CONFIG_CDA_310 (0 << 14)
66#define GALAXY_CONFIG_CDA_320 (1 << 14)
67#define GALAXY_CONFIG_CDA_340 (2 << 14)
68#define GALAXY_CONFIG_CDA_350 (3 << 14)
69#define GALAXY_CONFIG_CDA_MASK GALAXY_CONFIG_CDA_350
70
71#define GALAXY_CONFIG_CD_DISABLE (0 << 16)
72#define GALAXY_CONFIG_CD_PANASONIC (1 << 16)
73#define GALAXY_CONFIG_CD_SONY (2 << 16)
74#define GALAXY_CONFIG_CD_MITSUMI (3 << 16)
75#define GALAXY_CONFIG_CD_AZTECH (4 << 16)
76#define GALAXY_CONFIG_CD_UNUSED_5 (5 << 16)
77#define GALAXY_CONFIG_CD_UNUSED_6 (6 << 16)
78#define GALAXY_CONFIG_CD_UNUSED_7 (7 << 16)
79#define GALAXY_CONFIG_CD_MASK GALAXY_CONFIG_CD_UNUSED_7
80
81#define GALAXY_CONFIG_CDDMA8_DISABLE (0 << 20)
82#define GALAXY_CONFIG_CDDMA8_0 (1 << 20)
83#define GALAXY_CONFIG_CDDMA8_1 (2 << 20)
84#define GALAXY_CONFIG_CDDMA8_3 (3 << 20)
85#define GALAXY_CONFIG_CDDMA8_MASK GALAXY_CONFIG_CDDMA8_3
86
87#define GALAXY_CONFIG_CDDMA16_DISABLE (0 << 22)
88#define GALAXY_CONFIG_CDDMA16_5 (1 << 22)
89#define GALAXY_CONFIG_CDDMA16_6 (2 << 22)
90#define GALAXY_CONFIG_CDDMA16_7 (3 << 22)
91#define GALAXY_CONFIG_CDDMA16_MASK GALAXY_CONFIG_CDDMA16_7
92
93#define GALAXY_CONFIG_MPUIRQ_2 (1 << 24)
94#define GALAXY_CONFIG_MPUIRQ_5 (1 << 25)
95#define GALAXY_CONFIG_MPUIRQ_7 (1 << 26)
96#define GALAXY_CONFIG_MPUIRQ_10 (1 << 27)
97
98#define GALAXY_CONFIG_CDIRQ_5 (1 << 28)
99#define GALAXY_CONFIG_CDIRQ_11 (1 << 29)
100#define GALAXY_CONFIG_CDIRQ_12 (1 << 30)
101#define GALAXY_CONFIG_CDIRQ_15 (1 << 31)
102#define GALAXY_CONFIG_CDIRQ_MASK (\
103 GALAXY_CONFIG_CDIRQ_5 | GALAXY_CONFIG_CDIRQ_11 |\
104 GALAXY_CONFIG_CDIRQ_12 | GALAXY_CONFIG_CDIRQ_15)
105
106#define GALAXY_CONFIG_MASK (\
107 GALAXY_CONFIG_SBA_MASK | GALAXY_CONFIG_CDA_MASK |\
108 GALAXY_CONFIG_CD_MASK | GALAXY_CONFIG_CDDMA16_MASK |\
109 GALAXY_CONFIG_CDDMA8_MASK | GALAXY_CONFIG_CDIRQ_MASK)
110
111#include "galaxy.c"
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
new file mode 100644
index 000000000000..ee54df082b9c
--- /dev/null
+++ b/sound/isa/galaxy/galaxy.c
@@ -0,0 +1,652 @@
1/*
2 * Aztech AZT1605/AZT2316 Driver
3 * Copyright (C) 2007,2010 Rene Herman
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/isa.h>
23#include <linux/delay.h>
24#include <linux/io.h>
25#include <asm/processor.h>
26#include <sound/core.h>
27#include <sound/initval.h>
28#include <sound/wss.h>
29#include <sound/mpu401.h>
30#include <sound/opl3.h>
31
32MODULE_DESCRIPTION(CRD_NAME);
33MODULE_AUTHOR("Rene Herman");
34MODULE_LICENSE("GPL");
35
36static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
37static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
38static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
39
40module_param_array(index, int, NULL, 0444);
41MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
42module_param_array(id, charp, NULL, 0444);
43MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
44module_param_array(enable, bool, NULL, 0444);
45MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
46
47static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
48static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
49static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
50static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
51static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
52static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
53static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
54static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
55
56module_param_array(port, long, NULL, 0444);
57MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
58module_param_array(wss_port, long, NULL, 0444);
59MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver.");
60module_param_array(mpu_port, long, NULL, 0444);
61MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
62module_param_array(fm_port, long, NULL, 0444);
63MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver.");
64module_param_array(irq, int, NULL, 0444);
65MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
66module_param_array(mpu_irq, int, NULL, 0444);
67MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
68module_param_array(dma1, int, NULL, 0444);
69MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver.");
70module_param_array(dma2, int, NULL, 0444);
71MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
72
73/*
74 * Generic SB DSP support routines
75 */
76
77#define DSP_PORT_RESET 0x6
78#define DSP_PORT_READ 0xa
79#define DSP_PORT_COMMAND 0xc
80#define DSP_PORT_STATUS 0xc
81#define DSP_PORT_DATA_AVAIL 0xe
82
83#define DSP_SIGNATURE 0xaa
84
85#define DSP_COMMAND_GET_VERSION 0xe1
86
87static int __devinit dsp_get_byte(void __iomem *port, u8 *val)
88{
89 int loops = 1000;
90
91 while (!(ioread8(port + DSP_PORT_DATA_AVAIL) & 0x80)) {
92 if (!loops--)
93 return -EIO;
94 cpu_relax();
95 }
96 *val = ioread8(port + DSP_PORT_READ);
97 return 0;
98}
99
100static int __devinit dsp_reset(void __iomem *port)
101{
102 u8 val;
103
104 iowrite8(1, port + DSP_PORT_RESET);
105 udelay(10);
106 iowrite8(0, port + DSP_PORT_RESET);
107
108 if (dsp_get_byte(port, &val) < 0 || val != DSP_SIGNATURE)
109 return -ENODEV;
110
111 return 0;
112}
113
114static int __devinit dsp_command(void __iomem *port, u8 cmd)
115{
116 int loops = 1000;
117
118 while (ioread8(port + DSP_PORT_STATUS) & 0x80) {
119 if (!loops--)
120 return -EIO;
121 cpu_relax();
122 }
123 iowrite8(cmd, port + DSP_PORT_COMMAND);
124 return 0;
125}
126
127static int __devinit dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
128{
129 int err;
130
131 err = dsp_command(port, DSP_COMMAND_GET_VERSION);
132 if (err < 0)
133 return err;
134
135 err = dsp_get_byte(port, major);
136 if (err < 0)
137 return err;
138
139 err = dsp_get_byte(port, minor);
140 if (err < 0)
141 return err;
142
143 return 0;
144}
145
146/*
147 * Generic WSS support routines
148 */
149
150#define WSS_CONFIG_DMA_0 (1 << 0)
151#define WSS_CONFIG_DMA_1 (2 << 0)
152#define WSS_CONFIG_DMA_3 (3 << 0)
153#define WSS_CONFIG_DUPLEX (1 << 2)
154#define WSS_CONFIG_IRQ_7 (1 << 3)
155#define WSS_CONFIG_IRQ_9 (2 << 3)
156#define WSS_CONFIG_IRQ_10 (3 << 3)
157#define WSS_CONFIG_IRQ_11 (4 << 3)
158
159#define WSS_PORT_CONFIG 0
160#define WSS_PORT_SIGNATURE 3
161
162#define WSS_SIGNATURE 4
163
164static int __devinit wss_detect(void __iomem *wss_port)
165{
166 if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE)
167 return -ENODEV;
168
169 return 0;
170}
171
172static void wss_set_config(void __iomem *wss_port, u8 wss_config)
173{
174 iowrite8(wss_config, wss_port + WSS_PORT_CONFIG);
175}
176
177/*
178 * Aztech Sound Galaxy specifics
179 */
180
181#define GALAXY_PORT_CONFIG 1024
182#define CONFIG_PORT_SET 4
183
184#define DSP_COMMAND_GALAXY_8 8
185#define GALAXY_COMMAND_GET_TYPE 5
186
187#define DSP_COMMAND_GALAXY_9 9
188#define GALAXY_COMMAND_WSSMODE 0
189#define GALAXY_COMMAND_SB8MODE 1
190
191#define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE
192#define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE
193
194struct snd_galaxy {
195 void __iomem *port;
196 void __iomem *config_port;
197 void __iomem *wss_port;
198 u32 config;
199 struct resource *res_port;
200 struct resource *res_config_port;
201 struct resource *res_wss_port;
202};
203
204static u32 config[SNDRV_CARDS];
205static u8 wss_config[SNDRV_CARDS];
206
207static int __devinit snd_galaxy_match(struct device *dev, unsigned int n)
208{
209 if (!enable[n])
210 return 0;
211
212 switch (port[n]) {
213 case SNDRV_AUTO_PORT:
214 dev_err(dev, "please specify port\n");
215 return 0;
216 case 0x220:
217 config[n] |= GALAXY_CONFIG_SBA_220;
218 break;
219 case 0x240:
220 config[n] |= GALAXY_CONFIG_SBA_240;
221 break;
222 case 0x260:
223 config[n] |= GALAXY_CONFIG_SBA_260;
224 break;
225 case 0x280:
226 config[n] |= GALAXY_CONFIG_SBA_280;
227 break;
228 default:
229 dev_err(dev, "invalid port %#lx\n", port[n]);
230 return 0;
231 }
232
233 switch (wss_port[n]) {
234 case SNDRV_AUTO_PORT:
235 dev_err(dev, "please specify wss_port\n");
236 return 0;
237 case 0x530:
238 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_530;
239 break;
240 case 0x604:
241 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_604;
242 break;
243 case 0xe80:
244 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_E80;
245 break;
246 case 0xf40:
247 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_F40;
248 break;
249 default:
250 dev_err(dev, "invalid WSS port %#lx\n", wss_port[n]);
251 return 0;
252 }
253
254 switch (irq[n]) {
255 case SNDRV_AUTO_IRQ:
256 dev_err(dev, "please specify irq\n");
257 return 0;
258 case 7:
259 wss_config[n] |= WSS_CONFIG_IRQ_7;
260 break;
261 case 2:
262 irq[n] = 9;
263 case 9:
264 wss_config[n] |= WSS_CONFIG_IRQ_9;
265 break;
266 case 10:
267 wss_config[n] |= WSS_CONFIG_IRQ_10;
268 break;
269 case 11:
270 wss_config[n] |= WSS_CONFIG_IRQ_11;
271 break;
272 default:
273 dev_err(dev, "invalid IRQ %d\n", irq[n]);
274 return 0;
275 }
276
277 switch (dma1[n]) {
278 case SNDRV_AUTO_DMA:
279 dev_err(dev, "please specify dma1\n");
280 return 0;
281 case 0:
282 wss_config[n] |= WSS_CONFIG_DMA_0;
283 break;
284 case 1:
285 wss_config[n] |= WSS_CONFIG_DMA_1;
286 break;
287 case 3:
288 wss_config[n] |= WSS_CONFIG_DMA_3;
289 break;
290 default:
291 dev_err(dev, "invalid playback DMA %d\n", dma1[n]);
292 return 0;
293 }
294
295 if (dma2[n] == SNDRV_AUTO_DMA || dma2[n] == dma1[n]) {
296 dma2[n] = -1;
297 goto mpu;
298 }
299
300 wss_config[n] |= WSS_CONFIG_DUPLEX;
301 switch (dma2[n]) {
302 case 0:
303 break;
304 case 1:
305 if (dma1[n] == 0)
306 break;
307 default:
308 dev_err(dev, "invalid capture DMA %d\n", dma2[n]);
309 return 0;
310 }
311
312mpu:
313 switch (mpu_port[n]) {
314 case SNDRV_AUTO_PORT:
315 dev_warn(dev, "mpu_port not specified; not using MPU-401\n");
316 mpu_port[n] = -1;
317 goto fm;
318 case 0x300:
319 config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_300;
320 break;
321 case 0x330:
322 config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_330;
323 break;
324 default:
325 dev_err(dev, "invalid MPU port %#lx\n", mpu_port[n]);
326 return 0;
327 }
328
329 switch (mpu_irq[n]) {
330 case SNDRV_AUTO_IRQ:
331 dev_warn(dev, "mpu_irq not specified: using polling mode\n");
332 mpu_irq[n] = -1;
333 break;
334 case 2:
335 mpu_irq[n] = 9;
336 case 9:
337 config[n] |= GALAXY_CONFIG_MPUIRQ_2;
338 break;
339#ifdef AZT1605
340 case 3:
341 config[n] |= GALAXY_CONFIG_MPUIRQ_3;
342 break;
343#endif
344 case 5:
345 config[n] |= GALAXY_CONFIG_MPUIRQ_5;
346 break;
347 case 7:
348 config[n] |= GALAXY_CONFIG_MPUIRQ_7;
349 break;
350#ifdef AZT2316
351 case 10:
352 config[n] |= GALAXY_CONFIG_MPUIRQ_10;
353 break;
354#endif
355 default:
356 dev_err(dev, "invalid MPU IRQ %d\n", mpu_irq[n]);
357 return 0;
358 }
359
360 if (mpu_irq[n] == irq[n]) {
361 dev_err(dev, "cannot share IRQ between WSS and MPU-401\n");
362 return 0;
363 }
364
365fm:
366 switch (fm_port[n]) {
367 case SNDRV_AUTO_PORT:
368 dev_warn(dev, "fm_port not specified: not using OPL3\n");
369 fm_port[n] = -1;
370 break;
371 case 0x388:
372 break;
373 default:
374 dev_err(dev, "illegal FM port %#lx\n", fm_port[n]);
375 return 0;
376 }
377
378 config[n] |= GALAXY_CONFIG_GAME_ENABLE;
379 return 1;
380}
381
382static int __devinit galaxy_init(struct snd_galaxy *galaxy, u8 *type)
383{
384 u8 major;
385 u8 minor;
386 int err;
387
388 err = dsp_reset(galaxy->port);
389 if (err < 0)
390 return err;
391
392 err = dsp_get_version(galaxy->port, &major, &minor);
393 if (err < 0)
394 return err;
395
396 if (major != GALAXY_DSP_MAJOR || minor != GALAXY_DSP_MINOR)
397 return -ENODEV;
398
399 err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_8);
400 if (err < 0)
401 return err;
402
403 err = dsp_command(galaxy->port, GALAXY_COMMAND_GET_TYPE);
404 if (err < 0)
405 return err;
406
407 err = dsp_get_byte(galaxy->port, type);
408 if (err < 0)
409 return err;
410
411 return 0;
412}
413
414static int __devinit galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
415{
416 int err;
417
418 err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_9);
419 if (err < 0)
420 return err;
421
422 err = dsp_command(galaxy->port, mode);
423 if (err < 0)
424 return err;
425
426#ifdef AZT1605
427 /*
428 * Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again
429 */
430 err = dsp_reset(galaxy->port);
431 if (err < 0)
432 return err;
433#endif
434
435 return 0;
436}
437
438static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config)
439{
440 u8 tmp = ioread8(galaxy->config_port + CONFIG_PORT_SET);
441 int i;
442
443 iowrite8(tmp | 0x80, galaxy->config_port + CONFIG_PORT_SET);
444 for (i = 0; i < GALAXY_CONFIG_SIZE; i++) {
445 iowrite8(config, galaxy->config_port + i);
446 config >>= 8;
447 }
448 iowrite8(tmp & 0x7f, galaxy->config_port + CONFIG_PORT_SET);
449 msleep(10);
450}
451
452static void __devinit galaxy_config(struct snd_galaxy *galaxy, u32 config)
453{
454 int i;
455
456 for (i = GALAXY_CONFIG_SIZE; i; i--) {
457 u8 tmp = ioread8(galaxy->config_port + i - 1);
458 galaxy->config = (galaxy->config << 8) | tmp;
459 }
460 config |= galaxy->config & GALAXY_CONFIG_MASK;
461 galaxy_set_config(galaxy, config);
462}
463
464static int __devinit galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
465{
466 int err;
467
468 err = wss_detect(galaxy->wss_port);
469 if (err < 0)
470 return err;
471
472 wss_set_config(galaxy->wss_port, wss_config);
473
474 err = galaxy_set_mode(galaxy, GALAXY_MODE_WSS);
475 if (err < 0)
476 return err;
477
478 return 0;
479}
480
481static void snd_galaxy_free(struct snd_card *card)
482{
483 struct snd_galaxy *galaxy = card->private_data;
484
485 if (galaxy->wss_port) {
486 wss_set_config(galaxy->wss_port, 0);
487 ioport_unmap(galaxy->wss_port);
488 release_and_free_resource(galaxy->res_wss_port);
489 }
490 if (galaxy->config_port) {
491 galaxy_set_config(galaxy, galaxy->config);
492 ioport_unmap(galaxy->config_port);
493 release_and_free_resource(galaxy->res_config_port);
494 }
495 if (galaxy->port) {
496 ioport_unmap(galaxy->port);
497 release_and_free_resource(galaxy->res_port);
498 }
499}
500
501static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
502{
503 struct snd_galaxy *galaxy;
504 struct snd_wss *chip;
505 struct snd_card *card;
506 u8 type;
507 int err;
508
509 err = snd_card_create(index[n], id[n], THIS_MODULE, sizeof *galaxy,
510 &card);
511 if (err < 0)
512 return err;
513
514 snd_card_set_dev(card, dev);
515
516 card->private_free = snd_galaxy_free;
517 galaxy = card->private_data;
518
519 galaxy->res_port = request_region(port[n], 16, DRV_NAME);
520 if (!galaxy->res_port) {
521 dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n],
522 port[n] + 15);
523 err = -EBUSY;
524 goto error;
525 }
526 galaxy->port = ioport_map(port[n], 16);
527
528 err = galaxy_init(galaxy, &type);
529 if (err < 0) {
530 dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]);
531 goto error;
532 }
533 dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]);
534
535 galaxy->res_config_port = request_region(port[n] + GALAXY_PORT_CONFIG,
536 16, DRV_NAME);
537 if (!galaxy->res_config_port) {
538 dev_err(dev, "could not grab ports %#lx-%#lx\n",
539 port[n] + GALAXY_PORT_CONFIG,
540 port[n] + GALAXY_PORT_CONFIG + 15);
541 err = -EBUSY;
542 goto error;
543 }
544 galaxy->config_port = ioport_map(port[n] + GALAXY_PORT_CONFIG, 16);
545
546 galaxy_config(galaxy, config[n]);
547
548 galaxy->res_wss_port = request_region(wss_port[n], 4, DRV_NAME);
549 if (!galaxy->res_wss_port) {
550 dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n],
551 wss_port[n] + 3);
552 err = -EBUSY;
553 goto error;
554 }
555 galaxy->wss_port = ioport_map(wss_port[n], 4);
556
557 err = galaxy_wss_config(galaxy, wss_config[n]);
558 if (err < 0) {
559 dev_err(dev, "could not configure WSS\n");
560 goto error;
561 }
562
563 strcpy(card->driver, DRV_NAME);
564 strcpy(card->shortname, DRV_NAME);
565 sprintf(card->longname, "%s at %#lx/%#lx, irq %d, dma %d/%d",
566 card->shortname, port[n], wss_port[n], irq[n], dma1[n],
567 dma2[n]);
568
569 err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n],
570 dma2[n], WSS_HW_DETECT, 0, &chip);
571 if (err < 0)
572 goto error;
573
574 err = snd_wss_pcm(chip, 0, NULL);
575 if (err < 0)
576 goto error;
577
578 err = snd_wss_mixer(chip);
579 if (err < 0)
580 goto error;
581
582 err = snd_wss_timer(chip, 0, NULL);
583 if (err < 0)
584 goto error;
585
586 if (mpu_port[n] >= 0) {
587 err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
588 mpu_port[n], 0, mpu_irq[n],
589 IRQF_DISABLED, NULL);
590 if (err < 0)
591 goto error;
592 }
593
594 if (fm_port[n] >= 0) {
595 struct snd_opl3 *opl3;
596
597 err = snd_opl3_create(card, fm_port[n], fm_port[n] + 2,
598 OPL3_HW_AUTO, 0, &opl3);
599 if (err < 0) {
600 dev_err(dev, "no OPL device at %#lx\n", fm_port[n]);
601 goto error;
602 }
603 err = snd_opl3_timer_new(opl3, 1, 2);
604 if (err < 0)
605 goto error;
606
607 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
608 if (err < 0)
609 goto error;
610 }
611
612 err = snd_card_register(card);
613 if (err < 0)
614 goto error;
615
616 dev_set_drvdata(dev, card);
617 return 0;
618
619error:
620 snd_card_free(card);
621 return err;
622}
623
624static int __devexit snd_galaxy_remove(struct device *dev, unsigned int n)
625{
626 snd_card_free(dev_get_drvdata(dev));
627 dev_set_drvdata(dev, NULL);
628 return 0;
629}
630
631static struct isa_driver snd_galaxy_driver = {
632 .match = snd_galaxy_match,
633 .probe = snd_galaxy_probe,
634 .remove = __devexit_p(snd_galaxy_remove),
635
636 .driver = {
637 .name = DEV_NAME
638 }
639};
640
641static int __init alsa_card_galaxy_init(void)
642{
643 return isa_register_driver(&snd_galaxy_driver, SNDRV_CARDS);
644}
645
646static void __exit alsa_card_galaxy_exit(void)
647{
648 isa_unregister_driver(&snd_galaxy_driver);
649}
650
651module_init(alsa_card_galaxy_init);
652module_exit(alsa_card_galaxy_exit);
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index f26eac8d8110..3e4a58b72913 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -191,7 +191,7 @@ static int __devinit snd_gusmax_mixer(struct snd_wss *chip)
191 191
192static void snd_gusmax_free(struct snd_card *card) 192static void snd_gusmax_free(struct snd_card *card)
193{ 193{
194 struct snd_gusmax *maxcard = (struct snd_gusmax *)card->private_data; 194 struct snd_gusmax *maxcard = card->private_data;
195 195
196 if (maxcard == NULL) 196 if (maxcard == NULL)
197 return; 197 return;
@@ -219,7 +219,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
219 if (err < 0) 219 if (err < 0)
220 return err; 220 return err;
221 card->private_free = snd_gusmax_free; 221 card->private_free = snd_gusmax_free;
222 maxcard = (struct snd_gusmax *)card->private_data; 222 maxcard = card->private_data;
223 maxcard->card = card; 223 maxcard->card = card;
224 maxcard->irq = -1; 224 maxcard->irq = -1;
225 225
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 81284a8fa0ce..2259e3f726a7 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -72,7 +72,7 @@ static irqreturn_t snd_sb8_interrupt(int irq, void *dev_id)
72 72
73static void snd_sb8_free(struct snd_card *card) 73static void snd_sb8_free(struct snd_card *card)
74{ 74{
75 struct snd_sb8 *acard = (struct snd_sb8 *)card->private_data; 75 struct snd_sb8 *acard = card->private_data;
76 76
77 if (acard == NULL) 77 if (acard == NULL)
78 return; 78 return;
diff --git a/sound/isa/sgalaxy.c b/sound/isa/sgalaxy.c
deleted file mode 100644
index 6fe27b9d9440..000000000000
--- a/sound/isa/sgalaxy.c
+++ /dev/null
@@ -1,369 +0,0 @@
1/*
2 * Driver for Aztech Sound Galaxy cards
3 * Copyright (c) by Christopher Butler <chrisb@sandy.force9.co.uk.
4 *
5 * I don't have documentation for this card, I based this driver on the
6 * driver for OSS/Free included in the kernel source (drivers/sound/sgalaxy.c)
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24#include <linux/init.h>
25#include <linux/err.h>
26#include <linux/isa.h>
27#include <linux/delay.h>
28#include <linux/time.h>
29#include <linux/interrupt.h>
30#include <linux/moduleparam.h>
31#include <asm/dma.h>
32#include <sound/core.h>
33#include <sound/sb.h>
34#include <sound/wss.h>
35#include <sound/control.h>
36#define SNDRV_LEGACY_FIND_FREE_IRQ
37#define SNDRV_LEGACY_FIND_FREE_DMA
38#include <sound/initval.h>
39
40MODULE_AUTHOR("Christopher Butler <chrisb@sandy.force9.co.uk>");
41MODULE_DESCRIPTION("Aztech Sound Galaxy");
42MODULE_LICENSE("GPL");
43MODULE_SUPPORTED_DEVICE("{{Aztech Systems,Sound Galaxy}}");
44
45static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
46static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
47static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
48static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240 */
49static long wssport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530,0xe80,0xf40,0x604 */
50static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 7,9,10,11 */
51static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
52
53module_param_array(index, int, NULL, 0444);
54MODULE_PARM_DESC(index, "Index value for Sound Galaxy soundcard.");
55module_param_array(id, charp, NULL, 0444);
56MODULE_PARM_DESC(id, "ID string for Sound Galaxy soundcard.");
57module_param_array(sbport, long, NULL, 0444);
58MODULE_PARM_DESC(sbport, "Port # for Sound Galaxy SB driver.");
59module_param_array(wssport, long, NULL, 0444);
60MODULE_PARM_DESC(wssport, "Port # for Sound Galaxy WSS driver.");
61module_param_array(irq, int, NULL, 0444);
62MODULE_PARM_DESC(irq, "IRQ # for Sound Galaxy driver.");
63module_param_array(dma1, int, NULL, 0444);
64MODULE_PARM_DESC(dma1, "DMA1 # for Sound Galaxy driver.");
65
66#define SGALAXY_AUXC_LEFT 18
67#define SGALAXY_AUXC_RIGHT 19
68
69#define PFX "sgalaxy: "
70
71/*
72
73 */
74
75#define AD1848P1( port, x ) ( port + c_d_c_AD1848##x )
76
77/* from lowlevel/sb/sb.c - to avoid having to allocate a struct snd_sb for the */
78/* short time we actually need it.. */
79
80static int snd_sgalaxy_sbdsp_reset(unsigned long port)
81{
82 int i;
83
84 outb(1, SBP1(port, RESET));
85 udelay(10);
86 outb(0, SBP1(port, RESET));
87 udelay(30);
88 for (i = 0; i < 1000 && !(inb(SBP1(port, DATA_AVAIL)) & 0x80); i++);
89 if (inb(SBP1(port, READ)) != 0xaa) {
90 snd_printd("sb_reset: failed at 0x%lx!!!\n", port);
91 return -ENODEV;
92 }
93 return 0;
94}
95
96static int __devinit snd_sgalaxy_sbdsp_command(unsigned long port,
97 unsigned char val)
98{
99 int i;
100
101 for (i = 10000; i; i--)
102 if ((inb(SBP1(port, STATUS)) & 0x80) == 0) {
103 outb(val, SBP1(port, COMMAND));
104 return 1;
105 }
106
107 return 0;
108}
109
110static irqreturn_t snd_sgalaxy_dummy_interrupt(int irq, void *dev_id)
111{
112 return IRQ_NONE;
113}
114
115static int __devinit snd_sgalaxy_setup_wss(unsigned long port, int irq, int dma)
116{
117 static int interrupt_bits[] = {-1, -1, -1, -1, -1, -1, -1, 0x08, -1,
118 0x10, 0x18, 0x20, -1, -1, -1, -1};
119 static int dma_bits[] = {1, 2, 0, 3};
120 int tmp, tmp1;
121
122 if ((tmp = inb(port + 3)) == 0xff)
123 {
124 snd_printdd("I/O address dead (0x%lx)\n", port);
125 return 0;
126 }
127#if 0
128 snd_printdd("WSS signature = 0x%x\n", tmp);
129#endif
130
131 if ((tmp & 0x3f) != 0x04 &&
132 (tmp & 0x3f) != 0x0f &&
133 (tmp & 0x3f) != 0x00) {
134 snd_printdd("No WSS signature detected on port 0x%lx\n",
135 port + 3);
136 return 0;
137 }
138
139#if 0
140 snd_printdd(PFX "setting up IRQ/DMA for WSS\n");
141#endif
142
143 /* initialize IRQ for WSS codec */
144 tmp = interrupt_bits[irq % 16];
145 if (tmp < 0)
146 return -EINVAL;
147
148 if (request_irq(irq, snd_sgalaxy_dummy_interrupt, IRQF_DISABLED, "sgalaxy", NULL)) {
149 snd_printk(KERN_ERR "sgalaxy: can't grab irq %d\n", irq);
150 return -EIO;
151 }
152
153 outb(tmp | 0x40, port);
154 tmp1 = dma_bits[dma % 4];
155 outb(tmp | tmp1, port);
156
157 free_irq(irq, NULL);
158
159 return 0;
160}
161
162static int __devinit snd_sgalaxy_detect(int dev, int irq, int dma)
163{
164#if 0
165 snd_printdd(PFX "switching to WSS mode\n");
166#endif
167
168 /* switch to WSS mode */
169 snd_sgalaxy_sbdsp_reset(sbport[dev]);
170
171 snd_sgalaxy_sbdsp_command(sbport[dev], 9);
172 snd_sgalaxy_sbdsp_command(sbport[dev], 0);
173
174 udelay(400);
175 return snd_sgalaxy_setup_wss(wssport[dev], irq, dma);
176}
177
178static struct snd_kcontrol_new snd_sgalaxy_controls[] = {
179WSS_DOUBLE("Aux Playback Switch", 0,
180 SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 7, 7, 1, 1),
181WSS_DOUBLE("Aux Playback Volume", 0,
182 SGALAXY_AUXC_LEFT, SGALAXY_AUXC_RIGHT, 0, 0, 31, 0)
183};
184
185static int __devinit snd_sgalaxy_mixer(struct snd_wss *chip)
186{
187 struct snd_card *card = chip->card;
188 struct snd_ctl_elem_id id1, id2;
189 unsigned int idx;
190 int err;
191
192 memset(&id1, 0, sizeof(id1));
193 memset(&id2, 0, sizeof(id2));
194 id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
195 /* reassign AUX0 to LINE */
196 strcpy(id1.name, "Aux Playback Switch");
197 strcpy(id2.name, "Line Playback Switch");
198 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
199 return err;
200 strcpy(id1.name, "Aux Playback Volume");
201 strcpy(id2.name, "Line Playback Volume");
202 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
203 return err;
204 /* reassign AUX1 to FM */
205 strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
206 strcpy(id2.name, "FM Playback Switch");
207 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
208 return err;
209 strcpy(id1.name, "Aux Playback Volume");
210 strcpy(id2.name, "FM Playback Volume");
211 if ((err = snd_ctl_rename_id(card, &id1, &id2)) < 0)
212 return err;
213 /* build AUX2 input */
214 for (idx = 0; idx < ARRAY_SIZE(snd_sgalaxy_controls); idx++) {
215 err = snd_ctl_add(card,
216 snd_ctl_new1(&snd_sgalaxy_controls[idx], chip));
217 if (err < 0)
218 return err;
219 }
220 return 0;
221}
222
223static int __devinit snd_sgalaxy_match(struct device *devptr, unsigned int dev)
224{
225 if (!enable[dev])
226 return 0;
227 if (sbport[dev] == SNDRV_AUTO_PORT) {
228 snd_printk(KERN_ERR PFX "specify SB port\n");
229 return 0;
230 }
231 if (wssport[dev] == SNDRV_AUTO_PORT) {
232 snd_printk(KERN_ERR PFX "specify WSS port\n");
233 return 0;
234 }
235 return 1;
236}
237
238static int __devinit snd_sgalaxy_probe(struct device *devptr, unsigned int dev)
239{
240 static int possible_irqs[] = {7, 9, 10, 11, -1};
241 static int possible_dmas[] = {1, 3, 0, -1};
242 int err, xirq, xdma1;
243 struct snd_card *card;
244 struct snd_wss *chip;
245
246 err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
247 if (err < 0)
248 return err;
249
250 xirq = irq[dev];
251 if (xirq == SNDRV_AUTO_IRQ) {
252 if ((xirq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
253 snd_printk(KERN_ERR PFX "unable to find a free IRQ\n");
254 err = -EBUSY;
255 goto _err;
256 }
257 }
258 xdma1 = dma1[dev];
259 if (xdma1 == SNDRV_AUTO_DMA) {
260 if ((xdma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
261 snd_printk(KERN_ERR PFX "unable to find a free DMA\n");
262 err = -EBUSY;
263 goto _err;
264 }
265 }
266
267 if ((err = snd_sgalaxy_detect(dev, xirq, xdma1)) < 0)
268 goto _err;
269
270 err = snd_wss_create(card, wssport[dev] + 4, -1,
271 xirq, xdma1, -1,
272 WSS_HW_DETECT, 0, &chip);
273 if (err < 0)
274 goto _err;
275 card->private_data = chip;
276
277 err = snd_wss_pcm(chip, 0, NULL);
278 if (err < 0) {
279 snd_printdd(PFX "error creating new WSS PCM device\n");
280 goto _err;
281 }
282 err = snd_wss_mixer(chip);
283 if (err < 0) {
284 snd_printdd(PFX "error creating new WSS mixer\n");
285 goto _err;
286 }
287 if ((err = snd_sgalaxy_mixer(chip)) < 0) {
288 snd_printdd(PFX "the mixer rewrite failed\n");
289 goto _err;
290 }
291
292 strcpy(card->driver, "Sound Galaxy");
293 strcpy(card->shortname, "Sound Galaxy");
294 sprintf(card->longname, "Sound Galaxy at 0x%lx, irq %d, dma %d",
295 wssport[dev], xirq, xdma1);
296
297 snd_card_set_dev(card, devptr);
298
299 if ((err = snd_card_register(card)) < 0)
300 goto _err;
301
302 dev_set_drvdata(devptr, card);
303 return 0;
304
305 _err:
306 snd_card_free(card);
307 return err;
308}
309
310static int __devexit snd_sgalaxy_remove(struct device *devptr, unsigned int dev)
311{
312 snd_card_free(dev_get_drvdata(devptr));
313 dev_set_drvdata(devptr, NULL);
314 return 0;
315}
316
317#ifdef CONFIG_PM
318static int snd_sgalaxy_suspend(struct device *pdev, unsigned int n,
319 pm_message_t state)
320{
321 struct snd_card *card = dev_get_drvdata(pdev);
322 struct snd_wss *chip = card->private_data;
323
324 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
325 chip->suspend(chip);
326 return 0;
327}
328
329static int snd_sgalaxy_resume(struct device *pdev, unsigned int n)
330{
331 struct snd_card *card = dev_get_drvdata(pdev);
332 struct snd_wss *chip = card->private_data;
333
334 chip->resume(chip);
335 snd_wss_out(chip, SGALAXY_AUXC_LEFT, chip->image[SGALAXY_AUXC_LEFT]);
336 snd_wss_out(chip, SGALAXY_AUXC_RIGHT, chip->image[SGALAXY_AUXC_RIGHT]);
337
338 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
339 return 0;
340}
341#endif
342
343#define DEV_NAME "sgalaxy"
344
345static struct isa_driver snd_sgalaxy_driver = {
346 .match = snd_sgalaxy_match,
347 .probe = snd_sgalaxy_probe,
348 .remove = __devexit_p(snd_sgalaxy_remove),
349#ifdef CONFIG_PM
350 .suspend = snd_sgalaxy_suspend,
351 .resume = snd_sgalaxy_resume,
352#endif
353 .driver = {
354 .name = DEV_NAME
355 },
356};
357
358static int __init alsa_card_sgalaxy_init(void)
359{
360 return isa_register_driver(&snd_sgalaxy_driver, SNDRV_CARDS);
361}
362
363static void __exit alsa_card_sgalaxy_exit(void)
364{
365 isa_unregister_driver(&snd_sgalaxy_driver);
366}
367
368module_init(alsa_card_sgalaxy_init)
369module_exit(alsa_card_sgalaxy_exit)
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index a513651fa149..76c090218073 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -545,11 +545,3 @@ config SOUND_KAHLUA
545 545
546endif # SOUND_OSS 546endif # SOUND_OSS
547 547
548config SOUND_SH_DAC_AUDIO
549 tristate "SuperH DAC audio support"
550 depends on CPU_SH3 && HIGH_RES_TIMERS
551
552config SOUND_SH_DAC_AUDIO_CHANNEL
553 int "DAC channel"
554 default "1"
555 depends on SOUND_SH_DAC_AUDIO
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 567b8a74178a..96f14dcd0cd1 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -9,7 +9,6 @@ obj-$(CONFIG_SOUND_OSS) += sound.o
9 9
10# Please leave it as is, cause the link order is significant ! 10# Please leave it as is, cause the link order is significant !
11 11
12obj-$(CONFIG_SOUND_SH_DAC_AUDIO) += sh_dac_audio.o
13obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o 12obj-$(CONFIG_SOUND_AEDSP16) += aedsp16.o
14obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o 13obj-$(CONFIG_SOUND_PSS) += pss.o ad1848.o mpu401.o
15obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o 14obj-$(CONFIG_SOUND_TRIX) += trix.o ad1848.o sb_lib.o uart401.o
diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c
index c6f2621221ba..a8f626d99c5b 100644
--- a/sound/oss/au1550_ac97.c
+++ b/sound/oss/au1550_ac97.c
@@ -43,7 +43,6 @@
43#include <linux/sound.h> 43#include <linux/sound.h>
44#include <linux/slab.h> 44#include <linux/slab.h>
45#include <linux/soundcard.h> 45#include <linux/soundcard.h>
46#include <linux/smp_lock.h>
47#include <linux/init.h> 46#include <linux/init.h>
48#include <linux/interrupt.h> 47#include <linux/interrupt.h>
49#include <linux/kernel.h> 48#include <linux/kernel.h>
@@ -77,6 +76,7 @@
77/* Boot options 76/* Boot options
78 * 0 = no VRA, 1 = use VRA if codec supports it 77 * 0 = no VRA, 1 = use VRA if codec supports it
79 */ 78 */
79static DEFINE_MUTEX(au1550_ac97_mutex);
80static int vra = 1; 80static int vra = 1;
81module_param(vra, bool, 0); 81module_param(vra, bool, 0);
82MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it"); 82MODULE_PARM_DESC(vra, "if 1 use VRA if codec supports it");
@@ -171,7 +171,7 @@ au1550_delay(int msec)
171static u16 171static u16
172rdcodec(struct ac97_codec *codec, u8 addr) 172rdcodec(struct ac97_codec *codec, u8 addr)
173{ 173{
174 struct au1550_state *s = (struct au1550_state *)codec->private_data; 174 struct au1550_state *s = codec->private_data;
175 unsigned long flags; 175 unsigned long flags;
176 u32 cmd, val; 176 u32 cmd, val;
177 u16 data; 177 u16 data;
@@ -239,7 +239,7 @@ rdcodec(struct ac97_codec *codec, u8 addr)
239static void 239static void
240wrcodec(struct ac97_codec *codec, u8 addr, u16 data) 240wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
241{ 241{
242 struct au1550_state *s = (struct au1550_state *)codec->private_data; 242 struct au1550_state *s = codec->private_data;
243 unsigned long flags; 243 unsigned long flags;
244 u32 cmd, val; 244 u32 cmd, val;
245 int i; 245 int i;
@@ -798,9 +798,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin)
798static int 798static int
799au1550_open_mixdev(struct inode *inode, struct file *file) 799au1550_open_mixdev(struct inode *inode, struct file *file)
800{ 800{
801 lock_kernel(); 801 mutex_lock(&au1550_ac97_mutex);
802 file->private_data = &au1550_state; 802 file->private_data = &au1550_state;
803 unlock_kernel(); 803 mutex_unlock(&au1550_ac97_mutex);
804 return 0; 804 return 0;
805} 805}
806 806
@@ -820,13 +820,13 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
820static long 820static long
821au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg) 821au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg)
822{ 822{
823 struct au1550_state *s = (struct au1550_state *)file->private_data; 823 struct au1550_state *s = file->private_data;
824 struct ac97_codec *codec = s->codec; 824 struct ac97_codec *codec = s->codec;
825 int ret; 825 int ret;
826 826
827 lock_kernel(); 827 mutex_lock(&au1550_ac97_mutex);
828 ret = mixdev_ioctl(codec, cmd, arg); 828 ret = mixdev_ioctl(codec, cmd, arg);
829 unlock_kernel(); 829 mutex_unlock(&au1550_ac97_mutex);
830 830
831 return ret; 831 return ret;
832} 832}
@@ -1031,7 +1031,7 @@ copy_dmabuf_user(struct dmabuf *db, char* userbuf, int count, int to_user)
1031static ssize_t 1031static ssize_t
1032au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos) 1032au1550_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
1033{ 1033{
1034 struct au1550_state *s = (struct au1550_state *)file->private_data; 1034 struct au1550_state *s = file->private_data;
1035 struct dmabuf *db = &s->dma_adc; 1035 struct dmabuf *db = &s->dma_adc;
1036 DECLARE_WAITQUEUE(wait, current); 1036 DECLARE_WAITQUEUE(wait, current);
1037 ssize_t ret; 1037 ssize_t ret;
@@ -1111,7 +1111,7 @@ out2:
1111static ssize_t 1111static ssize_t
1112au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos) 1112au1550_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
1113{ 1113{
1114 struct au1550_state *s = (struct au1550_state *)file->private_data; 1114 struct au1550_state *s = file->private_data;
1115 struct dmabuf *db = &s->dma_dac; 1115 struct dmabuf *db = &s->dma_dac;
1116 DECLARE_WAITQUEUE(wait, current); 1116 DECLARE_WAITQUEUE(wait, current);
1117 ssize_t ret = 0; 1117 ssize_t ret = 0;
@@ -1211,7 +1211,7 @@ out2:
1211static unsigned int 1211static unsigned int
1212au1550_poll(struct file *file, struct poll_table_struct *wait) 1212au1550_poll(struct file *file, struct poll_table_struct *wait)
1213{ 1213{
1214 struct au1550_state *s = (struct au1550_state *)file->private_data; 1214 struct au1550_state *s = file->private_data;
1215 unsigned long flags; 1215 unsigned long flags;
1216 unsigned int mask = 0; 1216 unsigned int mask = 0;
1217 1217
@@ -1250,12 +1250,12 @@ au1550_poll(struct file *file, struct poll_table_struct *wait)
1250static int 1250static int
1251au1550_mmap(struct file *file, struct vm_area_struct *vma) 1251au1550_mmap(struct file *file, struct vm_area_struct *vma)
1252{ 1252{
1253 struct au1550_state *s = (struct au1550_state *)file->private_data; 1253 struct au1550_state *s = file->private_data;
1254 struct dmabuf *db; 1254 struct dmabuf *db;
1255 unsigned long size; 1255 unsigned long size;
1256 int ret = 0; 1256 int ret = 0;
1257 1257
1258 lock_kernel(); 1258 mutex_lock(&au1550_ac97_mutex);
1259 mutex_lock(&s->sem); 1259 mutex_lock(&s->sem);
1260 if (vma->vm_flags & VM_WRITE) 1260 if (vma->vm_flags & VM_WRITE)
1261 db = &s->dma_dac; 1261 db = &s->dma_dac;
@@ -1283,7 +1283,7 @@ au1550_mmap(struct file *file, struct vm_area_struct *vma)
1283 db->mapped = 1; 1283 db->mapped = 1;
1284out: 1284out:
1285 mutex_unlock(&s->sem); 1285 mutex_unlock(&s->sem);
1286 unlock_kernel(); 1286 mutex_unlock(&au1550_ac97_mutex);
1287 return ret; 1287 return ret;
1288} 1288}
1289 1289
@@ -1342,7 +1342,7 @@ dma_count_done(struct dmabuf *db)
1342static int 1342static int
1343au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 1343au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1344{ 1344{
1345 struct au1550_state *s = (struct au1550_state *)file->private_data; 1345 struct au1550_state *s = file->private_data;
1346 unsigned long flags; 1346 unsigned long flags;
1347 audio_buf_info abinfo; 1347 audio_buf_info abinfo;
1348 count_info cinfo; 1348 count_info cinfo;
@@ -1781,9 +1781,9 @@ au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1781{ 1781{
1782 int ret; 1782 int ret;
1783 1783
1784 lock_kernel(); 1784 mutex_lock(&au1550_ac97_mutex);
1785 ret = au1550_ioctl(file, cmd, arg); 1785 ret = au1550_ioctl(file, cmd, arg);
1786 unlock_kernel(); 1786 mutex_unlock(&au1550_ac97_mutex);
1787 1787
1788 return ret; 1788 return ret;
1789} 1789}
@@ -1804,7 +1804,7 @@ au1550_open(struct inode *inode, struct file *file)
1804#endif 1804#endif
1805 1805
1806 file->private_data = s; 1806 file->private_data = s;
1807 lock_kernel(); 1807 mutex_lock(&au1550_ac97_mutex);
1808 /* wait for device to become free */ 1808 /* wait for device to become free */
1809 mutex_lock(&s->open_mutex); 1809 mutex_lock(&s->open_mutex);
1810 while (s->open_mode & file->f_mode) { 1810 while (s->open_mode & file->f_mode) {
@@ -1861,21 +1861,21 @@ au1550_open(struct inode *inode, struct file *file)
1861out: 1861out:
1862 mutex_unlock(&s->open_mutex); 1862 mutex_unlock(&s->open_mutex);
1863out2: 1863out2:
1864 unlock_kernel(); 1864 mutex_unlock(&au1550_ac97_mutex);
1865 return ret; 1865 return ret;
1866} 1866}
1867 1867
1868static int 1868static int
1869au1550_release(struct inode *inode, struct file *file) 1869au1550_release(struct inode *inode, struct file *file)
1870{ 1870{
1871 struct au1550_state *s = (struct au1550_state *)file->private_data; 1871 struct au1550_state *s = file->private_data;
1872 1872
1873 lock_kernel(); 1873 mutex_lock(&au1550_ac97_mutex);
1874 1874
1875 if (file->f_mode & FMODE_WRITE) { 1875 if (file->f_mode & FMODE_WRITE) {
1876 unlock_kernel(); 1876 mutex_unlock(&au1550_ac97_mutex);
1877 drain_dac(s, file->f_flags & O_NONBLOCK); 1877 drain_dac(s, file->f_flags & O_NONBLOCK);
1878 lock_kernel(); 1878 mutex_lock(&au1550_ac97_mutex);
1879 } 1879 }
1880 1880
1881 mutex_lock(&s->open_mutex); 1881 mutex_lock(&s->open_mutex);
@@ -1892,7 +1892,7 @@ au1550_release(struct inode *inode, struct file *file)
1892 s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE)); 1892 s->open_mode &= ((~file->f_mode) & (FMODE_READ|FMODE_WRITE));
1893 mutex_unlock(&s->open_mutex); 1893 mutex_unlock(&s->open_mutex);
1894 wake_up(&s->open_wait); 1894 wake_up(&s->open_wait);
1895 unlock_kernel(); 1895 mutex_unlock(&au1550_ac97_mutex);
1896 return 0; 1896 return 0;
1897} 1897}
1898 1898
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index 6ecd41abb066..87e2c72651f5 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -181,7 +181,7 @@
181#include <linux/init.h> 181#include <linux/init.h>
182#include <linux/soundcard.h> 182#include <linux/soundcard.h>
183#include <linux/poll.h> 183#include <linux/poll.h>
184#include <linux/smp_lock.h> 184#include <linux/mutex.h>
185 185
186#include <asm/uaccess.h> 186#include <asm/uaccess.h>
187 187
@@ -194,6 +194,7 @@
194 * Declarations 194 * Declarations
195 */ 195 */
196 196
197static DEFINE_MUTEX(dmasound_core_mutex);
197int dmasound_catchRadius = 0; 198int dmasound_catchRadius = 0;
198module_param(dmasound_catchRadius, int, 0); 199module_param(dmasound_catchRadius, int, 0);
199 200
@@ -323,22 +324,22 @@ static struct {
323 324
324static int mixer_open(struct inode *inode, struct file *file) 325static int mixer_open(struct inode *inode, struct file *file)
325{ 326{
326 lock_kernel(); 327 mutex_lock(&dmasound_core_mutex);
327 if (!try_module_get(dmasound.mach.owner)) { 328 if (!try_module_get(dmasound.mach.owner)) {
328 unlock_kernel(); 329 mutex_unlock(&dmasound_core_mutex);
329 return -ENODEV; 330 return -ENODEV;
330 } 331 }
331 mixer.busy = 1; 332 mixer.busy = 1;
332 unlock_kernel(); 333 mutex_unlock(&dmasound_core_mutex);
333 return 0; 334 return 0;
334} 335}
335 336
336static int mixer_release(struct inode *inode, struct file *file) 337static int mixer_release(struct inode *inode, struct file *file)
337{ 338{
338 lock_kernel(); 339 mutex_lock(&dmasound_core_mutex);
339 mixer.busy = 0; 340 mixer.busy = 0;
340 module_put(dmasound.mach.owner); 341 module_put(dmasound.mach.owner);
341 unlock_kernel(); 342 mutex_unlock(&dmasound_core_mutex);
342 return 0; 343 return 0;
343} 344}
344 345
@@ -370,9 +371,9 @@ static long mixer_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
370{ 371{
371 int ret; 372 int ret;
372 373
373 lock_kernel(); 374 mutex_lock(&dmasound_core_mutex);
374 ret = mixer_ioctl(file, cmd, arg); 375 ret = mixer_ioctl(file, cmd, arg);
375 unlock_kernel(); 376 mutex_unlock(&dmasound_core_mutex);
376 377
377 return ret; 378 return ret;
378} 379}
@@ -752,9 +753,9 @@ static int sq_open(struct inode *inode, struct file *file)
752{ 753{
753 int rc; 754 int rc;
754 755
755 lock_kernel(); 756 mutex_lock(&dmasound_core_mutex);
756 if (!try_module_get(dmasound.mach.owner)) { 757 if (!try_module_get(dmasound.mach.owner)) {
757 unlock_kernel(); 758 mutex_unlock(&dmasound_core_mutex);
758 return -ENODEV; 759 return -ENODEV;
759 } 760 }
760 761
@@ -799,11 +800,11 @@ static int sq_open(struct inode *inode, struct file *file)
799 sound_set_format(AFMT_MU_LAW); 800 sound_set_format(AFMT_MU_LAW);
800 } 801 }
801#endif 802#endif
802 unlock_kernel(); 803 mutex_unlock(&dmasound_core_mutex);
803 return 0; 804 return 0;
804 out: 805 out:
805 module_put(dmasound.mach.owner); 806 module_put(dmasound.mach.owner);
806 unlock_kernel(); 807 mutex_unlock(&dmasound_core_mutex);
807 return rc; 808 return rc;
808} 809}
809 810
@@ -869,7 +870,7 @@ static int sq_release(struct inode *inode, struct file *file)
869{ 870{
870 int rc = 0; 871 int rc = 0;
871 872
872 lock_kernel(); 873 mutex_lock(&dmasound_core_mutex);
873 874
874 if (file->f_mode & FMODE_WRITE) { 875 if (file->f_mode & FMODE_WRITE) {
875 if (write_sq.busy) 876 if (write_sq.busy)
@@ -900,7 +901,7 @@ static int sq_release(struct inode *inode, struct file *file)
900 write_sq_wake_up(file); /* checks f_mode */ 901 write_sq_wake_up(file); /* checks f_mode */
901#endif /* blocking open() */ 902#endif /* blocking open() */
902 903
903 unlock_kernel(); 904 mutex_unlock(&dmasound_core_mutex);
904 905
905 return rc; 906 return rc;
906} 907}
@@ -1141,9 +1142,9 @@ static long sq_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
1141{ 1142{
1142 int ret; 1143 int ret;
1143 1144
1144 lock_kernel(); 1145 mutex_lock(&dmasound_core_mutex);
1145 ret = sq_ioctl(file, cmd, arg); 1146 ret = sq_ioctl(file, cmd, arg);
1146 unlock_kernel(); 1147 mutex_unlock(&dmasound_core_mutex);
1147 1148
1148 return ret; 1149 return ret;
1149} 1150}
@@ -1257,7 +1258,7 @@ static int state_open(struct inode *inode, struct file *file)
1257 int len = 0; 1258 int len = 0;
1258 int ret; 1259 int ret;
1259 1260
1260 lock_kernel(); 1261 mutex_lock(&dmasound_core_mutex);
1261 ret = -EBUSY; 1262 ret = -EBUSY;
1262 if (state.busy) 1263 if (state.busy)
1263 goto out; 1264 goto out;
@@ -1329,16 +1330,16 @@ printk("dmasound: stat buffer used %d bytes\n", len) ;
1329 state.len = len; 1330 state.len = len;
1330 ret = 0; 1331 ret = 0;
1331out: 1332out:
1332 unlock_kernel(); 1333 mutex_unlock(&dmasound_core_mutex);
1333 return ret; 1334 return ret;
1334} 1335}
1335 1336
1336static int state_release(struct inode *inode, struct file *file) 1337static int state_release(struct inode *inode, struct file *file)
1337{ 1338{
1338 lock_kernel(); 1339 mutex_lock(&dmasound_core_mutex);
1339 state.busy = 0; 1340 state.busy = 0;
1340 module_put(dmasound.mach.owner); 1341 module_put(dmasound.mach.owner);
1341 unlock_kernel(); 1342 mutex_unlock(&dmasound_core_mutex);
1342 return 0; 1343 return 0;
1343} 1344}
1344 1345
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index ca942f7cd231..7b5c77b32a90 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -39,7 +39,7 @@
39#include <linux/delay.h> 39#include <linux/delay.h>
40#include <linux/init.h> 40#include <linux/init.h>
41#include <linux/interrupt.h> 41#include <linux/interrupt.h>
42#include <linux/smp_lock.h> 42#include <linux/mutex.h>
43#include <linux/gfp.h> 43#include <linux/gfp.h>
44#include <asm/irq.h> 44#include <asm/irq.h>
45#include <asm/io.h> 45#include <asm/io.h>
@@ -79,6 +79,7 @@
79 dev.rec_sample_rate / \ 79 dev.rec_sample_rate / \
80 dev.rec_channels) 80 dev.rec_channels)
81 81
82static DEFINE_MUTEX(msnd_pinnacle_mutex);
82static multisound_dev_t dev; 83static multisound_dev_t dev;
83 84
84#ifndef HAVE_DSPCODEH 85#ifndef HAVE_DSPCODEH
@@ -651,12 +652,12 @@ static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
651 652
652 ret = -EINVAL; 653 ret = -EINVAL;
653 654
654 lock_kernel(); 655 mutex_lock(&msnd_pinnacle_mutex);
655 if (minor == dev.dsp_minor) 656 if (minor == dev.dsp_minor)
656 ret = dsp_ioctl(file, cmd, arg); 657 ret = dsp_ioctl(file, cmd, arg);
657 else if (minor == dev.mixer_minor) 658 else if (minor == dev.mixer_minor)
658 ret = mixer_ioctl(cmd, arg); 659 ret = mixer_ioctl(cmd, arg);
659 unlock_kernel(); 660 mutex_unlock(&msnd_pinnacle_mutex);
660 661
661 return ret; 662 return ret;
662} 663}
@@ -761,7 +762,7 @@ static int dev_open(struct inode *inode, struct file *file)
761 int minor = iminor(inode); 762 int minor = iminor(inode);
762 int err = 0; 763 int err = 0;
763 764
764 lock_kernel(); 765 mutex_lock(&msnd_pinnacle_mutex);
765 if (minor == dev.dsp_minor) { 766 if (minor == dev.dsp_minor) {
766 if ((file->f_mode & FMODE_WRITE && 767 if ((file->f_mode & FMODE_WRITE &&
767 test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) || 768 test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) ||
@@ -791,7 +792,7 @@ static int dev_open(struct inode *inode, struct file *file)
791 } else 792 } else
792 err = -EINVAL; 793 err = -EINVAL;
793out: 794out:
794 unlock_kernel(); 795 mutex_unlock(&msnd_pinnacle_mutex);
795 return err; 796 return err;
796} 797}
797 798
@@ -800,14 +801,14 @@ static int dev_release(struct inode *inode, struct file *file)
800 int minor = iminor(inode); 801 int minor = iminor(inode);
801 int err = 0; 802 int err = 0;
802 803
803 lock_kernel(); 804 mutex_lock(&msnd_pinnacle_mutex);
804 if (minor == dev.dsp_minor) 805 if (minor == dev.dsp_minor)
805 err = dsp_release(file); 806 err = dsp_release(file);
806 else if (minor == dev.mixer_minor) { 807 else if (minor == dev.mixer_minor) {
807 /* nothing */ 808 /* nothing */
808 } else 809 } else
809 err = -EINVAL; 810 err = -EINVAL;
810 unlock_kernel(); 811 mutex_unlock(&msnd_pinnacle_mutex);
811 return err; 812 return err;
812} 813}
813 814
diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c
deleted file mode 100644
index 479e3025a8a3..000000000000
--- a/sound/oss/sh_dac_audio.c
+++ /dev/null
@@ -1,325 +0,0 @@
1/*
2 * sound/oss/sh_dac_audio.c
3 *
4 * SH DAC based sound :(
5 *
6 * Copyright (C) 2004,2005 Andriy Skulysh
7 *
8 * This file is subject to the terms and conditions of the GNU General Public
9 * License. See the file "COPYING" in the main directory of this archive
10 * for more details.
11 */
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/sched.h>
15#include <linux/linkage.h>
16#include <linux/slab.h>
17#include <linux/fs.h>
18#include <linux/sound.h>
19#include <linux/smp_lock.h>
20#include <linux/soundcard.h>
21#include <linux/interrupt.h>
22#include <linux/hrtimer.h>
23#include <asm/io.h>
24#include <asm/uaccess.h>
25#include <asm/irq.h>
26#include <asm/delay.h>
27#include <asm/clock.h>
28#include <cpu/dac.h>
29#include <asm/machvec.h>
30#include <mach/hp6xx.h>
31#include <asm/hd64461.h>
32
33#define MODNAME "sh_dac_audio"
34
35#define BUFFER_SIZE 48000
36
37static int rate;
38static int empty;
39static char *data_buffer, *buffer_begin, *buffer_end;
40static int in_use, device_major;
41static struct hrtimer hrtimer;
42static ktime_t wakeups_per_second;
43
44static void dac_audio_start_timer(void)
45{
46 hrtimer_start(&hrtimer, wakeups_per_second, HRTIMER_MODE_REL);
47}
48
49static void dac_audio_stop_timer(void)
50{
51 hrtimer_cancel(&hrtimer);
52}
53
54static void dac_audio_reset(void)
55{
56 dac_audio_stop_timer();
57 buffer_begin = buffer_end = data_buffer;
58 empty = 1;
59}
60
61static void dac_audio_sync(void)
62{
63 while (!empty)
64 schedule();
65}
66
67static void dac_audio_start(void)
68{
69 if (mach_is_hp6xx()) {
70 u16 v = __raw_readw(HD64461_GPADR);
71 v &= ~HD64461_GPADR_SPEAKER;
72 __raw_writew(v, HD64461_GPADR);
73 }
74
75 sh_dac_enable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
76}
77static void dac_audio_stop(void)
78{
79 dac_audio_stop_timer();
80
81 if (mach_is_hp6xx()) {
82 u16 v = __raw_readw(HD64461_GPADR);
83 v |= HD64461_GPADR_SPEAKER;
84 __raw_writew(v, HD64461_GPADR);
85 }
86
87 sh_dac_output(0, CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
88 sh_dac_disable(CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
89}
90
91static void dac_audio_set_rate(void)
92{
93 wakeups_per_second = ktime_set(0, 1000000000 / rate);
94}
95
96static int dac_audio_ioctl(struct file *file,
97 unsigned int cmd, unsigned long arg)
98{
99 int val;
100
101 switch (cmd) {
102 case OSS_GETVERSION:
103 return put_user(SOUND_VERSION, (int *)arg);
104
105 case SNDCTL_DSP_SYNC:
106 dac_audio_sync();
107 return 0;
108
109 case SNDCTL_DSP_RESET:
110 dac_audio_reset();
111 return 0;
112
113 case SNDCTL_DSP_GETFMTS:
114 return put_user(AFMT_U8, (int *)arg);
115
116 case SNDCTL_DSP_SETFMT:
117 return put_user(AFMT_U8, (int *)arg);
118
119 case SNDCTL_DSP_NONBLOCK:
120 spin_lock(&file->f_lock);
121 file->f_flags |= O_NONBLOCK;
122 spin_unlock(&file->f_lock);
123 return 0;
124
125 case SNDCTL_DSP_GETCAPS:
126 return 0;
127
128 case SOUND_PCM_WRITE_RATE:
129 val = *(int *)arg;
130 if (val > 0) {
131 rate = val;
132 dac_audio_set_rate();
133 }
134 return put_user(rate, (int *)arg);
135
136 case SNDCTL_DSP_STEREO:
137 return put_user(0, (int *)arg);
138
139 case SOUND_PCM_WRITE_CHANNELS:
140 return put_user(1, (int *)arg);
141
142 case SNDCTL_DSP_SETDUPLEX:
143 return -EINVAL;
144
145 case SNDCTL_DSP_PROFILE:
146 return -EINVAL;
147
148 case SNDCTL_DSP_GETBLKSIZE:
149 return put_user(BUFFER_SIZE, (int *)arg);
150
151 case SNDCTL_DSP_SETFRAGMENT:
152 return 0;
153
154 default:
155 printk(KERN_ERR "sh_dac_audio: unimplemented ioctl=0x%x\n",
156 cmd);
157 return -EINVAL;
158 }
159 return -EINVAL;
160}
161
162static long dac_audio_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
163{
164 int ret;
165
166 lock_kernel();
167 ret = dac_audio_ioctl(file, cmd, arg);
168 unlock_kernel();
169
170 return ret;
171}
172
173static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
174 loff_t * ppos)
175{
176 int free;
177 int nbytes;
178
179 if (!count) {
180 dac_audio_sync();
181 return 0;
182 }
183
184 free = buffer_begin - buffer_end;
185
186 if (free < 0)
187 free += BUFFER_SIZE;
188 if ((free == 0) && (empty))
189 free = BUFFER_SIZE;
190 if (count > free)
191 count = free;
192 if (buffer_begin > buffer_end) {
193 if (copy_from_user((void *)buffer_end, buf, count))
194 return -EFAULT;
195
196 buffer_end += count;
197 } else {
198 nbytes = data_buffer + BUFFER_SIZE - buffer_end;
199 if (nbytes > count) {
200 if (copy_from_user((void *)buffer_end, buf, count))
201 return -EFAULT;
202 buffer_end += count;
203 } else {
204 if (copy_from_user((void *)buffer_end, buf, nbytes))
205 return -EFAULT;
206 if (copy_from_user
207 ((void *)data_buffer, buf + nbytes, count - nbytes))
208 return -EFAULT;
209 buffer_end = data_buffer + count - nbytes;
210 }
211 }
212
213 if (empty) {
214 empty = 0;
215 dac_audio_start_timer();
216 }
217
218 return count;
219}
220
221static ssize_t dac_audio_read(struct file *file, char *buf, size_t count,
222 loff_t * ppos)
223{
224 return -EINVAL;
225}
226
227static int dac_audio_open(struct inode *inode, struct file *file)
228{
229 if (file->f_mode & FMODE_READ)
230 return -ENODEV;
231
232 lock_kernel();
233 if (in_use) {
234 unlock_kernel();
235 return -EBUSY;
236 }
237
238 in_use = 1;
239
240 dac_audio_start();
241 unlock_kernel();
242 return 0;
243}
244
245static int dac_audio_release(struct inode *inode, struct file *file)
246{
247 dac_audio_sync();
248 dac_audio_stop();
249 in_use = 0;
250
251 return 0;
252}
253
254const struct file_operations dac_audio_fops = {
255 .read = dac_audio_read,
256 .write = dac_audio_write,
257 .unlocked_ioctl = dac_audio_unlocked_ioctl,
258 .open = dac_audio_open,
259 .release = dac_audio_release,
260};
261
262static enum hrtimer_restart sh_dac_audio_timer(struct hrtimer *handle)
263{
264 if (!empty) {
265 sh_dac_output(*buffer_begin, CONFIG_SOUND_SH_DAC_AUDIO_CHANNEL);
266 buffer_begin++;
267
268 if (buffer_begin == data_buffer + BUFFER_SIZE)
269 buffer_begin = data_buffer;
270 if (buffer_begin == buffer_end)
271 empty = 1;
272 }
273
274 if (!empty)
275 hrtimer_start(&hrtimer, wakeups_per_second, HRTIMER_MODE_REL);
276
277 return HRTIMER_NORESTART;
278}
279
280static int __init dac_audio_init(void)
281{
282 if ((device_major = register_sound_dsp(&dac_audio_fops, -1)) < 0) {
283 printk(KERN_ERR "Cannot register dsp device");
284 return device_major;
285 }
286
287 in_use = 0;
288
289 data_buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
290 if (data_buffer == NULL)
291 return -ENOMEM;
292
293 dac_audio_reset();
294 rate = 8000;
295 dac_audio_set_rate();
296
297 /* Today: High Resolution Timer driven DAC playback.
298 * The timer callback gets called once per sample. Ouch.
299 *
300 * Future: A much better approach would be to use the
301 * SH7720 CMT+DMAC+DAC hardware combination like this:
302 * - Program sample rate using CMT0 or CMT1
303 * - Program DMAC to use CMT for timing and output to DAC
304 * - Play sound using DMAC, let CPU sleep.
305 * - While at it, rewrite this driver to use ALSA.
306 */
307
308 hrtimer_init(&hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
309 hrtimer.function = sh_dac_audio_timer;
310
311 return 0;
312}
313
314static void __exit dac_audio_exit(void)
315{
316 unregister_sound_dsp(device_major);
317 kfree((void *)data_buffer);
318}
319
320module_init(dac_audio_init);
321module_exit(dac_audio_exit);
322
323MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
324MODULE_DESCRIPTION("SH DAC sound driver");
325MODULE_LICENSE("GPL");
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index 07f803e6d203..46c0d03dbecc 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -40,7 +40,7 @@
40#include <linux/major.h> 40#include <linux/major.h>
41#include <linux/delay.h> 41#include <linux/delay.h>
42#include <linux/proc_fs.h> 42#include <linux/proc_fs.h>
43#include <linux/smp_lock.h> 43#include <linux/mutex.h>
44#include <linux/module.h> 44#include <linux/module.h>
45#include <linux/mm.h> 45#include <linux/mm.h>
46#include <linux/device.h> 46#include <linux/device.h>
@@ -56,6 +56,7 @@
56 * Table for permanently allocated memory (used when unloading the module) 56 * Table for permanently allocated memory (used when unloading the module)
57 */ 57 */
58void * sound_mem_blocks[MAX_MEM_BLOCKS]; 58void * sound_mem_blocks[MAX_MEM_BLOCKS];
59static DEFINE_MUTEX(soundcard_mutex);
59int sound_nblocks = 0; 60int sound_nblocks = 0;
60 61
61/* Persistent DMA buffers */ 62/* Persistent DMA buffers */
@@ -151,7 +152,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
151 * big one anyway, we might as well bandage here.. 152 * big one anyway, we might as well bandage here..
152 */ 153 */
153 154
154 lock_kernel(); 155 mutex_lock(&soundcard_mutex);
155 156
156 DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count)); 157 DEB(printk("sound_read(dev=%d, count=%d)\n", dev, count));
157 switch (dev & 0x0f) { 158 switch (dev & 0x0f) {
@@ -169,7 +170,7 @@ static ssize_t sound_read(struct file *file, char __user *buf, size_t count, lof
169 case SND_DEV_MIDIN: 170 case SND_DEV_MIDIN:
170 ret = MIDIbuf_read(dev, file, buf, count); 171 ret = MIDIbuf_read(dev, file, buf, count);
171 } 172 }
172 unlock_kernel(); 173 mutex_unlock(&soundcard_mutex);
173 return ret; 174 return ret;
174} 175}
175 176
@@ -178,7 +179,7 @@ static ssize_t sound_write(struct file *file, const char __user *buf, size_t cou
178 int dev = iminor(file->f_path.dentry->d_inode); 179 int dev = iminor(file->f_path.dentry->d_inode);
179 int ret = -EINVAL; 180 int ret = -EINVAL;
180 181
181 lock_kernel(); 182 mutex_lock(&soundcard_mutex);
182 DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count)); 183 DEB(printk("sound_write(dev=%d, count=%d)\n", dev, count));
183 switch (dev & 0x0f) { 184 switch (dev & 0x0f) {
184 case SND_DEV_SEQ: 185 case SND_DEV_SEQ:
@@ -196,7 +197,7 @@ static ssize_t sound_write(struct file *file, const char __user *buf, size_t cou
196 ret = MIDIbuf_write(dev, file, buf, count); 197 ret = MIDIbuf_write(dev, file, buf, count);
197 break; 198 break;
198 } 199 }
199 unlock_kernel(); 200 mutex_unlock(&soundcard_mutex);
200 return ret; 201 return ret;
201} 202}
202 203
@@ -210,7 +211,7 @@ static int sound_open(struct inode *inode, struct file *file)
210 printk(KERN_ERR "Invalid minor device %d\n", dev); 211 printk(KERN_ERR "Invalid minor device %d\n", dev);
211 return -ENXIO; 212 return -ENXIO;
212 } 213 }
213 lock_kernel(); 214 mutex_lock(&soundcard_mutex);
214 switch (dev & 0x0f) { 215 switch (dev & 0x0f) {
215 case SND_DEV_CTL: 216 case SND_DEV_CTL:
216 dev >>= 4; 217 dev >>= 4;
@@ -247,15 +248,15 @@ static int sound_open(struct inode *inode, struct file *file)
247 retval = -ENXIO; 248 retval = -ENXIO;
248 } 249 }
249 250
250 unlock_kernel(); 251 mutex_unlock(&soundcard_mutex);
251 return 0; 252 return retval;
252} 253}
253 254
254static int sound_release(struct inode *inode, struct file *file) 255static int sound_release(struct inode *inode, struct file *file)
255{ 256{
256 int dev = iminor(inode); 257 int dev = iminor(inode);
257 258
258 lock_kernel(); 259 mutex_lock(&soundcard_mutex);
259 DEB(printk("sound_release(dev=%d)\n", dev)); 260 DEB(printk("sound_release(dev=%d)\n", dev));
260 switch (dev & 0x0f) { 261 switch (dev & 0x0f) {
261 case SND_DEV_CTL: 262 case SND_DEV_CTL:
@@ -280,7 +281,7 @@ static int sound_release(struct inode *inode, struct file *file)
280 default: 281 default:
281 printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev); 282 printk(KERN_ERR "Sound error: Releasing unknown device 0x%02x\n", dev);
282 } 283 }
283 unlock_kernel(); 284 mutex_unlock(&soundcard_mutex);
284 285
285 return 0; 286 return 0;
286} 287}
@@ -354,7 +355,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
354 if (cmd == OSS_GETVERSION) 355 if (cmd == OSS_GETVERSION)
355 return __put_user(SOUND_VERSION, (int __user *)p); 356 return __put_user(SOUND_VERSION, (int __user *)p);
356 357
357 lock_kernel(); 358 mutex_lock(&soundcard_mutex);
358 if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */ 359 if (_IOC_TYPE(cmd) == 'M' && num_mixers > 0 && /* Mixer ioctl */
359 (dev & 0x0f) != SND_DEV_CTL) { 360 (dev & 0x0f) != SND_DEV_CTL) {
360 dtype = dev & 0x0f; 361 dtype = dev & 0x0f;
@@ -369,7 +370,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
369 ret = sound_mixer_ioctl(dev >> 4, cmd, p); 370 ret = sound_mixer_ioctl(dev >> 4, cmd, p);
370 break; 371 break;
371 } 372 }
372 unlock_kernel(); 373 mutex_unlock(&soundcard_mutex);
373 return ret; 374 return ret;
374 } 375 }
375 376
@@ -399,7 +400,7 @@ static long sound_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
399 break; 400 break;
400 401
401 } 402 }
402 unlock_kernel(); 403 mutex_unlock(&soundcard_mutex);
403 return ret; 404 return ret;
404} 405}
405 406
@@ -439,35 +440,35 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
439 printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n"); 440 printk(KERN_ERR "Sound: mmap() not supported for other than audio devices\n");
440 return -EINVAL; 441 return -EINVAL;
441 } 442 }
442 lock_kernel(); 443 mutex_lock(&soundcard_mutex);
443 if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */ 444 if (vma->vm_flags & VM_WRITE) /* Map write and read/write to the output buf */
444 dmap = audio_devs[dev]->dmap_out; 445 dmap = audio_devs[dev]->dmap_out;
445 else if (vma->vm_flags & VM_READ) 446 else if (vma->vm_flags & VM_READ)
446 dmap = audio_devs[dev]->dmap_in; 447 dmap = audio_devs[dev]->dmap_in;
447 else { 448 else {
448 printk(KERN_ERR "Sound: Undefined mmap() access\n"); 449 printk(KERN_ERR "Sound: Undefined mmap() access\n");
449 unlock_kernel(); 450 mutex_unlock(&soundcard_mutex);
450 return -EINVAL; 451 return -EINVAL;
451 } 452 }
452 453
453 if (dmap == NULL) { 454 if (dmap == NULL) {
454 printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n"); 455 printk(KERN_ERR "Sound: mmap() error. dmap == NULL\n");
455 unlock_kernel(); 456 mutex_unlock(&soundcard_mutex);
456 return -EIO; 457 return -EIO;
457 } 458 }
458 if (dmap->raw_buf == NULL) { 459 if (dmap->raw_buf == NULL) {
459 printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n"); 460 printk(KERN_ERR "Sound: mmap() called when raw_buf == NULL\n");
460 unlock_kernel(); 461 mutex_unlock(&soundcard_mutex);
461 return -EIO; 462 return -EIO;
462 } 463 }
463 if (dmap->mapping_flags) { 464 if (dmap->mapping_flags) {
464 printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n"); 465 printk(KERN_ERR "Sound: mmap() called twice for the same DMA buffer\n");
465 unlock_kernel(); 466 mutex_unlock(&soundcard_mutex);
466 return -EIO; 467 return -EIO;
467 } 468 }
468 if (vma->vm_pgoff != 0) { 469 if (vma->vm_pgoff != 0) {
469 printk(KERN_ERR "Sound: mmap() offset must be 0.\n"); 470 printk(KERN_ERR "Sound: mmap() offset must be 0.\n");
470 unlock_kernel(); 471 mutex_unlock(&soundcard_mutex);
471 return -EINVAL; 472 return -EINVAL;
472 } 473 }
473 size = vma->vm_end - vma->vm_start; 474 size = vma->vm_end - vma->vm_start;
@@ -478,7 +479,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
478 if (remap_pfn_range(vma, vma->vm_start, 479 if (remap_pfn_range(vma, vma->vm_start,
479 virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT, 480 virt_to_phys(dmap->raw_buf) >> PAGE_SHIFT,
480 vma->vm_end - vma->vm_start, vma->vm_page_prot)) { 481 vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
481 unlock_kernel(); 482 mutex_unlock(&soundcard_mutex);
482 return -EAGAIN; 483 return -EAGAIN;
483 } 484 }
484 485
@@ -490,7 +491,7 @@ static int sound_mmap(struct file *file, struct vm_area_struct *vma)
490 memset(dmap->raw_buf, 491 memset(dmap->raw_buf,
491 dmap->neutral_byte, 492 dmap->neutral_byte,
492 dmap->bytes_in_use); 493 dmap->bytes_in_use);
493 unlock_kernel(); 494 mutex_unlock(&soundcard_mutex);
494 return 0; 495 return 0;
495} 496}
496 497
diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c
index b15840ad2527..44357d877a27 100644
--- a/sound/oss/swarm_cs4297a.c
+++ b/sound/oss/swarm_cs4297a.c
@@ -68,7 +68,6 @@
68#include <linux/delay.h> 68#include <linux/delay.h>
69#include <linux/sound.h> 69#include <linux/sound.h>
70#include <linux/slab.h> 70#include <linux/slab.h>
71#include <linux/smp_lock.h>
72#include <linux/soundcard.h> 71#include <linux/soundcard.h>
73#include <linux/ac97_codec.h> 72#include <linux/ac97_codec.h>
74#include <linux/pci.h> 73#include <linux/pci.h>
@@ -94,6 +93,7 @@
94 93
95struct cs4297a_state; 94struct cs4297a_state;
96 95
96static DEFINE_MUTEX(swarm_cs4297a_mutex);
97static void stop_dac(struct cs4297a_state *s); 97static void stop_dac(struct cs4297a_state *s);
98static void stop_adc(struct cs4297a_state *s); 98static void stop_adc(struct cs4297a_state *s);
99static void start_dac(struct cs4297a_state *s); 99static void start_dac(struct cs4297a_state *s);
@@ -1535,7 +1535,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
1535 CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, 1535 CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
1536 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n")); 1536 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n"));
1537 1537
1538 lock_kernel(); 1538 mutex_lock(&swarm_cs4297a_mutex);
1539 list_for_each(entry, &cs4297a_devs) 1539 list_for_each(entry, &cs4297a_devs)
1540 { 1540 {
1541 s = list_entry(entry, struct cs4297a_state, list); 1541 s = list_entry(entry, struct cs4297a_state, list);
@@ -1547,7 +1547,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
1547 CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, 1547 CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
1548 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n")); 1548 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n"));
1549 1549
1550 unlock_kernel(); 1550 mutex_unlock(&swarm_cs4297a_mutex);
1551 return -ENODEV; 1551 return -ENODEV;
1552 } 1552 }
1553 VALIDATE_STATE(s); 1553 VALIDATE_STATE(s);
@@ -1555,7 +1555,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
1555 1555
1556 CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4, 1556 CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
1557 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n")); 1557 printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n"));
1558 unlock_kernel(); 1558 mutex_unlock(&swarm_cs4297a_mutex);
1559 1559
1560 return nonseekable_open(inode, file); 1560 return nonseekable_open(inode, file);
1561} 1561}
@@ -1575,10 +1575,10 @@ static int cs4297a_ioctl_mixdev(struct file *file,
1575 unsigned int cmd, unsigned long arg) 1575 unsigned int cmd, unsigned long arg)
1576{ 1576{
1577 int ret; 1577 int ret;
1578 lock_kernel(); 1578 mutex_lock(&swarm_cs4297a_mutex);
1579 ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd, 1579 ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd,
1580 arg); 1580 arg);
1581 unlock_kernel(); 1581 mutex_unlock(&swarm_cs4297a_mutex);
1582 return ret; 1582 return ret;
1583} 1583}
1584 1584
@@ -2350,9 +2350,9 @@ static long cs4297a_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
2350{ 2350{
2351 int ret; 2351 int ret;
2352 2352
2353 lock_kernel(); 2353 mutex_lock(&swarm_cs4297a_mutex);
2354 ret = cs4297a_ioctl(file, cmd, arg); 2354 ret = cs4297a_ioctl(file, cmd, arg);
2355 unlock_kernel(); 2355 mutex_unlock(&swarm_cs4297a_mutex);
2356 2356
2357 return ret; 2357 return ret;
2358} 2358}
@@ -2509,9 +2509,9 @@ static int cs4297a_open(struct inode *inode, struct file *file)
2509{ 2509{
2510 int ret; 2510 int ret;
2511 2511
2512 lock_kernel(); 2512 mutex_lock(&swarm_cs4297a_mutex);
2513 ret = cs4297a_open(inode, file); 2513 ret = cs4297a_open(inode, file);
2514 unlock_kernel(); 2514 mutex_unlock(&swarm_cs4297a_mutex);
2515 2515
2516 return ret; 2516 return ret;
2517} 2517}
diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c
index 8cd73cdd88af..643f1113b1d8 100644
--- a/sound/oss/vwsnd.c
+++ b/sound/oss/vwsnd.c
@@ -145,7 +145,6 @@
145#include <linux/init.h> 145#include <linux/init.h>
146 146
147#include <linux/spinlock.h> 147#include <linux/spinlock.h>
148#include <linux/smp_lock.h>
149#include <linux/wait.h> 148#include <linux/wait.h>
150#include <linux/interrupt.h> 149#include <linux/interrupt.h>
151#include <linux/mutex.h> 150#include <linux/mutex.h>
@@ -160,6 +159,7 @@
160 159
161#ifdef VWSND_DEBUG 160#ifdef VWSND_DEBUG
162 161
162static DEFINE_MUTEX(vwsnd_mutex);
163static int shut_up = 1; 163static int shut_up = 1;
164 164
165/* 165/*
@@ -2891,11 +2891,11 @@ static long vwsnd_audio_ioctl(struct file *file,
2891 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data; 2891 vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
2892 int ret; 2892 int ret;
2893 2893
2894 lock_kernel(); 2894 mutex_lock(&vwsnd_mutex);
2895 mutex_lock(&devc->io_mutex); 2895 mutex_lock(&devc->io_mutex);
2896 ret = vwsnd_audio_do_ioctl(file, cmd, arg); 2896 ret = vwsnd_audio_do_ioctl(file, cmd, arg);
2897 mutex_unlock(&devc->io_mutex); 2897 mutex_unlock(&devc->io_mutex);
2898 unlock_kernel(); 2898 mutex_unlock(&vwsnd_mutex);
2899 2899
2900 return ret; 2900 return ret;
2901} 2901}
@@ -2922,7 +2922,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
2922 2922
2923 DBGE("(inode=0x%p, file=0x%p)\n", inode, file); 2923 DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
2924 2924
2925 lock_kernel(); 2925 mutex_lock(&vwsnd_mutex);
2926 INC_USE_COUNT; 2926 INC_USE_COUNT;
2927 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev) 2927 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
2928 if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F)) 2928 if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
@@ -2930,7 +2930,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
2930 2930
2931 if (devc == NULL) { 2931 if (devc == NULL) {
2932 DEC_USE_COUNT; 2932 DEC_USE_COUNT;
2933 unlock_kernel(); 2933 mutex_unlock(&vwsnd_mutex);
2934 return -ENODEV; 2934 return -ENODEV;
2935 } 2935 }
2936 2936
@@ -2939,13 +2939,13 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
2939 mutex_unlock(&devc->open_mutex); 2939 mutex_unlock(&devc->open_mutex);
2940 if (file->f_flags & O_NONBLOCK) { 2940 if (file->f_flags & O_NONBLOCK) {
2941 DEC_USE_COUNT; 2941 DEC_USE_COUNT;
2942 unlock_kernel(); 2942 mutex_unlock(&vwsnd_mutex);
2943 return -EBUSY; 2943 return -EBUSY;
2944 } 2944 }
2945 interruptible_sleep_on(&devc->open_wait); 2945 interruptible_sleep_on(&devc->open_wait);
2946 if (signal_pending(current)) { 2946 if (signal_pending(current)) {
2947 DEC_USE_COUNT; 2947 DEC_USE_COUNT;
2948 unlock_kernel(); 2948 mutex_unlock(&vwsnd_mutex);
2949 return -ERESTARTSYS; 2949 return -ERESTARTSYS;
2950 } 2950 }
2951 mutex_lock(&devc->open_mutex); 2951 mutex_lock(&devc->open_mutex);
@@ -2998,7 +2998,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
2998 2998
2999 file->private_data = devc; 2999 file->private_data = devc;
3000 DBGRV(); 3000 DBGRV();
3001 unlock_kernel(); 3001 mutex_unlock(&vwsnd_mutex);
3002 return 0; 3002 return 0;
3003} 3003}
3004 3004
@@ -3012,7 +3012,7 @@ static int vwsnd_audio_release(struct inode *inode, struct file *file)
3012 vwsnd_port_t *wport = NULL, *rport = NULL; 3012 vwsnd_port_t *wport = NULL, *rport = NULL;
3013 int err = 0; 3013 int err = 0;
3014 3014
3015 lock_kernel(); 3015 mutex_lock(&vwsnd_mutex);
3016 mutex_lock(&devc->io_mutex); 3016 mutex_lock(&devc->io_mutex);
3017 { 3017 {
3018 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file); 3018 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
@@ -3040,7 +3040,7 @@ static int vwsnd_audio_release(struct inode *inode, struct file *file)
3040 wake_up(&devc->open_wait); 3040 wake_up(&devc->open_wait);
3041 DEC_USE_COUNT; 3041 DEC_USE_COUNT;
3042 DBGR(); 3042 DBGR();
3043 unlock_kernel(); 3043 mutex_unlock(&vwsnd_mutex);
3044 return err; 3044 return err;
3045} 3045}
3046 3046
@@ -3068,18 +3068,18 @@ static int vwsnd_mixer_open(struct inode *inode, struct file *file)
3068 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file); 3068 DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
3069 3069
3070 INC_USE_COUNT; 3070 INC_USE_COUNT;
3071 lock_kernel(); 3071 mutex_lock(&vwsnd_mutex);
3072 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev) 3072 for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
3073 if (devc->mixer_minor == iminor(inode)) 3073 if (devc->mixer_minor == iminor(inode))
3074 break; 3074 break;
3075 3075
3076 if (devc == NULL) { 3076 if (devc == NULL) {
3077 DEC_USE_COUNT; 3077 DEC_USE_COUNT;
3078 unlock_kernel(); 3078 mutex_unlock(&vwsnd_mutex);
3079 return -ENODEV; 3079 return -ENODEV;
3080 } 3080 }
3081 file->private_data = devc; 3081 file->private_data = devc;
3082 unlock_kernel(); 3082 mutex_unlock(&vwsnd_mutex);
3083 return 0; 3083 return 0;
3084} 3084}
3085 3085
@@ -3223,7 +3223,7 @@ static long vwsnd_mixer_ioctl(struct file *file,
3223 3223
3224 DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg); 3224 DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
3225 3225
3226 lock_kernel(); 3226 mutex_lock(&vwsnd_mutex);
3227 mutex_lock(&devc->mix_mutex); 3227 mutex_lock(&devc->mix_mutex);
3228 { 3228 {
3229 if ((cmd & ~nrmask) == MIXER_READ(0)) 3229 if ((cmd & ~nrmask) == MIXER_READ(0))
@@ -3234,7 +3234,7 @@ static long vwsnd_mixer_ioctl(struct file *file,
3234 retval = -EINVAL; 3234 retval = -EINVAL;
3235 } 3235 }
3236 mutex_unlock(&devc->mix_mutex); 3236 mutex_unlock(&devc->mix_mutex);
3237 unlock_kernel(); 3237 mutex_unlock(&vwsnd_mutex);
3238 return retval; 3238 return retval;
3239} 3239}
3240 3240
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index e7a8cd058efb..12e34653b8a8 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -207,12 +207,12 @@ config SND_CMIPCI
207 207
208config SND_OXYGEN_LIB 208config SND_OXYGEN_LIB
209 tristate 209 tristate
210 select SND_PCM
211 select SND_MPU401_UART
212 210
213config SND_OXYGEN 211config SND_OXYGEN
214 tristate "C-Media 8788 (Oxygen)" 212 tristate "C-Media 8788 (Oxygen)"
215 select SND_OXYGEN_LIB 213 select SND_OXYGEN_LIB
214 select SND_PCM
215 select SND_MPU401_UART
216 help 216 help
217 Say Y here to include support for sound cards based on the 217 Say Y here to include support for sound cards based on the
218 C-Media CMI8788 (Oxygen HD Audio) chip: 218 C-Media CMI8788 (Oxygen HD Audio) chip:
@@ -581,6 +581,8 @@ config SND_HDSPM
581config SND_HIFIER 581config SND_HIFIER
582 tristate "TempoTec HiFier Fantasia" 582 tristate "TempoTec HiFier Fantasia"
583 select SND_OXYGEN_LIB 583 select SND_OXYGEN_LIB
584 select SND_PCM
585 select SND_MPU401_UART
584 help 586 help
585 Say Y here to include support for the MediaTek/TempoTec HiFier 587 Say Y here to include support for the MediaTek/TempoTec HiFier
586 Fantasia sound card. 588 Fantasia sound card.
@@ -815,14 +817,17 @@ config SND_VIA82XX_MODEM
815 will be called snd-via82xx-modem. 817 will be called snd-via82xx-modem.
816 818
817config SND_VIRTUOSO 819config SND_VIRTUOSO
818 tristate "Asus Virtuoso 100/200 (Xonar)" 820 tristate "Asus Virtuoso 66/100/200 (Xonar)"
819 select SND_OXYGEN_LIB 821 select SND_OXYGEN_LIB
822 select SND_PCM
823 select SND_MPU401_UART
824 select SND_JACK if INPUT=y || INPUT=SND
820 help 825 help
821 Say Y here to include support for sound cards based on the 826 Say Y here to include support for sound cards based on the
822 Asus AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, 827 Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS,
823 Essence ST (Deluxe), and Essence STX. 828 Essence ST (Deluxe), and Essence STX.
824 Support for the DS is experimental. 829 Support for the HDAV1.3 (Deluxe) is incomplete; for the
825 Support for the HDAV1.3 (Deluxe) is very experimental. 830 HDAV1.3 Slim and Xense, missing.
826 831
827 To compile this driver as a module, choose M here: the module 832 To compile this driver as a module, choose M here: the module
828 will be called snd-virtuoso. 833 will be called snd-virtuoso.
diff --git a/sound/pci/au88x0/au88x0_mixer.c b/sound/pci/au88x0/au88x0_mixer.c
index c92f493d341e..557c782ae4fc 100644
--- a/sound/pci/au88x0/au88x0_mixer.c
+++ b/sound/pci/au88x0/au88x0_mixer.c
@@ -23,7 +23,7 @@ static int __devinit snd_vortex_mixer(vortex_t * vortex)
23 if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0) 23 if ((err = snd_ac97_bus(vortex->card, 0, &ops, NULL, &pbus)) < 0)
24 return err; 24 return err;
25 memset(&ac97, 0, sizeof(ac97)); 25 memset(&ac97, 0, sizeof(ac97));
26 // Intialize AC97 codec stuff. 26 // Initialize AC97 codec stuff.
27 ac97.private_data = vortex; 27 ac97.private_data = vortex;
28 ac97.scaps = AC97_SCAP_NO_SPDIF; 28 ac97.scaps = AC97_SCAP_NO_SPDIF;
29 err = snd_ac97_mixer(pbus, &ac97, &vortex->codec); 29 err = snd_ac97_mixer(pbus, &ac97, &vortex->codec);
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index 14b8d9a91aae..f19c11077255 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -670,8 +670,9 @@ struct snd_ca0106_details {
670 gpio_type = 2 -> shared side-out/line-in. */ 670 gpio_type = 2 -> shared side-out/line-in. */
671 int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume 671 int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume
672 controls, phone, mic, line-in and aux. */ 672 controls, phone, mic, line-in and aux. */
673 int spi_dac; /* spi_dac=1 adds the mute switch for each analog 673 u16 spi_dac; /* spi_dac = 0 -> no spi interface for DACs
674 output, front, rear, etc. */ 674 spi_dac = 0x<front><rear><center-lfe><side>
675 -> specifies DAC id for each channel pair. */
675}; 676};
676 677
677// definition of the chip-specific record 678// definition of the chip-specific record
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 0a3d3d6e77b4..d2d12c08f937 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -227,7 +227,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
227 .name = "Audigy SE [SB0570]", 227 .name = "Audigy SE [SB0570]",
228 .gpio_type = 1, 228 .gpio_type = 1,
229 .i2c_adc = 1, 229 .i2c_adc = 1,
230 .spi_dac = 1 } , 230 .spi_dac = 0x4021 } ,
231 /* New Audigy LS. Has a different DAC. */ 231 /* New Audigy LS. Has a different DAC. */
232 /* SB0570: 232 /* SB0570:
233 * CTRL:CA0106-DAT 233 * CTRL:CA0106-DAT
@@ -238,7 +238,17 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
238 .name = "Audigy SE OEM [SB0570a]", 238 .name = "Audigy SE OEM [SB0570a]",
239 .gpio_type = 1, 239 .gpio_type = 1,
240 .i2c_adc = 1, 240 .i2c_adc = 1,
241 .spi_dac = 1 } , 241 .spi_dac = 0x4021 } ,
242 /* Sound Blaster 5.1vx
243 * Tested: Playback on front, rear, center/lfe speakers
244 * Not-Tested: Capture
245 */
246 { .serial = 0x10041102,
247 .name = "Sound Blaster 5.1vx [SB1070]",
248 .gpio_type = 1,
249 .i2c_adc = 0,
250 .spi_dac = 0x0124
251 } ,
242 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ 252 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
243 /* SB0438 253 /* SB0438
244 * CTRL:CA0106-DAT 254 * CTRL:CA0106-DAT
@@ -254,7 +264,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = {
254 .name = "MSI K8N Diamond MB", 264 .name = "MSI K8N Diamond MB",
255 .gpio_type = 2, 265 .gpio_type = 2,
256 .i2c_adc = 1, 266 .i2c_adc = 1,
257 .spi_dac = 1 } , 267 .spi_dac = 0x4021 } ,
258 /* Giga-byte GA-G1975X mobo 268 /* Giga-byte GA-G1975X mobo
259 * Novell bnc#395807 269 * Novell bnc#395807
260 */ 270 */
@@ -483,16 +493,18 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime)
483} 493}
484 494
485static const int spi_dacd_reg[] = { 495static const int spi_dacd_reg[] = {
486 [PCM_FRONT_CHANNEL] = SPI_DACD4_REG, 496 SPI_DACD0_REG,
487 [PCM_REAR_CHANNEL] = SPI_DACD0_REG, 497 SPI_DACD1_REG,
488 [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG, 498 SPI_DACD2_REG,
489 [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_REG, 499 0,
500 SPI_DACD4_REG,
490}; 501};
491static const int spi_dacd_bit[] = { 502static const int spi_dacd_bit[] = {
492 [PCM_FRONT_CHANNEL] = SPI_DACD4_BIT, 503 SPI_DACD0_BIT,
493 [PCM_REAR_CHANNEL] = SPI_DACD0_BIT, 504 SPI_DACD1_BIT,
494 [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_BIT, 505 SPI_DACD2_BIT,
495 [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, 506 0,
507 SPI_DACD4_BIT,
496}; 508};
497 509
498static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) 510static void restore_spdif_bits(struct snd_ca0106 *chip, int idx)
@@ -504,6 +516,45 @@ static void restore_spdif_bits(struct snd_ca0106 *chip, int idx)
504 } 516 }
505} 517}
506 518
519static int snd_ca0106_channel_dac(struct snd_ca0106_details *details,
520 int channel_id)
521{
522 switch (channel_id) {
523 case PCM_FRONT_CHANNEL:
524 return (details->spi_dac & 0xf000) >> (4 * 3);
525 case PCM_REAR_CHANNEL:
526 return (details->spi_dac & 0x0f00) >> (4 * 2);
527 case PCM_CENTER_LFE_CHANNEL:
528 return (details->spi_dac & 0x00f0) >> (4 * 1);
529 case PCM_UNKNOWN_CHANNEL:
530 return (details->spi_dac & 0x000f) >> (4 * 0);
531 default:
532 snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n",
533 channel_id);
534 }
535 return 0;
536}
537
538static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id,
539 int power)
540{
541 if (chip->details->spi_dac) {
542 const int dac = snd_ca0106_channel_dac(chip->details,
543 channel_id);
544 const int reg = spi_dacd_reg[dac];
545 const int bit = spi_dacd_bit[dac];
546
547 if (power)
548 /* Power up */
549 chip->spi_dac_reg[reg] &= ~bit;
550 else
551 /* Power down */
552 chip->spi_dac_reg[reg] |= bit;
553 return snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
554 }
555 return 0;
556}
557
507/* open_playback callback */ 558/* open_playback callback */
508static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, 559static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream,
509 int channel_id) 560 int channel_id)
@@ -543,12 +594,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr
543 return err; 594 return err;
544 snd_pcm_set_sync(substream); 595 snd_pcm_set_sync(substream);
545 596
546 if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) { 597 /* Front channel dac should already be on */
547 const int reg = spi_dacd_reg[channel_id]; 598 if (channel_id != PCM_FRONT_CHANNEL) {
548 599 err = snd_ca0106_pcm_power_dac(chip, channel_id, 1);
549 /* Power up dac */
550 chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id];
551 err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]);
552 if (err < 0) 600 if (err < 0)
553 return err; 601 return err;
554 } 602 }
@@ -568,13 +616,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
568 616
569 restore_spdif_bits(chip, epcm->channel_id); 617 restore_spdif_bits(chip, epcm->channel_id);
570 618
571 if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { 619 /* Front channel dac should stay on */
572 const int reg = spi_dacd_reg[epcm->channel_id]; 620 if (epcm->channel_id != PCM_FRONT_CHANNEL) {
573 621 int err;
574 /* Power down DAC */ 622 err = snd_ca0106_pcm_power_dac(chip, epcm->channel_id, 0);
575 chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id]; 623 if (err < 0)
576 snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); 624 return err;
577 } 625 }
626
578 /* FIXME: maybe zero others */ 627 /* FIXME: maybe zero others */
579 return 0; 628 return 0;
580} 629}
@@ -1002,29 +1051,27 @@ snd_ca0106_pcm_pointer_playback(struct snd_pcm_substream *substream)
1002 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream); 1051 struct snd_ca0106 *emu = snd_pcm_substream_chip(substream);
1003 struct snd_pcm_runtime *runtime = substream->runtime; 1052 struct snd_pcm_runtime *runtime = substream->runtime;
1004 struct snd_ca0106_pcm *epcm = runtime->private_data; 1053 struct snd_ca0106_pcm *epcm = runtime->private_data;
1005 snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0; 1054 unsigned int ptr, prev_ptr;
1006 int channel = epcm->channel_id; 1055 int channel = epcm->channel_id;
1056 int timeout = 10;
1007 1057
1008 if (!epcm->running) 1058 if (!epcm->running)
1009 return 0; 1059 return 0;
1010 1060
1011 ptr3 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel); 1061 prev_ptr = -1;
1012 ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel); 1062 do {
1013 ptr4 = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel); 1063 ptr = snd_ca0106_ptr_read(emu, PLAYBACK_LIST_PTR, channel);
1014 if (ptr3 != ptr4) ptr1 = snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel); 1064 ptr = (ptr >> 3) * runtime->period_size;
1015 ptr2 = bytes_to_frames(runtime, ptr1); 1065 ptr += bytes_to_frames(runtime,
1016 ptr2+= (ptr4 >> 3) * runtime->period_size; 1066 snd_ca0106_ptr_read(emu, PLAYBACK_POINTER, channel));
1017 ptr=ptr2; 1067 if (ptr >= runtime->buffer_size)
1018 if (ptr >= runtime->buffer_size) 1068 ptr -= runtime->buffer_size;
1019 ptr -= runtime->buffer_size; 1069 if (prev_ptr == ptr)
1020 /* 1070 return ptr;
1021 printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, " 1071 prev_ptr = ptr;
1022 "buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", 1072 } while (--timeout);
1023 ptr1, ptr2, ptr, (int)runtime->buffer_size, 1073 snd_printk(KERN_WARNING "ca0106: unstable DMA pointer!\n");
1024 (int)runtime->period_size, (int)runtime->frame_bits, 1074 return 0;
1025 (int)runtime->rate);
1026 */
1027 return ptr;
1028} 1075}
1029 1076
1030/* pointer_capture callback */ 1077/* pointer_capture callback */
@@ -1362,7 +1409,7 @@ static unsigned int spi_dac_init[] = {
1362 SPI_REG(12, 0x00), 1409 SPI_REG(12, 0x00),
1363 SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB), 1410 SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB),
1364 SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE), 1411 SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE),
1365 SPI_REG(SPI_DACD4_REG, 0x00), 1412 SPI_REG(SPI_DACD4_REG, SPI_DACD4_BIT),
1366}; 1413};
1367 1414
1368static unsigned int i2c_adc_init[][2] = { 1415static unsigned int i2c_adc_init[][2] = {
@@ -1541,7 +1588,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
1541 /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */ 1588 /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */
1542 } 1589 }
1543 1590
1544 if (chip->details->spi_dac == 1) { 1591 if (chip->details->spi_dac) {
1545 /* The SB0570 use SPI to control DAC. */ 1592 /* The SB0570 use SPI to control DAC. */
1546 int size, n; 1593 int size, n;
1547 1594
@@ -1553,6 +1600,9 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume)
1553 if (reg < ARRAY_SIZE(chip->spi_dac_reg)) 1600 if (reg < ARRAY_SIZE(chip->spi_dac_reg))
1554 chip->spi_dac_reg[reg] = spi_dac_init[n]; 1601 chip->spi_dac_reg[reg] = spi_dac_init[n];
1555 } 1602 }
1603
1604 /* Enable front dac only */
1605 snd_ca0106_pcm_power_dac(chip, PCM_FRONT_CHANNEL, 1);
1556 } 1606 }
1557} 1607}
1558 1608
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 85fd315d9999..630aa4998189 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -676,28 +676,65 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata =
676 I2C_VOLUME("Aux Capture Volume", 3), 676 I2C_VOLUME("Aux Capture Volume", 3),
677}; 677};
678 678
679#define SPI_SWITCH(xname,reg,bit) \ 679static const int spi_dmute_reg[] = {
680{ \ 680 SPI_DMUTE0_REG,
681 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 681 SPI_DMUTE1_REG,
682 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 682 SPI_DMUTE2_REG,
683 .info = spi_mute_info, \ 683 0,
684 .get = spi_mute_get, \ 684 SPI_DMUTE4_REG,
685 .put = spi_mute_put, \ 685};
686 .private_value = (reg<<SPI_REG_SHIFT) | (bit) \ 686static const int spi_dmute_bit[] = {
687} 687 SPI_DMUTE0_BIT,
688 688 SPI_DMUTE1_BIT,
689static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[] 689 SPI_DMUTE2_BIT,
690__devinitdata = { 690 0,
691 SPI_SWITCH("Analog Front Playback Switch", 691 SPI_DMUTE4_BIT,
692 SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
693 SPI_SWITCH("Analog Rear Playback Switch",
694 SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
695 SPI_SWITCH("Analog Center/LFE Playback Switch",
696 SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
697 SPI_SWITCH("Analog Side Playback Switch",
698 SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
699}; 692};
700 693
694static struct snd_kcontrol_new __devinit
695snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
696 int channel_id)
697{
698 struct snd_kcontrol_new spi_switch = {0};
699 int reg, bit;
700 int dac_id;
701
702 spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
703 spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
704 spi_switch.info = spi_mute_info;
705 spi_switch.get = spi_mute_get;
706 spi_switch.put = spi_mute_put;
707
708 switch (channel_id) {
709 case PCM_FRONT_CHANNEL:
710 spi_switch.name = "Analog Front Playback Switch";
711 dac_id = (details->spi_dac & 0xf000) >> (4 * 3);
712 break;
713 case PCM_REAR_CHANNEL:
714 spi_switch.name = "Analog Rear Playback Switch";
715 dac_id = (details->spi_dac & 0x0f00) >> (4 * 2);
716 break;
717 case PCM_CENTER_LFE_CHANNEL:
718 spi_switch.name = "Analog Center/LFE Playback Switch";
719 dac_id = (details->spi_dac & 0x00f0) >> (4 * 1);
720 break;
721 case PCM_UNKNOWN_CHANNEL:
722 spi_switch.name = "Analog Side Playback Switch";
723 dac_id = (details->spi_dac & 0x000f) >> (4 * 0);
724 break;
725 default:
726 /* Unused channel */
727 spi_switch.name = NULL;
728 dac_id = 0;
729 }
730 reg = spi_dmute_reg[dac_id];
731 bit = spi_dmute_bit[dac_id];
732
733 spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit;
734
735 return spi_switch;
736}
737
701static int __devinit remove_ctl(struct snd_card *card, const char *name) 738static int __devinit remove_ctl(struct snd_card *card, const char *name)
702{ 739{
703 struct snd_ctl_elem_id id; 740 struct snd_ctl_elem_id id;
@@ -832,8 +869,18 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
832 if (err < 0) 869 if (err < 0)
833 return err; 870 return err;
834 } 871 }
835 if (emu->details->spi_dac == 1) 872 if (emu->details->spi_dac) {
836 ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls); 873 int i;
874 for (i = 0;; i++) {
875 struct snd_kcontrol_new ctl;
876 ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i);
877 if (!ctl.name)
878 break;
879 err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu));
880 if (err < 0)
881 return err;
882 }
883 }
837 884
838 /* Create virtual master controls */ 885 /* Create virtual master controls */
839 vmaster = snd_ctl_make_virtual_master("Master Playback Volume", 886 vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
@@ -845,7 +892,7 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
845 return err; 892 return err;
846 add_slaves(card, vmaster, slave_vols); 893 add_slaves(card, vmaster, slave_vols);
847 894
848 if (emu->details->spi_dac == 1) { 895 if (emu->details->spi_dac) {
849 vmaster = snd_ctl_make_virtual_master("Master Playback Switch", 896 vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
850 NULL); 897 NULL);
851 if (!vmaster) 898 if (!vmaster)
diff --git a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
index 8578c70c61f2..bab564824efe 100644
--- a/sound/pci/emu10k1/emumpu401.c
+++ b/sound/pci/emu10k1/emumpu401.c
@@ -321,7 +321,7 @@ static struct snd_rawmidi_ops snd_emu10k1_midi_input =
321 321
322static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi) 322static void snd_emu10k1_midi_free(struct snd_rawmidi *rmidi)
323{ 323{
324 struct snd_emu10k1_midi *midi = (struct snd_emu10k1_midi *)rmidi->private_data; 324 struct snd_emu10k1_midi *midi = rmidi->private_data;
325 midi->interrupt = NULL; 325 midi->interrupt = NULL;
326 midi->rmidi = NULL; 326 midi->rmidi = NULL;
327} 327}
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 9194c3c1d04a..0ea5cc60ac78 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -119,47 +119,20 @@ config SND_HDA_CODEC_VIA
119 snd-hda-codec-via. 119 snd-hda-codec-via.
120 This module is automatically loaded at probing. 120 This module is automatically loaded at probing.
121 121
122config SND_HDA_CODEC_ATIHDMI 122config SND_HDA_CODEC_HDMI
123 bool "Build ATI HDMI HD-audio codec support" 123 bool "Build HDMI/DisplayPort HD-audio codec support"
124 default y
125 help
126 Say Y here to include ATI HDMI HD-audio codec support in
127 snd-hda-intel driver, such as ATI RS600 HDMI.
128
129 When the HD-audio driver is built as a module, the codec
130 support code is also built as another module,
131 snd-hda-codec-atihdmi.
132 This module is automatically loaded at probing.
133
134config SND_HDA_CODEC_NVHDMI
135 bool "Build NVIDIA HDMI HD-audio codec support"
136 default y
137 help
138 Say Y here to include NVIDIA HDMI HD-audio codec support in
139 snd-hda-intel driver, such as NVIDIA MCP78 HDMI.
140
141 When the HD-audio driver is built as a module, the codec
142 support code is also built as another module,
143 snd-hda-codec-nvhdmi.
144 This module is automatically loaded at probing.
145
146config SND_HDA_CODEC_INTELHDMI
147 bool "Build INTEL HDMI HD-audio codec support"
148 select SND_DYNAMIC_MINORS 124 select SND_DYNAMIC_MINORS
149 default y 125 default y
150 help 126 help
151 Say Y here to include INTEL HDMI HD-audio codec support in 127 Say Y here to include HDMI and DisplayPort HD-audio codec
152 snd-hda-intel driver, such as Eaglelake integrated HDMI. 128 support in snd-hda-intel driver. This includes all AMD/ATI,
129 Intel and Nvidia HDMI/DisplayPort codecs.
153 130
154 When the HD-audio driver is built as a module, the codec 131 When the HD-audio driver is built as a module, the codec
155 support code is also built as another module, 132 support code is also built as another module,
156 snd-hda-codec-intelhdmi. 133 snd-hda-codec-hdmi.
157 This module is automatically loaded at probing. 134 This module is automatically loaded at probing.
158 135
159config SND_HDA_ELD
160 def_bool y
161 depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
162
163config SND_HDA_CODEC_CIRRUS 136config SND_HDA_CODEC_CIRRUS
164 bool "Build Cirrus Logic codec support" 137 bool "Build Cirrus Logic codec support"
165 depends on SND_HDA_INTEL 138 depends on SND_HDA_INTEL
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 24bc195b02da..17ef3658f34b 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o
3snd-hda-codec-y := hda_codec.o 3snd-hda-codec-y := hda_codec.o
4snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o 4snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
5snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o 5snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
6snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
7snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o 6snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
8snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o 7snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
9 8
@@ -12,13 +11,11 @@ snd-hda-codec-cmedia-objs := patch_cmedia.o
12snd-hda-codec-analog-objs := patch_analog.o 11snd-hda-codec-analog-objs := patch_analog.o
13snd-hda-codec-idt-objs := patch_sigmatel.o 12snd-hda-codec-idt-objs := patch_sigmatel.o
14snd-hda-codec-si3054-objs := patch_si3054.o 13snd-hda-codec-si3054-objs := patch_si3054.o
15snd-hda-codec-atihdmi-objs := patch_atihdmi.o
16snd-hda-codec-cirrus-objs := patch_cirrus.o 14snd-hda-codec-cirrus-objs := patch_cirrus.o
17snd-hda-codec-ca0110-objs := patch_ca0110.o 15snd-hda-codec-ca0110-objs := patch_ca0110.o
18snd-hda-codec-conexant-objs := patch_conexant.o 16snd-hda-codec-conexant-objs := patch_conexant.o
19snd-hda-codec-via-objs := patch_via.o 17snd-hda-codec-via-objs := patch_via.o
20snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o 18snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o
21snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o
22 19
23# common driver 20# common driver
24obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o 21obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
@@ -39,9 +36,6 @@ endif
39ifdef CONFIG_SND_HDA_CODEC_SI3054 36ifdef CONFIG_SND_HDA_CODEC_SI3054
40obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o 37obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o
41endif 38endif
42ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
43obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o
44endif
45ifdef CONFIG_SND_HDA_CODEC_CIRRUS 39ifdef CONFIG_SND_HDA_CODEC_CIRRUS
46obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o 40obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o
47endif 41endif
@@ -54,11 +48,8 @@ endif
54ifdef CONFIG_SND_HDA_CODEC_VIA 48ifdef CONFIG_SND_HDA_CODEC_VIA
55obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o 49obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o
56endif 50endif
57ifdef CONFIG_SND_HDA_CODEC_NVHDMI 51ifdef CONFIG_SND_HDA_CODEC_HDMI
58obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-nvhdmi.o 52obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o
59endif
60ifdef CONFIG_SND_HDA_CODEC_INTELHDMI
61obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-intelhdmi.o
62endif 53endif
63 54
64# this must be the last entry after codec drivers; 55# this must be the last entry after codec drivers;
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 14829210ef0b..644e3f14f8ca 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1216,6 +1216,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1216 struct hda_codec *c; 1216 struct hda_codec *c;
1217 struct hda_cvt_setup *p; 1217 struct hda_cvt_setup *p;
1218 unsigned int oldval, newval; 1218 unsigned int oldval, newval;
1219 int type;
1219 int i; 1220 int i;
1220 1221
1221 if (!nid) 1222 if (!nid)
@@ -1254,10 +1255,12 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
1254 p->dirty = 0; 1255 p->dirty = 0;
1255 1256
1256 /* make other inactive cvts with the same stream-tag dirty */ 1257 /* make other inactive cvts with the same stream-tag dirty */
1258 type = get_wcaps_type(get_wcaps(codec, nid));
1257 list_for_each_entry(c, &codec->bus->codec_list, list) { 1259 list_for_each_entry(c, &codec->bus->codec_list, list) {
1258 for (i = 0; i < c->cvt_setups.used; i++) { 1260 for (i = 0; i < c->cvt_setups.used; i++) {
1259 p = snd_array_elem(&c->cvt_setups, i); 1261 p = snd_array_elem(&c->cvt_setups, i);
1260 if (!p->active && p->stream_tag == stream_tag) 1262 if (!p->active && p->stream_tag == stream_tag &&
1263 get_wcaps_type(get_wcaps(codec, p->nid)) == type)
1261 p->dirty = 1; 1264 p->dirty = 1;
1262 } 1265 }
1263 } 1266 }
@@ -1281,6 +1284,9 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
1281 if (!nid) 1284 if (!nid)
1282 return; 1285 return;
1283 1286
1287 if (codec->no_sticky_stream)
1288 do_now = 1;
1289
1284 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); 1290 snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid);
1285 p = get_hda_cvt_setup(codec, nid); 1291 p = get_hda_cvt_setup(codec, nid);
1286 if (p) { 1292 if (p) {
@@ -1831,6 +1837,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1831 hda_nid_t nid = get_amp_nid(kcontrol); 1837 hda_nid_t nid = get_amp_nid(kcontrol);
1832 int dir = get_amp_direction(kcontrol); 1838 int dir = get_amp_direction(kcontrol);
1833 unsigned int ofs = get_amp_offset(kcontrol); 1839 unsigned int ofs = get_amp_offset(kcontrol);
1840 bool min_mute = get_amp_min_mute(kcontrol);
1834 u32 caps, val1, val2; 1841 u32 caps, val1, val2;
1835 1842
1836 if (size < 4 * sizeof(unsigned int)) 1843 if (size < 4 * sizeof(unsigned int))
@@ -1841,6 +1848,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
1841 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); 1848 val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
1842 val1 += ofs; 1849 val1 += ofs;
1843 val1 = ((int)val1) * ((int)val2); 1850 val1 = ((int)val1) * ((int)val2);
1851 if (min_mute)
1852 val2 |= TLV_DB_SCALE_MUTE;
1844 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) 1853 if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
1845 return -EFAULT; 1854 return -EFAULT;
1846 if (put_user(2 * sizeof(unsigned int), _tlv + 1)) 1855 if (put_user(2 * sizeof(unsigned int), _tlv + 1))
@@ -2228,10 +2237,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
2228 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, 2237 change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
2229 HDA_AMP_MUTE, 2238 HDA_AMP_MUTE,
2230 *valp ? 0 : HDA_AMP_MUTE); 2239 *valp ? 0 : HDA_AMP_MUTE);
2231#ifdef CONFIG_SND_HDA_POWER_SAVE 2240 hda_call_check_power_status(codec, nid);
2232 if (codec->patch_ops.check_power_status)
2233 codec->patch_ops.check_power_status(codec, nid);
2234#endif
2235 snd_hda_power_down(codec); 2241 snd_hda_power_down(codec);
2236 return change; 2242 return change;
2237} 2243}
@@ -4372,6 +4378,34 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
4372} 4378}
4373 4379
4374 4380
4381/* add the found input-pin to the cfg->inputs[] table */
4382static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid,
4383 int type)
4384{
4385 if (cfg->num_inputs < AUTO_CFG_MAX_INS) {
4386 cfg->inputs[cfg->num_inputs].pin = nid;
4387 cfg->inputs[cfg->num_inputs].type = type;
4388 cfg->num_inputs++;
4389 }
4390}
4391
4392/* sort inputs in the order of AUTO_PIN_* type */
4393static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
4394{
4395 int i, j;
4396
4397 for (i = 0; i < cfg->num_inputs; i++) {
4398 for (j = i + 1; j < cfg->num_inputs; j++) {
4399 if (cfg->inputs[i].type > cfg->inputs[j].type) {
4400 struct auto_pin_cfg_item tmp;
4401 tmp = cfg->inputs[i];
4402 cfg->inputs[i] = cfg->inputs[j];
4403 cfg->inputs[j] = tmp;
4404 }
4405 }
4406 }
4407}
4408
4375/* 4409/*
4376 * Parse all pin widgets and store the useful pin nids to cfg 4410 * Parse all pin widgets and store the useful pin nids to cfg
4377 * 4411 *
@@ -4385,7 +4419,7 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
4385 * output, i.e. to line_out_pins[0]. So, line_outs is always positive 4419 * output, i.e. to line_out_pins[0]. So, line_outs is always positive
4386 * if any analog output exists. 4420 * if any analog output exists.
4387 * 4421 *
4388 * The analog input pins are assigned to input_pins array. 4422 * The analog input pins are assigned to inputs array.
4389 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, 4423 * The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
4390 * respectively. 4424 * respectively.
4391 */ 4425 */
@@ -4398,6 +4432,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4398 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; 4432 short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
4399 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; 4433 short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
4400 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; 4434 short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
4435 int i;
4401 4436
4402 memset(cfg, 0, sizeof(*cfg)); 4437 memset(cfg, 0, sizeof(*cfg));
4403 4438
@@ -4468,33 +4503,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4468 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; 4503 sequences_hp[cfg->hp_outs] = (assoc << 4) | seq;
4469 cfg->hp_outs++; 4504 cfg->hp_outs++;
4470 break; 4505 break;
4471 case AC_JACK_MIC_IN: { 4506 case AC_JACK_MIC_IN:
4472 int preferred, alt; 4507 add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC);
4473 if (loc == AC_JACK_LOC_FRONT ||
4474 (loc & 0x30) == AC_JACK_LOC_INTERNAL) {
4475 preferred = AUTO_PIN_FRONT_MIC;
4476 alt = AUTO_PIN_MIC;
4477 } else {
4478 preferred = AUTO_PIN_MIC;
4479 alt = AUTO_PIN_FRONT_MIC;
4480 }
4481 if (!cfg->input_pins[preferred])
4482 cfg->input_pins[preferred] = nid;
4483 else if (!cfg->input_pins[alt])
4484 cfg->input_pins[alt] = nid;
4485 break; 4508 break;
4486 }
4487 case AC_JACK_LINE_IN: 4509 case AC_JACK_LINE_IN:
4488 if (loc == AC_JACK_LOC_FRONT) 4510 add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN);
4489 cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
4490 else
4491 cfg->input_pins[AUTO_PIN_LINE] = nid;
4492 break; 4511 break;
4493 case AC_JACK_CD: 4512 case AC_JACK_CD:
4494 cfg->input_pins[AUTO_PIN_CD] = nid; 4513 add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD);
4495 break; 4514 break;
4496 case AC_JACK_AUX: 4515 case AC_JACK_AUX:
4497 cfg->input_pins[AUTO_PIN_AUX] = nid; 4516 add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX);
4498 break; 4517 break;
4499 case AC_JACK_SPDIF_OUT: 4518 case AC_JACK_SPDIF_OUT:
4500 case AC_JACK_DIG_OTHER_OUT: 4519 case AC_JACK_DIG_OTHER_OUT:
@@ -4539,6 +4558,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4539 memmove(sequences_hp + i, sequences_hp + i + 1, 4558 memmove(sequences_hp + i, sequences_hp + i + 1,
4540 sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); 4559 sizeof(sequences_hp[0]) * (cfg->hp_outs - i));
4541 } 4560 }
4561 memset(cfg->hp_pins + cfg->hp_outs, 0,
4562 sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs));
4542 } 4563 }
4543 4564
4544 /* sort by sequence */ 4565 /* sort by sequence */
@@ -4549,21 +4570,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4549 sort_pins_by_sequence(cfg->hp_pins, sequences_hp, 4570 sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
4550 cfg->hp_outs); 4571 cfg->hp_outs);
4551 4572
4552 /* if we have only one mic, make it AUTO_PIN_MIC */
4553 if (!cfg->input_pins[AUTO_PIN_MIC] &&
4554 cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
4555 cfg->input_pins[AUTO_PIN_MIC] =
4556 cfg->input_pins[AUTO_PIN_FRONT_MIC];
4557 cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0;
4558 }
4559 /* ditto for line-in */
4560 if (!cfg->input_pins[AUTO_PIN_LINE] &&
4561 cfg->input_pins[AUTO_PIN_FRONT_LINE]) {
4562 cfg->input_pins[AUTO_PIN_LINE] =
4563 cfg->input_pins[AUTO_PIN_FRONT_LINE];
4564 cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0;
4565 }
4566
4567 /* 4573 /*
4568 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin 4574 * FIX-UP: if no line-outs are detected, try to use speaker or HP pin
4569 * as a primary output 4575 * as a primary output
@@ -4602,6 +4608,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4602 break; 4608 break;
4603 } 4609 }
4604 4610
4611 sort_autocfg_input_pins(cfg);
4612
4605 /* 4613 /*
4606 * debug prints of the parsed results 4614 * debug prints of the parsed results
4607 */ 4615 */
@@ -4621,14 +4629,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4621 if (cfg->dig_outs) 4629 if (cfg->dig_outs)
4622 snd_printd(" dig-out=0x%x/0x%x\n", 4630 snd_printd(" dig-out=0x%x/0x%x\n",
4623 cfg->dig_out_pins[0], cfg->dig_out_pins[1]); 4631 cfg->dig_out_pins[0], cfg->dig_out_pins[1]);
4624 snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," 4632 snd_printd(" inputs:");
4625 " cd=0x%x, aux=0x%x\n", 4633 for (i = 0; i < cfg->num_inputs; i++) {
4626 cfg->input_pins[AUTO_PIN_MIC], 4634 snd_printdd(" %s=0x%x",
4627 cfg->input_pins[AUTO_PIN_FRONT_MIC], 4635 hda_get_autocfg_input_label(codec, cfg, i),
4628 cfg->input_pins[AUTO_PIN_LINE], 4636 cfg->inputs[i].pin);
4629 cfg->input_pins[AUTO_PIN_FRONT_LINE], 4637 }
4630 cfg->input_pins[AUTO_PIN_CD], 4638 snd_printd("\n");
4631 cfg->input_pins[AUTO_PIN_AUX]);
4632 if (cfg->dig_in_pin) 4639 if (cfg->dig_in_pin)
4633 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); 4640 snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin);
4634 4641
@@ -4636,11 +4643,165 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
4636} 4643}
4637EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); 4644EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
4638 4645
4639/* labels for input pins */ 4646int snd_hda_get_input_pin_attr(unsigned int def_conf)
4640const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = { 4647{
4641 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" 4648 unsigned int loc = get_defcfg_location(def_conf);
4642}; 4649 unsigned int conn = get_defcfg_connect(def_conf);
4643EXPORT_SYMBOL_HDA(auto_pin_cfg_labels); 4650 if (conn == AC_JACK_PORT_NONE)
4651 return INPUT_PIN_ATTR_UNUSED;
4652 /* Windows may claim the internal mic to be BOTH, too */
4653 if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH)
4654 return INPUT_PIN_ATTR_INT;
4655 if ((loc & 0x30) == AC_JACK_LOC_INTERNAL)
4656 return INPUT_PIN_ATTR_INT;
4657 if ((loc & 0x30) == AC_JACK_LOC_SEPARATE)
4658 return INPUT_PIN_ATTR_DOCK;
4659 if (loc == AC_JACK_LOC_REAR)
4660 return INPUT_PIN_ATTR_REAR;
4661 if (loc == AC_JACK_LOC_FRONT)
4662 return INPUT_PIN_ATTR_FRONT;
4663 return INPUT_PIN_ATTR_NORMAL;
4664}
4665EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
4666
4667/**
4668 * hda_get_input_pin_label - Give a label for the given input pin
4669 *
4670 * When check_location is true, the function checks the pin location
4671 * for mic and line-in pins, and set an appropriate prefix like "Front",
4672 * "Rear", "Internal".
4673 */
4674
4675const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
4676 int check_location)
4677{
4678 unsigned int def_conf;
4679 static const char *mic_names[] = {
4680 "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic",
4681 };
4682 int attr;
4683
4684 def_conf = snd_hda_codec_get_pincfg(codec, pin);
4685
4686 switch (get_defcfg_device(def_conf)) {
4687 case AC_JACK_MIC_IN:
4688 if (!check_location)
4689 return "Mic";
4690 attr = snd_hda_get_input_pin_attr(def_conf);
4691 if (!attr)
4692 return "None";
4693 return mic_names[attr - 1];
4694 case AC_JACK_LINE_IN:
4695 if (!check_location)
4696 return "Line";
4697 attr = snd_hda_get_input_pin_attr(def_conf);
4698 if (!attr)
4699 return "None";
4700 if (attr == INPUT_PIN_ATTR_DOCK)
4701 return "Dock Line";
4702 return "Line";
4703 case AC_JACK_AUX:
4704 return "Aux";
4705 case AC_JACK_CD:
4706 return "CD";
4707 case AC_JACK_SPDIF_IN:
4708 return "SPDIF In";
4709 case AC_JACK_DIG_OTHER_IN:
4710 return "Digital In";
4711 default:
4712 return "Misc";
4713 }
4714}
4715EXPORT_SYMBOL_HDA(hda_get_input_pin_label);
4716
4717/* Check whether the location prefix needs to be added to the label.
4718 * If all mic-jacks are in the same location (e.g. rear panel), we don't
4719 * have to put "Front" prefix to each label. In such a case, returns false.
4720 */
4721static int check_mic_location_need(struct hda_codec *codec,
4722 const struct auto_pin_cfg *cfg,
4723 int input)
4724{
4725 unsigned int defc;
4726 int i, attr, attr2;
4727
4728 defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin);
4729 attr = snd_hda_get_input_pin_attr(defc);
4730 /* for internal or docking mics, we need locations */
4731 if (attr <= INPUT_PIN_ATTR_NORMAL)
4732 return 1;
4733
4734 attr = 0;
4735 for (i = 0; i < cfg->num_inputs; i++) {
4736 defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin);
4737 attr2 = snd_hda_get_input_pin_attr(defc);
4738 if (attr2 >= INPUT_PIN_ATTR_NORMAL) {
4739 if (attr && attr != attr2)
4740 return 1; /* different locations found */
4741 attr = attr2;
4742 }
4743 }
4744 return 0;
4745}
4746
4747/**
4748 * hda_get_autocfg_input_label - Get a label for the given input
4749 *
4750 * Get a label for the given input pin defined by the autocfg item.
4751 * Unlike hda_get_input_pin_label(), this function checks all inputs
4752 * defined in autocfg and avoids the redundant mic/line prefix as much as
4753 * possible.
4754 */
4755const char *hda_get_autocfg_input_label(struct hda_codec *codec,
4756 const struct auto_pin_cfg *cfg,
4757 int input)
4758{
4759 int type = cfg->inputs[input].type;
4760 int has_multiple_pins = 0;
4761
4762 if ((input > 0 && cfg->inputs[input - 1].type == type) ||
4763 (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type))
4764 has_multiple_pins = 1;
4765 if (has_multiple_pins && type == AUTO_PIN_MIC)
4766 has_multiple_pins &= check_mic_location_need(codec, cfg, input);
4767 return hda_get_input_pin_label(codec, cfg->inputs[input].pin,
4768 has_multiple_pins);
4769}
4770EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
4771
4772/**
4773 * snd_hda_add_imux_item - Add an item to input_mux
4774 *
4775 * When the same label is used already in the existing items, the number
4776 * suffix is appended to the label. This label index number is stored
4777 * to type_idx when non-NULL pointer is given.
4778 */
4779int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
4780 int index, int *type_idx)
4781{
4782 int i, label_idx = 0;
4783 if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
4784 snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
4785 return -EINVAL;
4786 }
4787 for (i = 0; i < imux->num_items; i++) {
4788 if (!strncmp(label, imux->items[i].label, strlen(label)))
4789 label_idx++;
4790 }
4791 if (type_idx)
4792 *type_idx = label_idx;
4793 if (label_idx > 0)
4794 snprintf(imux->items[imux->num_items].label,
4795 sizeof(imux->items[imux->num_items].label),
4796 "%s %d", label, label_idx);
4797 else
4798 strlcpy(imux->items[imux->num_items].label, label,
4799 sizeof(imux->items[imux->num_items].label));
4800 imux->items[imux->num_items].index = index;
4801 imux->num_items++;
4802 return 0;
4803}
4804EXPORT_SYMBOL_HDA(snd_hda_add_imux_item);
4644 4805
4645 4806
4646#ifdef CONFIG_PM 4807#ifdef CONFIG_PM
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 62c702240108..fdf8d44f8b6b 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -850,6 +850,7 @@ struct hda_codec {
850 unsigned int pin_amp_workaround:1; /* pin out-amp takes index 850 unsigned int pin_amp_workaround:1; /* pin out-amp takes index
851 * (e.g. Conexant codecs) 851 * (e.g. Conexant codecs)
852 */ 852 */
853 unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
853 unsigned int pins_shutup:1; /* pins are shut up */ 854 unsigned int pins_shutup:1; /* pins are shut up */
854 unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ 855 unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
855#ifdef CONFIG_SND_HDA_POWER_SAVE 856#ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -989,6 +990,18 @@ int snd_hda_suspend(struct hda_bus *bus);
989int snd_hda_resume(struct hda_bus *bus); 990int snd_hda_resume(struct hda_bus *bus);
990#endif 991#endif
991 992
993#ifdef CONFIG_SND_HDA_POWER_SAVE
994static inline
995int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid)
996{
997 if (codec->patch_ops.check_power_status)
998 return codec->patch_ops.check_power_status(codec, nid);
999 return 0;
1000}
1001#else
1002#define hda_call_check_power_status(codec, nid) 0
1003#endif
1004
992/* 1005/*
993 * get widget information 1006 * get widget information
994 */ 1007 */
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 26c3ade73583..cb0c23a6b473 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -332,7 +332,6 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
332 return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, 332 return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
333 AC_DIPSIZE_ELD_BUF); 333 AC_DIPSIZE_ELD_BUF);
334} 334}
335EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size);
336 335
337int snd_hdmi_get_eld(struct hdmi_eld *eld, 336int snd_hdmi_get_eld(struct hdmi_eld *eld,
338 struct hda_codec *codec, hda_nid_t nid) 337 struct hda_codec *codec, hda_nid_t nid)
@@ -368,7 +367,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
368 kfree(buf); 367 kfree(buf);
369 return ret; 368 return ret;
370} 369}
371EXPORT_SYMBOL_HDA(snd_hdmi_get_eld);
372 370
373static void hdmi_show_short_audio_desc(struct cea_sad *a) 371static void hdmi_show_short_audio_desc(struct cea_sad *a)
374{ 372{
@@ -407,7 +405,6 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
407 } 405 }
408 buf[j] = '\0'; /* necessary when j == 0 */ 406 buf[j] = '\0'; /* necessary when j == 0 */
409} 407}
410EXPORT_SYMBOL_HDA(snd_print_channel_allocation);
411 408
412void snd_hdmi_show_eld(struct hdmi_eld *e) 409void snd_hdmi_show_eld(struct hdmi_eld *e)
413{ 410{
@@ -426,7 +423,6 @@ void snd_hdmi_show_eld(struct hdmi_eld *e)
426 for (i = 0; i < e->sad_count; i++) 423 for (i = 0; i < e->sad_count; i++)
427 hdmi_show_short_audio_desc(e->sad + i); 424 hdmi_show_short_audio_desc(e->sad + i);
428} 425}
429EXPORT_SYMBOL_HDA(snd_hdmi_show_eld);
430 426
431#ifdef CONFIG_PROC_FS 427#ifdef CONFIG_PROC_FS
432 428
@@ -585,7 +581,6 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
585 581
586 return 0; 582 return 0;
587} 583}
588EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new);
589 584
590void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) 585void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
591{ 586{
@@ -594,7 +589,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
594 eld->proc_entry = NULL; 589 eld->proc_entry = NULL;
595 } 590 }
596} 591}
597EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
598 592
599#endif /* CONFIG_PROC_FS */ 593#endif /* CONFIG_PROC_FS */
600 594
@@ -645,4 +639,3 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm,
645 pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max); 639 pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max);
646 pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps); 640 pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps);
647} 641}
648EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info);
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 5ea21285ee1f..fb0582f8d725 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -61,7 +61,6 @@ struct hda_gspec {
61 struct hda_gnode *cap_vol_node; /* Node for capture volume */ 61 struct hda_gnode *cap_vol_node; /* Node for capture volume */
62 unsigned int cur_cap_src; /* current capture source */ 62 unsigned int cur_cap_src; /* current capture source */
63 struct hda_input_mux input_mux; 63 struct hda_input_mux input_mux;
64 char cap_labels[HDA_MAX_NUM_INPUTS][16];
65 64
66 unsigned int def_amp_in_caps; 65 unsigned int def_amp_in_caps;
67 unsigned int def_amp_out_caps; 66 unsigned int def_amp_out_caps;
@@ -506,11 +505,10 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
506 * returns 0 if not found, 1 if found, or a negative error code. 505 * returns 0 if not found, 1 if found, or a negative error code.
507 */ 506 */
508static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, 507static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
509 struct hda_gnode *node) 508 struct hda_gnode *node, int idx)
510{ 509{
511 int i, err; 510 int i, err;
512 unsigned int pinctl; 511 unsigned int pinctl;
513 char *label;
514 const char *type; 512 const char *type;
515 513
516 if (node->checked) 514 if (node->checked)
@@ -523,7 +521,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
523 child = hda_get_node(spec, node->conn_list[i]); 521 child = hda_get_node(spec, node->conn_list[i]);
524 if (! child) 522 if (! child)
525 continue; 523 continue;
526 err = parse_adc_sub_nodes(codec, spec, child); 524 err = parse_adc_sub_nodes(codec, spec, child, idx);
527 if (err < 0) 525 if (err < 0)
528 return err; 526 return err;
529 if (err > 0) { 527 if (err > 0) {
@@ -564,9 +562,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
564 return 0; 562 return 0;
565 type = "Input"; 563 type = "Input";
566 } 564 }
567 label = spec->cap_labels[spec->input_mux.num_items]; 565 snd_hda_add_imux_item(&spec->input_mux, type, idx, NULL);
568 strcpy(label, type);
569 spec->input_mux.items[spec->input_mux.num_items].label = label;
570 566
571 /* unmute the PIN external input */ 567 /* unmute the PIN external input */
572 unmute_input(codec, node, 0); /* index = 0? */ 568 unmute_input(codec, node, 0); /* index = 0? */
@@ -577,29 +573,6 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
577 return 1; /* found */ 573 return 1; /* found */
578} 574}
579 575
580/* add a capture source element */
581static void add_cap_src(struct hda_gspec *spec, int idx)
582{
583 struct hda_input_mux_item *csrc;
584 char *buf;
585 int num, ocap;
586
587 num = spec->input_mux.num_items;
588 csrc = &spec->input_mux.items[num];
589 buf = spec->cap_labels[num];
590 for (ocap = 0; ocap < num; ocap++) {
591 if (! strcmp(buf, spec->cap_labels[ocap])) {
592 /* same label already exists,
593 * put the index number to be unique
594 */
595 sprintf(buf, "%s %d", spec->cap_labels[ocap], num);
596 break;
597 }
598 }
599 csrc->index = idx;
600 spec->input_mux.num_items++;
601}
602
603/* 576/*
604 * parse input 577 * parse input
605 */ 578 */
@@ -624,22 +597,18 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node)
624 for (i = 0; i < adc_node->nconns; i++) { 597 for (i = 0; i < adc_node->nconns; i++) {
625 node = hda_get_node(spec, adc_node->conn_list[i]); 598 node = hda_get_node(spec, adc_node->conn_list[i]);
626 if (node && node->type == AC_WID_PIN) { 599 if (node && node->type == AC_WID_PIN) {
627 err = parse_adc_sub_nodes(codec, spec, node); 600 err = parse_adc_sub_nodes(codec, spec, node, i);
628 if (err < 0) 601 if (err < 0)
629 return err; 602 return err;
630 else if (err > 0)
631 add_cap_src(spec, i);
632 } 603 }
633 } 604 }
634 /* ... then check the rests, more complicated connections */ 605 /* ... then check the rests, more complicated connections */
635 for (i = 0; i < adc_node->nconns; i++) { 606 for (i = 0; i < adc_node->nconns; i++) {
636 node = hda_get_node(spec, adc_node->conn_list[i]); 607 node = hda_get_node(spec, adc_node->conn_list[i]);
637 if (node && node->type != AC_WID_PIN) { 608 if (node && node->type != AC_WID_PIN) {
638 err = parse_adc_sub_nodes(codec, spec, node); 609 err = parse_adc_sub_nodes(codec, spec, node, i);
639 if (err < 0) 610 if (err < 0)
640 return err; 611 return err;
641 else if (err > 0)
642 add_cap_src(spec, i);
643 } 612 }
644 } 613 }
645 614
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 34940a079051..21aa9b0e28f6 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -78,8 +78,8 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
78module_param_array(model, charp, NULL, 0444); 78module_param_array(model, charp, NULL, 0444);
79MODULE_PARM_DESC(model, "Use the given board model."); 79MODULE_PARM_DESC(model, "Use the given board model.");
80module_param_array(position_fix, int, NULL, 0444); 80module_param_array(position_fix, int, NULL, 0444);
81MODULE_PARM_DESC(position_fix, "Fix DMA pointer " 81MODULE_PARM_DESC(position_fix, "DMA pointer read method."
82 "(0 = auto, 1 = none, 2 = POSBUF)."); 82 "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO).");
83module_param_array(bdl_pos_adj, int, NULL, 0644); 83module_param_array(bdl_pos_adj, int, NULL, 0644);
84MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); 84MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
85module_param_array(probe_mask, int, NULL, 0444); 85module_param_array(probe_mask, int, NULL, 0444);
@@ -305,6 +305,7 @@ enum {
305 POS_FIX_AUTO, 305 POS_FIX_AUTO,
306 POS_FIX_LPIB, 306 POS_FIX_LPIB,
307 POS_FIX_POSBUF, 307 POS_FIX_POSBUF,
308 POS_FIX_VIACOMBO,
308}; 309};
309 310
310/* Defines for ATI HD Audio support in SB450 south bridge */ 311/* Defines for ATI HD Audio support in SB450 south bridge */
@@ -433,7 +434,6 @@ struct azx {
433 unsigned int polling_mode :1; 434 unsigned int polling_mode :1;
434 unsigned int msi :1; 435 unsigned int msi :1;
435 unsigned int irq_pending_warned :1; 436 unsigned int irq_pending_warned :1;
436 unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */
437 unsigned int probing :1; /* codec probing phase */ 437 unsigned int probing :1; /* codec probing phase */
438 438
439 /* for debugging */ 439 /* for debugging */
@@ -458,6 +458,7 @@ enum {
458 AZX_DRIVER_ULI, 458 AZX_DRIVER_ULI,
459 AZX_DRIVER_NVIDIA, 459 AZX_DRIVER_NVIDIA,
460 AZX_DRIVER_TERA, 460 AZX_DRIVER_TERA,
461 AZX_DRIVER_CTX,
461 AZX_DRIVER_GENERIC, 462 AZX_DRIVER_GENERIC,
462 AZX_NUM_DRIVERS, /* keep this as last entry */ 463 AZX_NUM_DRIVERS, /* keep this as last entry */
463}; 464};
@@ -473,6 +474,7 @@ static char *driver_short_names[] __devinitdata = {
473 [AZX_DRIVER_ULI] = "HDA ULI M5461", 474 [AZX_DRIVER_ULI] = "HDA ULI M5461",
474 [AZX_DRIVER_NVIDIA] = "HDA NVidia", 475 [AZX_DRIVER_NVIDIA] = "HDA NVidia",
475 [AZX_DRIVER_TERA] = "HDA Teradici", 476 [AZX_DRIVER_TERA] = "HDA Teradici",
477 [AZX_DRIVER_CTX] = "HDA Creative",
476 [AZX_DRIVER_GENERIC] = "HD-Audio Generic", 478 [AZX_DRIVER_GENERIC] = "HD-Audio Generic",
477}; 479};
478 480
@@ -563,7 +565,10 @@ static void azx_init_cmd_io(struct azx *chip)
563 /* reset the rirb hw write pointer */ 565 /* reset the rirb hw write pointer */
564 azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); 566 azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
565 /* set N=1, get RIRB response interrupt for new entry */ 567 /* set N=1, get RIRB response interrupt for new entry */
566 azx_writew(chip, RINTCNT, 1); 568 if (chip->driver_type == AZX_DRIVER_CTX)
569 azx_writew(chip, RINTCNT, 0xc0);
570 else
571 azx_writew(chip, RINTCNT, 1);
567 /* enable rirb dma and response irq */ 572 /* enable rirb dma and response irq */
568 azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); 573 azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
569 spin_unlock_irq(&chip->reg_lock); 574 spin_unlock_irq(&chip->reg_lock);
@@ -1136,8 +1141,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
1136 /* clear rirb int */ 1141 /* clear rirb int */
1137 status = azx_readb(chip, RIRBSTS); 1142 status = azx_readb(chip, RIRBSTS);
1138 if (status & RIRB_INT_MASK) { 1143 if (status & RIRB_INT_MASK) {
1139 if (status & RIRB_INT_RESPONSE) 1144 if (status & RIRB_INT_RESPONSE) {
1145 if (chip->driver_type == AZX_DRIVER_CTX)
1146 udelay(80);
1140 azx_update_rirb(chip); 1147 azx_update_rirb(chip);
1148 }
1141 azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); 1149 azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
1142 } 1150 }
1143 1151
@@ -1309,11 +1317,8 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
1309 azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); 1317 azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr));
1310 1318
1311 /* enable the position buffer */ 1319 /* enable the position buffer */
1312 if (chip->position_fix[0] == POS_FIX_POSBUF || 1320 if (chip->position_fix[0] != POS_FIX_LPIB ||
1313 chip->position_fix[0] == POS_FIX_AUTO || 1321 chip->position_fix[1] != POS_FIX_LPIB) {
1314 chip->position_fix[1] == POS_FIX_POSBUF ||
1315 chip->position_fix[1] == POS_FIX_AUTO ||
1316 chip->via_dmapos_patch) {
1317 if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) 1322 if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
1318 azx_writel(chip, DPLBASE, 1323 azx_writel(chip, DPLBASE,
1319 (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); 1324 (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
@@ -1647,7 +1652,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
1647 struct azx_dev *azx_dev = get_azx_dev(substream); 1652 struct azx_dev *azx_dev = get_azx_dev(substream);
1648 struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; 1653 struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
1649 struct snd_pcm_runtime *runtime = substream->runtime; 1654 struct snd_pcm_runtime *runtime = substream->runtime;
1650 unsigned int bufsize, period_bytes, format_val; 1655 unsigned int bufsize, period_bytes, format_val, stream_tag;
1651 int err; 1656 int err;
1652 1657
1653 azx_stream_reset(chip, azx_dev); 1658 azx_stream_reset(chip, azx_dev);
@@ -1689,7 +1694,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
1689 else 1694 else
1690 azx_dev->fifo_size = 0; 1695 azx_dev->fifo_size = 0;
1691 1696
1692 return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag, 1697 stream_tag = azx_dev->stream_tag;
1698 /* CA-IBG chips need the playback stream starting from 1 */
1699 if (chip->driver_type == AZX_DRIVER_CTX &&
1700 stream_tag > chip->capture_streams)
1701 stream_tag -= chip->capture_streams;
1702 return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
1693 azx_dev->format_val, substream); 1703 azx_dev->format_val, substream);
1694} 1704}
1695 1705
@@ -1852,20 +1862,21 @@ static unsigned int azx_get_position(struct azx *chip,
1852 struct azx_dev *azx_dev) 1862 struct azx_dev *azx_dev)
1853{ 1863{
1854 unsigned int pos; 1864 unsigned int pos;
1865 int stream = azx_dev->substream->stream;
1855 1866
1856 if (chip->via_dmapos_patch) 1867 switch (chip->position_fix[stream]) {
1868 case POS_FIX_LPIB:
1869 /* read LPIB */
1870 pos = azx_sd_readl(azx_dev, SD_LPIB);
1871 break;
1872 case POS_FIX_VIACOMBO:
1857 pos = azx_via_get_position(chip, azx_dev); 1873 pos = azx_via_get_position(chip, azx_dev);
1858 else { 1874 break;
1859 int stream = azx_dev->substream->stream; 1875 default:
1860 if (chip->position_fix[stream] == POS_FIX_POSBUF || 1876 /* use the position buffer */
1861 chip->position_fix[stream] == POS_FIX_AUTO) { 1877 pos = le32_to_cpu(*azx_dev->posbuf);
1862 /* use the position buffer */
1863 pos = le32_to_cpu(*azx_dev->posbuf);
1864 } else {
1865 /* read LPIB */
1866 pos = azx_sd_readl(azx_dev, SD_LPIB);
1867 }
1868 } 1878 }
1879
1869 if (pos >= azx_dev->bufsize) 1880 if (pos >= azx_dev->bufsize)
1870 pos = 0; 1881 pos = 0;
1871 return pos; 1882 return pos;
@@ -2313,19 +2324,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
2313 switch (fix) { 2324 switch (fix) {
2314 case POS_FIX_LPIB: 2325 case POS_FIX_LPIB:
2315 case POS_FIX_POSBUF: 2326 case POS_FIX_POSBUF:
2327 case POS_FIX_VIACOMBO:
2316 return fix; 2328 return fix;
2317 } 2329 }
2318 2330
2319 /* Check VIA/ATI HD Audio Controller exist */
2320 switch (chip->driver_type) {
2321 case AZX_DRIVER_VIA:
2322 case AZX_DRIVER_ATI:
2323 chip->via_dmapos_patch = 1;
2324 /* Use link position directly, avoid any transfer problem. */
2325 return POS_FIX_LPIB;
2326 }
2327 chip->via_dmapos_patch = 0;
2328
2329 q = snd_pci_quirk_lookup(chip->pci, position_fix_list); 2331 q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
2330 if (q) { 2332 if (q) {
2331 printk(KERN_INFO 2333 printk(KERN_INFO
@@ -2334,6 +2336,15 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
2334 q->value, q->subvendor, q->subdevice); 2336 q->value, q->subvendor, q->subdevice);
2335 return q->value; 2337 return q->value;
2336 } 2338 }
2339
2340 /* Check VIA/ATI HD Audio Controller exist */
2341 switch (chip->driver_type) {
2342 case AZX_DRIVER_VIA:
2343 case AZX_DRIVER_ATI:
2344 /* Use link position directly, avoid any transfer problem. */
2345 return POS_FIX_VIACOMBO;
2346 }
2347
2337 return POS_FIX_AUTO; 2348 return POS_FIX_AUTO;
2338} 2349}
2339 2350
@@ -2735,25 +2746,17 @@ static void __devexit azx_remove(struct pci_dev *pci)
2735 2746
2736/* PCI IDs */ 2747/* PCI IDs */
2737static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { 2748static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
2738 /* ICH 6..10 */
2739 { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
2740 { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
2741 { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
2742 { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
2743 { PCI_DEVICE(0x8086, 0x2911), .driver_data = AZX_DRIVER_ICH },
2744 { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
2745 { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
2746 { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
2747 { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
2748 /* PCH */
2749 { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH },
2750 { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH },
2751 /* CPT */ 2749 /* CPT */
2752 { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, 2750 { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
2753 /* PBG */ 2751 /* PBG */
2754 { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, 2752 { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH },
2755 /* SCH */ 2753 /* SCH */
2756 { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, 2754 { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
2755 /* Generic Intel */
2756 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
2757 .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
2758 .class_mask = 0xffffff,
2759 .driver_data = AZX_DRIVER_ICH },
2757 /* ATI SB 450/600 */ 2760 /* ATI SB 450/600 */
2758 { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI }, 2761 { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
2759 { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI }, 2762 { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
@@ -2794,11 +2797,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
2794 { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), 2797 { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
2795 .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, 2798 .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
2796 .class_mask = 0xffffff, 2799 .class_mask = 0xffffff,
2797 .driver_data = AZX_DRIVER_GENERIC }, 2800 .driver_data = AZX_DRIVER_CTX },
2798#else 2801#else
2799 /* this entry seems still valid -- i.e. without emu20kx chip */ 2802 /* this entry seems still valid -- i.e. without emu20kx chip */
2800 { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC }, 2803 { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX },
2801#endif 2804#endif
2805 /* Vortex86MX */
2806 { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
2802 /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */ 2807 /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */
2803 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), 2808 { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
2804 .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, 2809 .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 28ab4aead48f..46bbefe2e4a9 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -38,10 +38,11 @@
38 */ 38 */
39#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ 39#define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \
40 ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) 40 ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23))
41#define HDA_AMP_VAL_MIN_MUTE (1<<29)
41#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ 42#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \
42 HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) 43 HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0)
43/* mono volume with index (index=0,1,...) (channel=1,2) */ 44/* mono volume with index (index=0,1,...) (channel=1,2) */
44#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ 45#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, dir, flags) \
45 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ 46 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
46 .subdevice = HDA_SUBDEV_AMP_FLAG, \ 47 .subdevice = HDA_SUBDEV_AMP_FLAG, \
47 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ 48 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
@@ -51,16 +52,20 @@
51 .get = snd_hda_mixer_amp_volume_get, \ 52 .get = snd_hda_mixer_amp_volume_get, \
52 .put = snd_hda_mixer_amp_volume_put, \ 53 .put = snd_hda_mixer_amp_volume_put, \
53 .tlv = { .c = snd_hda_mixer_amp_tlv }, \ 54 .tlv = { .c = snd_hda_mixer_amp_tlv }, \
54 .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } 55 .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, dir) | flags }
55/* stereo volume with index */ 56/* stereo volume with index */
56#define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ 57#define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \
57 HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) 58 HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction, 0)
58/* mono volume */ 59/* mono volume */
59#define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ 60#define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \
60 HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction) 61 HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction, 0)
61/* stereo volume */ 62/* stereo volume */
62#define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ 63#define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \
63 HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) 64 HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction)
65/* stereo volume with min=mute */
66#define HDA_CODEC_VOLUME_MIN_MUTE(xname, nid, xindex, direction) \
67 HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, 3, xindex, direction, \
68 HDA_AMP_VAL_MIN_MUTE)
64/* mono mute switch with index (index=0,1,...) (channel=1,2) */ 69/* mono mute switch with index (index=0,1,...) (channel=1,2) */
65#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ 70#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
66 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ 71 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
@@ -215,7 +220,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
215 */ 220 */
216#define HDA_MAX_NUM_INPUTS 16 221#define HDA_MAX_NUM_INPUTS 16
217struct hda_input_mux_item { 222struct hda_input_mux_item {
218 const char *label; 223 char label[32];
219 unsigned int index; 224 unsigned int index;
220}; 225};
221struct hda_input_mux { 226struct hda_input_mux {
@@ -366,9 +371,7 @@ struct hda_bus_unsolicited {
366 371
367enum { 372enum {
368 AUTO_PIN_MIC, 373 AUTO_PIN_MIC,
369 AUTO_PIN_FRONT_MIC, 374 AUTO_PIN_LINE_IN,
370 AUTO_PIN_LINE,
371 AUTO_PIN_FRONT_LINE,
372 AUTO_PIN_CD, 375 AUTO_PIN_CD,
373 AUTO_PIN_AUX, 376 AUTO_PIN_AUX,
374 AUTO_PIN_LAST 377 AUTO_PIN_LAST
@@ -380,9 +383,33 @@ enum {
380 AUTO_PIN_HP_OUT 383 AUTO_PIN_HP_OUT
381}; 384};
382 385
383extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST];
384
385#define AUTO_CFG_MAX_OUTS 5 386#define AUTO_CFG_MAX_OUTS 5
387#define AUTO_CFG_MAX_INS 8
388
389struct auto_pin_cfg_item {
390 hda_nid_t pin;
391 int type;
392};
393
394struct auto_pin_cfg;
395const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
396 int check_location);
397const char *hda_get_autocfg_input_label(struct hda_codec *codec,
398 const struct auto_pin_cfg *cfg,
399 int input);
400int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
401 int index, int *type_index_ret);
402
403enum {
404 INPUT_PIN_ATTR_UNUSED, /* pin not connected */
405 INPUT_PIN_ATTR_INT, /* internal mic/line-in */
406 INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */
407 INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */
408 INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */
409 INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */
410};
411
412int snd_hda_get_input_pin_attr(unsigned int def_conf);
386 413
387struct auto_pin_cfg { 414struct auto_pin_cfg {
388 int line_outs; 415 int line_outs;
@@ -393,7 +420,8 @@ struct auto_pin_cfg {
393 int hp_outs; 420 int hp_outs;
394 int line_out_type; /* AUTO_PIN_XXX_OUT */ 421 int line_out_type; /* AUTO_PIN_XXX_OUT */
395 hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; 422 hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS];
396 hda_nid_t input_pins[AUTO_PIN_LAST]; 423 int num_inputs;
424 struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS];
397 int dig_outs; 425 int dig_outs;
398 hda_nid_t dig_out_pins[2]; 426 hda_nid_t dig_out_pins[2];
399 hda_nid_t dig_in_pin; 427 hda_nid_t dig_in_pin;
@@ -558,6 +586,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
558#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) 586#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
559#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) 587#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
560#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) 588#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f)
589#define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1)
561 590
562/* 591/*
563 * CEA Short Audio Descriptor data 592 * CEA Short Audio Descriptor data
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 10bbbaf6ebc3..f7ff3f7ccb8e 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -1276,6 +1276,7 @@ static int patch_ad1986a(struct hda_codec *codec)
1276 spec->multiout.no_share_stream = 1; 1276 spec->multiout.no_share_stream = 1;
1277 1277
1278 codec->no_trigger_sense = 1; 1278 codec->no_trigger_sense = 1;
1279 codec->no_sticky_stream = 1;
1279 1280
1280 return 0; 1281 return 0;
1281} 1282}
@@ -1463,6 +1464,7 @@ static int patch_ad1983(struct hda_codec *codec)
1463 codec->patch_ops = ad198x_patch_ops; 1464 codec->patch_ops = ad198x_patch_ops;
1464 1465
1465 codec->no_trigger_sense = 1; 1466 codec->no_trigger_sense = 1;
1467 codec->no_sticky_stream = 1;
1466 1468
1467 return 0; 1469 return 0;
1468} 1470}
@@ -1917,6 +1919,7 @@ static int patch_ad1981(struct hda_codec *codec)
1917 } 1919 }
1918 1920
1919 codec->no_trigger_sense = 1; 1921 codec->no_trigger_sense = 1;
1922 codec->no_sticky_stream = 1;
1920 1923
1921 return 0; 1924 return 0;
1922} 1925}
@@ -2880,7 +2883,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
2880 2883
2881/* create input playback/capture controls for the given pin */ 2884/* create input playback/capture controls for the given pin */
2882static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, 2885static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2883 const char *ctlname, int boost) 2886 const char *ctlname, int ctlidx, int boost)
2884{ 2887{
2885 char name[32]; 2888 char name[32];
2886 int err, idx; 2889 int err, idx;
@@ -2909,25 +2912,27 @@ static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin,
2909} 2912}
2910 2913
2911/* create playback/capture controls for input pins */ 2914/* create playback/capture controls for input pins */
2912static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec, 2915static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec,
2913 const struct auto_pin_cfg *cfg) 2916 const struct auto_pin_cfg *cfg)
2914{ 2917{
2918 struct ad198x_spec *spec = codec->spec;
2915 struct hda_input_mux *imux = &spec->private_imux; 2919 struct hda_input_mux *imux = &spec->private_imux;
2916 int i, err; 2920 int i, err, type, type_idx;
2917 2921
2918 for (i = 0; i < AUTO_PIN_LAST; i++) { 2922 for (i = 0; i < cfg->num_inputs; i++) {
2919 err = new_analog_input(spec, cfg->input_pins[i], 2923 const char *label;
2920 auto_pin_cfg_labels[i], 2924 type = cfg->inputs[i].type;
2921 i <= AUTO_PIN_FRONT_MIC); 2925 label = hda_get_autocfg_input_label(codec, cfg, i);
2926 snd_hda_add_imux_item(imux, label,
2927 ad1988_pin_to_adc_idx(cfg->inputs[i].pin),
2928 &type_idx);
2929 err = new_analog_input(spec, cfg->inputs[i].pin,
2930 label, type_idx,
2931 type == AUTO_PIN_MIC);
2922 if (err < 0) 2932 if (err < 0)
2923 return err; 2933 return err;
2924 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
2925 imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]);
2926 imux->num_items++;
2927 } 2934 }
2928 imux->items[imux->num_items].label = "Mix"; 2935 snd_hda_add_imux_item(imux, "Mix", 9, NULL);
2929 imux->items[imux->num_items].index = 9;
2930 imux->num_items++;
2931 2936
2932 if ((err = add_control(spec, AD_CTL_WIDGET_VOL, 2937 if ((err = add_control(spec, AD_CTL_WIDGET_VOL,
2933 "Analog Mix Playback Volume", 2938 "Analog Mix Playback Volume",
@@ -2994,12 +2999,11 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec)
2994static void ad1988_auto_init_analog_input(struct hda_codec *codec) 2999static void ad1988_auto_init_analog_input(struct hda_codec *codec)
2995{ 3000{
2996 struct ad198x_spec *spec = codec->spec; 3001 struct ad198x_spec *spec = codec->spec;
3002 const struct auto_pin_cfg *cfg = &spec->autocfg;
2997 int i, idx; 3003 int i, idx;
2998 3004
2999 for (i = 0; i < AUTO_PIN_LAST; i++) { 3005 for (i = 0; i < cfg->num_inputs; i++) {
3000 hda_nid_t nid = spec->autocfg.input_pins[i]; 3006 hda_nid_t nid = cfg->inputs[i].pin;
3001 if (! nid)
3002 continue;
3003 switch (nid) { 3007 switch (nid) {
3004 case 0x15: /* port-C */ 3008 case 0x15: /* port-C */
3005 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); 3009 snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
@@ -3009,7 +3013,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
3009 break; 3013 break;
3010 } 3014 }
3011 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, 3015 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
3012 i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); 3016 i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
3013 if (nid != AD1988_PIN_CD_NID) 3017 if (nid != AD1988_PIN_CD_NID)
3014 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 3018 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
3015 AMP_OUT_MUTE); 3019 AMP_OUT_MUTE);
@@ -3040,7 +3044,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
3040 "Speaker")) < 0 || 3044 "Speaker")) < 0 ||
3041 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], 3045 (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
3042 "Headphone")) < 0 || 3046 "Headphone")) < 0 ||
3043 (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) 3047 (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
3044 return err; 3048 return err;
3045 3049
3046 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 3050 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
@@ -3235,6 +3239,7 @@ static int patch_ad1988(struct hda_codec *codec)
3235 spec->vmaster_nid = 0x04; 3239 spec->vmaster_nid = 0x04;
3236 3240
3237 codec->no_trigger_sense = 1; 3241 codec->no_trigger_sense = 1;
3242 codec->no_sticky_stream = 1;
3238 3243
3239 return 0; 3244 return 0;
3240} 3245}
@@ -3449,6 +3454,7 @@ static int patch_ad1884(struct hda_codec *codec)
3449 codec->patch_ops = ad198x_patch_ops; 3454 codec->patch_ops = ad198x_patch_ops;
3450 3455
3451 codec->no_trigger_sense = 1; 3456 codec->no_trigger_sense = 1;
3457 codec->no_sticky_stream = 1;
3452 3458
3453 return 0; 3459 return 0;
3454} 3460}
@@ -4422,6 +4428,7 @@ static int patch_ad1884a(struct hda_codec *codec)
4422 } 4428 }
4423 4429
4424 codec->no_trigger_sense = 1; 4430 codec->no_trigger_sense = 1;
4431 codec->no_sticky_stream = 1;
4425 4432
4426 return 0; 4433 return 0;
4427} 4434}
@@ -4761,6 +4768,7 @@ static int patch_ad1882(struct hda_codec *codec)
4761 } 4768 }
4762 4769
4763 codec->no_trigger_sense = 1; 4770 codec->no_trigger_sense = 1;
4771 codec->no_sticky_stream = 1;
4764 4772
4765 return 0; 4773 return 0;
4766} 4774}
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
deleted file mode 100644
index fb684f00156b..000000000000
--- a/sound/pci/hda/patch_atihdmi.c
+++ /dev/null
@@ -1,224 +0,0 @@
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * HD audio interface patch for ATI HDMI codecs
5 *
6 * Copyright (c) 2006 ATI Technologies Inc.
7 *
8 *
9 * This driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/slab.h>
27#include <sound/core.h>
28#include "hda_codec.h"
29#include "hda_local.h"
30
31struct atihdmi_spec {
32 struct hda_multi_out multiout;
33
34 struct hda_pcm pcm_rec;
35};
36
37#define CVT_NID 0x02 /* audio converter */
38#define PIN_NID 0x03 /* HDMI output pin */
39
40static struct hda_verb atihdmi_basic_init[] = {
41 /* enable digital output on pin widget */
42 { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
43 {} /* terminator */
44};
45
46/*
47 * Controls
48 */
49static int atihdmi_build_controls(struct hda_codec *codec)
50{
51 struct atihdmi_spec *spec = codec->spec;
52 int err;
53
54 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
55 if (err < 0)
56 return err;
57
58 return 0;
59}
60
61static int atihdmi_init(struct hda_codec *codec)
62{
63 snd_hda_sequence_write(codec, atihdmi_basic_init);
64 /* SI codec requires to unmute the pin */
65 if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP)
66 snd_hda_codec_write(codec, PIN_NID, 0,
67 AC_VERB_SET_AMP_GAIN_MUTE,
68 AMP_OUT_UNMUTE);
69 return 0;
70}
71
72/*
73 * Digital out
74 */
75static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
76 struct hda_codec *codec,
77 struct snd_pcm_substream *substream)
78{
79 struct atihdmi_spec *spec = codec->spec;
80 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
81}
82
83static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
84 struct hda_codec *codec,
85 struct snd_pcm_substream *substream)
86{
87 struct atihdmi_spec *spec = codec->spec;
88 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
89}
90
91static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
92 struct hda_codec *codec,
93 unsigned int stream_tag,
94 unsigned int format,
95 struct snd_pcm_substream *substream)
96{
97 struct atihdmi_spec *spec = codec->spec;
98 int chans = substream->runtime->channels;
99 int i, err;
100
101 err = snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
102 format, substream);
103 if (err < 0)
104 return err;
105 snd_hda_codec_write(codec, CVT_NID, 0, AC_VERB_SET_CVT_CHAN_COUNT,
106 chans - 1);
107 /* FIXME: XXX */
108 for (i = 0; i < chans; i++) {
109 snd_hda_codec_write(codec, CVT_NID, 0,
110 AC_VERB_SET_HDMI_CHAN_SLOT,
111 (i << 4) | i);
112 }
113 return 0;
114}
115
116static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
117 .substreams = 1,
118 .channels_min = 2,
119 .channels_max = 2,
120 .nid = CVT_NID, /* NID to query formats and rates and setup streams */
121 .ops = {
122 .open = atihdmi_dig_playback_pcm_open,
123 .close = atihdmi_dig_playback_pcm_close,
124 .prepare = atihdmi_dig_playback_pcm_prepare
125 },
126};
127
128static int atihdmi_build_pcms(struct hda_codec *codec)
129{
130 struct atihdmi_spec *spec = codec->spec;
131 struct hda_pcm *info = &spec->pcm_rec;
132 unsigned int chans;
133
134 codec->num_pcms = 1;
135 codec->pcm_info = info;
136
137 info->name = "ATI HDMI";
138 info->pcm_type = HDA_PCM_TYPE_HDMI;
139 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback;
140
141 /* FIXME: we must check ELD and change the PCM parameters dynamically
142 */
143 chans = get_wcaps(codec, CVT_NID);
144 chans = get_wcaps_channels(chans);
145 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
146
147 return 0;
148}
149
150static void atihdmi_free(struct hda_codec *codec)
151{
152 kfree(codec->spec);
153}
154
155static struct hda_codec_ops atihdmi_patch_ops = {
156 .build_controls = atihdmi_build_controls,
157 .build_pcms = atihdmi_build_pcms,
158 .init = atihdmi_init,
159 .free = atihdmi_free,
160};
161
162static int patch_atihdmi(struct hda_codec *codec)
163{
164 struct atihdmi_spec *spec;
165
166 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
167 if (spec == NULL)
168 return -ENOMEM;
169
170 codec->spec = spec;
171
172 spec->multiout.num_dacs = 0; /* no analog */
173 spec->multiout.max_channels = 2;
174 /* NID for copying analog to digital,
175 * seems to be unused in pure-digital
176 * case.
177 */
178 spec->multiout.dig_out_nid = CVT_NID;
179
180 codec->patch_ops = atihdmi_patch_ops;
181
182 return 0;
183}
184
185/*
186 * patch entries
187 */
188static struct hda_codec_preset snd_hda_preset_atihdmi[] = {
189 { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi },
190 { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi },
191 { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi },
192 { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi },
193 { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi },
194 { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi },
195 {} /* terminator */
196};
197
198MODULE_ALIAS("snd-hda-codec-id:1002793c");
199MODULE_ALIAS("snd-hda-codec-id:10027919");
200MODULE_ALIAS("snd-hda-codec-id:1002791a");
201MODULE_ALIAS("snd-hda-codec-id:1002aa01");
202MODULE_ALIAS("snd-hda-codec-id:10951390");
203MODULE_ALIAS("snd-hda-codec-id:17e80047");
204
205MODULE_LICENSE("GPL");
206MODULE_DESCRIPTION("ATI HDMI HD-audio codec");
207
208static struct hda_codec_preset_list atihdmi_list = {
209 .preset = snd_hda_preset_atihdmi,
210 .owner = THIS_MODULE,
211};
212
213static int __init patch_atihdmi_init(void)
214{
215 return snd_hda_add_codec_preset(&atihdmi_list);
216}
217
218static void __exit patch_atihdmi_exit(void)
219{
220 snd_hda_delete_codec_preset(&atihdmi_list);
221}
222
223module_init(patch_atihdmi_init)
224module_exit(patch_atihdmi_exit)
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
index af478019088e..46c8bf48c31f 100644
--- a/sound/pci/hda/patch_ca0110.c
+++ b/sound/pci/hda/patch_ca0110.c
@@ -468,13 +468,13 @@ static void parse_input(struct hda_codec *codec)
468 spec->dig_in = nid; 468 spec->dig_in = nid;
469 continue; 469 continue;
470 } 470 }
471 for (j = 0; j < AUTO_PIN_LAST; j++) 471 for (j = 0; j < cfg->num_inputs; j++)
472 if (cfg->input_pins[j] == pin) 472 if (cfg->inputs[j].pin == pin)
473 break; 473 break;
474 if (j >= AUTO_PIN_LAST) 474 if (j >= cfg->num_inputs)
475 continue; 475 continue;
476 spec->input_pins[n] = pin; 476 spec->input_pins[n] = pin;
477 spec->input_labels[n] = auto_pin_cfg_labels[j]; 477 spec->input_labels[n] = hda_get_input_pin_label(codec, pin, 1);
478 spec->adcs[n] = nid; 478 spec->adcs[n] = nid;
479 n++; 479 n++;
480 } 480 }
@@ -489,7 +489,7 @@ static void parse_digital(struct hda_codec *codec)
489 if (cfg->dig_outs && 489 if (cfg->dig_outs &&
490 snd_hda_get_connections(codec, cfg->dig_out_pins[0], 490 snd_hda_get_connections(codec, cfg->dig_out_pins[0],
491 &spec->dig_out, 1) == 1) 491 &spec->dig_out, 1) == 1)
492 spec->multiout.dig_out_nid = cfg->dig_out_pins[0]; 492 spec->multiout.dig_out_nid = spec->dig_out;
493} 493}
494 494
495static int ca0110_parse_auto_config(struct hda_codec *codec) 495static int ca0110_parse_auto_config(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 488fd9ade1ba..460fb2ef7e39 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -65,6 +65,7 @@ struct cs_spec {
65 65
66/* available models */ 66/* available models */
67enum { 67enum {
68 CS420X_MBP53,
68 CS420X_MBP55, 69 CS420X_MBP55,
69 CS420X_IMAC27, 70 CS420X_IMAC27,
70 CS420X_AUTO, 71 CS420X_AUTO,
@@ -329,12 +330,12 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx)
329{ 330{
330 struct cs_spec *spec = codec->spec; 331 struct cs_spec *spec = codec->spec;
331 struct auto_pin_cfg *cfg = &spec->autocfg; 332 struct auto_pin_cfg *cfg = &spec->autocfg;
332 hda_nid_t pin = cfg->input_pins[idx]; 333 hda_nid_t pin = cfg->inputs[idx].pin;
333 unsigned int val = snd_hda_query_pin_caps(codec, pin); 334 unsigned int val = snd_hda_query_pin_caps(codec, pin);
334 if (!(val & AC_PINCAP_PRES_DETECT)) 335 if (!(val & AC_PINCAP_PRES_DETECT))
335 return 0; 336 return 0;
336 val = snd_hda_codec_get_pincfg(codec, pin); 337 val = snd_hda_codec_get_pincfg(codec, pin);
337 return (get_defcfg_connect(val) == AC_JACK_PORT_COMPLEX); 338 return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT);
338} 339}
339 340
340static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, 341static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin,
@@ -424,10 +425,8 @@ static int parse_input(struct hda_codec *codec)
424 struct auto_pin_cfg *cfg = &spec->autocfg; 425 struct auto_pin_cfg *cfg = &spec->autocfg;
425 int i; 426 int i;
426 427
427 for (i = 0; i < AUTO_PIN_LAST; i++) { 428 for (i = 0; i < cfg->num_inputs; i++) {
428 hda_nid_t pin = cfg->input_pins[i]; 429 hda_nid_t pin = cfg->inputs[i].pin;
429 if (!pin)
430 continue;
431 spec->input_idx[spec->num_inputs] = i; 430 spec->input_idx[spec->num_inputs] = i;
432 spec->capsrc_idx[i] = spec->num_inputs++; 431 spec->capsrc_idx[i] = spec->num_inputs++;
433 spec->cur_input = i; 432 spec->cur_input = i;
@@ -438,16 +437,17 @@ static int parse_input(struct hda_codec *codec)
438 437
439 /* check whether the automatic mic switch is available */ 438 /* check whether the automatic mic switch is available */
440 if (spec->num_inputs == 2 && 439 if (spec->num_inputs == 2 &&
441 spec->adc_nid[AUTO_PIN_MIC] && spec->adc_nid[AUTO_PIN_FRONT_MIC]) { 440 cfg->inputs[0].type == AUTO_PIN_MIC &&
442 if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_FRONT_MIC])) { 441 cfg->inputs[1].type == AUTO_PIN_MIC) {
443 if (!is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { 442 if (is_ext_mic(codec, cfg->inputs[0].pin)) {
443 if (!is_ext_mic(codec, cfg->inputs[1].pin)) {
444 spec->mic_detect = 1; 444 spec->mic_detect = 1;
445 spec->automic_idx = AUTO_PIN_FRONT_MIC; 445 spec->automic_idx = 0;
446 } 446 }
447 } else { 447 } else {
448 if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { 448 if (is_ext_mic(codec, cfg->inputs[1].pin)) {
449 spec->mic_detect = 1; 449 spec->mic_detect = 1;
450 spec->automic_idx = AUTO_PIN_MIC; 450 spec->automic_idx = 1;
451 } 451 }
452 } 452 }
453 } 453 }
@@ -674,6 +674,7 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
674{ 674{
675 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 675 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
676 struct cs_spec *spec = codec->spec; 676 struct cs_spec *spec = codec->spec;
677 struct auto_pin_cfg *cfg = &spec->autocfg;
677 unsigned int idx; 678 unsigned int idx;
678 679
679 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 680 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -682,7 +683,8 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
682 if (uinfo->value.enumerated.item >= spec->num_inputs) 683 if (uinfo->value.enumerated.item >= spec->num_inputs)
683 uinfo->value.enumerated.item = spec->num_inputs - 1; 684 uinfo->value.enumerated.item = spec->num_inputs - 1;
684 idx = spec->input_idx[uinfo->value.enumerated.item]; 685 idx = spec->input_idx[uinfo->value.enumerated.item];
685 strcpy(uinfo->value.enumerated.name, auto_pin_cfg_labels[idx]); 686 strcpy(uinfo->value.enumerated.name,
687 hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1));
686 return 0; 688 return 0;
687} 689}
688 690
@@ -740,6 +742,27 @@ static struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec,
740 return bind; 742 return bind;
741} 743}
742 744
745/* add a (input-boost) volume control to the given input pin */
746static int add_input_volume_control(struct hda_codec *codec,
747 struct auto_pin_cfg *cfg,
748 int item)
749{
750 hda_nid_t pin = cfg->inputs[item].pin;
751 u32 caps;
752 const char *label;
753 struct snd_kcontrol *kctl;
754
755 if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP))
756 return 0;
757 caps = query_amp_caps(codec, pin, HDA_INPUT);
758 caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
759 if (caps <= 1)
760 return 0;
761 label = hda_get_autocfg_input_label(codec, cfg, item);
762 return add_volume(codec, label, 0,
763 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl);
764}
765
743static int build_input(struct hda_codec *codec) 766static int build_input(struct hda_codec *codec)
744{ 767{
745 struct cs_spec *spec = codec->spec; 768 struct cs_spec *spec = codec->spec;
@@ -779,6 +802,12 @@ static int build_input(struct hda_codec *codec)
779 return err; 802 return err;
780 } 803 }
781 804
805 for (i = 0; i < spec->num_inputs; i++) {
806 err = add_input_volume_control(codec, &spec->autocfg, i);
807 if (err < 0)
808 return err;
809 }
810
782 return 0; 811 return 0;
783} 812}
784 813
@@ -838,7 +867,8 @@ static void cs_automute(struct hda_codec *codec)
838 AC_VERB_SET_PIN_WIDGET_CONTROL, 867 AC_VERB_SET_PIN_WIDGET_CONTROL,
839 hp_present ? 0 : PIN_OUT); 868 hp_present ? 0 : PIN_OUT);
840 } 869 }
841 if (spec->board_config == CS420X_MBP55 || 870 if (spec->board_config == CS420X_MBP53 ||
871 spec->board_config == CS420X_MBP55 ||
842 spec->board_config == CS420X_IMAC27) { 872 spec->board_config == CS420X_IMAC27) {
843 unsigned int gpio = hp_present ? 0x02 : 0x08; 873 unsigned int gpio = hp_present ? 0x02 : 0x08;
844 snd_hda_codec_write(codec, 0x01, 0, 874 snd_hda_codec_write(codec, 0x01, 0,
@@ -853,15 +883,12 @@ static void cs_automic(struct hda_codec *codec)
853 hda_nid_t nid; 883 hda_nid_t nid;
854 unsigned int present; 884 unsigned int present;
855 885
856 nid = cfg->input_pins[spec->automic_idx]; 886 nid = cfg->inputs[spec->automic_idx].pin;
857 present = snd_hda_jack_detect(codec, nid); 887 present = snd_hda_jack_detect(codec, nid);
858 if (present) 888 if (present)
859 change_cur_input(codec, spec->automic_idx, 0); 889 change_cur_input(codec, spec->automic_idx, 0);
860 else { 890 else
861 unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? 891 change_cur_input(codec, !spec->automic_idx, 0);
862 AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC;
863 change_cur_input(codec, imic, 0);
864 }
865} 892}
866 893
867/* 894/*
@@ -918,14 +945,14 @@ static void init_input(struct hda_codec *codec)
918 unsigned int coef; 945 unsigned int coef;
919 int i; 946 int i;
920 947
921 for (i = 0; i < AUTO_PIN_LAST; i++) { 948 for (i = 0; i < cfg->num_inputs; i++) {
922 unsigned int ctl; 949 unsigned int ctl;
923 hda_nid_t pin = cfg->input_pins[i]; 950 hda_nid_t pin = cfg->inputs[i].pin;
924 if (!pin || !spec->adc_nid[i]) 951 if (!spec->adc_nid[i])
925 continue; 952 continue;
926 /* set appropriate pin control and mute first */ 953 /* set appropriate pin control and mute first */
927 ctl = PIN_IN; 954 ctl = PIN_IN;
928 if (i <= AUTO_PIN_FRONT_MIC) { 955 if (cfg->inputs[i].type == AUTO_PIN_MIC) {
929 unsigned int caps = snd_hda_query_pin_caps(codec, pin); 956 unsigned int caps = snd_hda_query_pin_caps(codec, pin);
930 caps >>= AC_PINCAP_VREF_SHIFT; 957 caps >>= AC_PINCAP_VREF_SHIFT;
931 if (caps & AC_PINCAP_VREF_80) 958 if (caps & AC_PINCAP_VREF_80)
@@ -1130,6 +1157,7 @@ static int cs_parse_auto_config(struct hda_codec *codec)
1130} 1157}
1131 1158
1132static const char *cs420x_models[CS420X_MODELS] = { 1159static const char *cs420x_models[CS420X_MODELS] = {
1160 [CS420X_MBP53] = "mbp53",
1133 [CS420X_MBP55] = "mbp55", 1161 [CS420X_MBP55] = "mbp55",
1134 [CS420X_IMAC27] = "imac27", 1162 [CS420X_IMAC27] = "imac27",
1135 [CS420X_AUTO] = "auto", 1163 [CS420X_AUTO] = "auto",
@@ -1137,7 +1165,9 @@ static const char *cs420x_models[CS420X_MODELS] = {
1137 1165
1138 1166
1139static struct snd_pci_quirk cs420x_cfg_tbl[] = { 1167static struct snd_pci_quirk cs420x_cfg_tbl[] = {
1168 SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53),
1140 SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), 1169 SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
1170 SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
1141 SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), 1171 SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
1142 {} /* terminator */ 1172 {} /* terminator */
1143}; 1173};
@@ -1147,6 +1177,20 @@ struct cs_pincfg {
1147 u32 val; 1177 u32 val;
1148}; 1178};
1149 1179
1180static struct cs_pincfg mbp53_pincfgs[] = {
1181 { 0x09, 0x012b4050 },
1182 { 0x0a, 0x90100141 },
1183 { 0x0b, 0x90100140 },
1184 { 0x0c, 0x018b3020 },
1185 { 0x0d, 0x90a00110 },
1186 { 0x0e, 0x400000f0 },
1187 { 0x0f, 0x01cbe030 },
1188 { 0x10, 0x014be060 },
1189 { 0x12, 0x400000f0 },
1190 { 0x15, 0x400000f0 },
1191 {} /* terminator */
1192};
1193
1150static struct cs_pincfg mbp55_pincfgs[] = { 1194static struct cs_pincfg mbp55_pincfgs[] = {
1151 { 0x09, 0x012b4030 }, 1195 { 0x09, 0x012b4030 },
1152 { 0x0a, 0x90100121 }, 1196 { 0x0a, 0x90100121 },
@@ -1176,6 +1220,7 @@ static struct cs_pincfg imac27_pincfgs[] = {
1176}; 1220};
1177 1221
1178static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { 1222static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = {
1223 [CS420X_MBP53] = mbp53_pincfgs,
1179 [CS420X_MBP55] = mbp55_pincfgs, 1224 [CS420X_MBP55] = mbp55_pincfgs,
1180 [CS420X_IMAC27] = imac27_pincfgs, 1225 [CS420X_IMAC27] = imac27_pincfgs,
1181}; 1226};
@@ -1208,6 +1253,7 @@ static int patch_cs420x(struct hda_codec *codec)
1208 1253
1209 switch (spec->board_config) { 1254 switch (spec->board_config) {
1210 case CS420X_IMAC27: 1255 case CS420X_IMAC27:
1256 case CS420X_MBP53:
1211 case CS420X_MBP55: 1257 case CS420X_MBP55:
1212 /* GPIO1 = headphones */ 1258 /* GPIO1 = headphones */
1213 /* GPIO3 = speakers */ 1259 /* GPIO3 = speakers */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 972e7c453b3d..6361f752b5f3 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -57,6 +57,12 @@ struct conexant_jack {
57 57
58}; 58};
59 59
60struct pin_dac_pair {
61 hda_nid_t pin;
62 hda_nid_t dac;
63 int type;
64};
65
60struct conexant_spec { 66struct conexant_spec {
61 67
62 struct snd_kcontrol_new *mixers[5]; 68 struct snd_kcontrol_new *mixers[5];
@@ -77,6 +83,7 @@ struct conexant_spec {
77 unsigned int cur_eapd; 83 unsigned int cur_eapd;
78 unsigned int hp_present; 84 unsigned int hp_present;
79 unsigned int auto_mic; 85 unsigned int auto_mic;
86 int auto_mic_ext; /* autocfg.inputs[] index for ext mic */
80 unsigned int need_dac_fix; 87 unsigned int need_dac_fix;
81 88
82 /* capture */ 89 /* capture */
@@ -110,9 +117,12 @@ struct conexant_spec {
110 struct auto_pin_cfg autocfg; 117 struct auto_pin_cfg autocfg;
111 struct hda_input_mux private_imux; 118 struct hda_input_mux private_imux;
112 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; 119 hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
120 struct pin_dac_pair dac_info[8];
121 int dac_info_filled;
113 122
114 unsigned int dell_automute;
115 unsigned int port_d_mode; 123 unsigned int port_d_mode;
124 unsigned int auto_mute:1; /* used in auto-parser */
125 unsigned int dell_automute:1;
116 unsigned int dell_vostro:1; 126 unsigned int dell_vostro:1;
117 unsigned int ideapad:1; 127 unsigned int ideapad:1;
118 unsigned int thinkpad:1; 128 unsigned int thinkpad:1;
@@ -3065,7 +3075,7 @@ enum {
3065 CXT5066_LAPTOP, /* Laptops w/ EAPD support */ 3075 CXT5066_LAPTOP, /* Laptops w/ EAPD support */
3066 CXT5066_DELL_LAPTOP, /* Dell Laptop */ 3076 CXT5066_DELL_LAPTOP, /* Dell Laptop */
3067 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ 3077 CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */
3068 CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ 3078 CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */
3069 CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ 3079 CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */
3070 CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ 3080 CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */
3071 CXT5066_HP_LAPTOP, /* HP Laptop */ 3081 CXT5066_HP_LAPTOP, /* HP Laptop */
@@ -3076,25 +3086,26 @@ static const char *cxt5066_models[CXT5066_MODELS] = {
3076 [CXT5066_LAPTOP] = "laptop", 3086 [CXT5066_LAPTOP] = "laptop",
3077 [CXT5066_DELL_LAPTOP] = "dell-laptop", 3087 [CXT5066_DELL_LAPTOP] = "dell-laptop",
3078 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", 3088 [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5",
3079 [CXT5066_DELL_VOSTO] = "dell-vostro", 3089 [CXT5066_DELL_VOSTRO] = "dell-vostro",
3080 [CXT5066_IDEAPAD] = "ideapad", 3090 [CXT5066_IDEAPAD] = "ideapad",
3081 [CXT5066_THINKPAD] = "thinkpad", 3091 [CXT5066_THINKPAD] = "thinkpad",
3082 [CXT5066_HP_LAPTOP] = "hp-laptop", 3092 [CXT5066_HP_LAPTOP] = "hp-laptop",
3083}; 3093};
3084 3094
3085static struct snd_pci_quirk cxt5066_cfg_tbl[] = { 3095static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
3086 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", 3096 SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
3087 CXT5066_LAPTOP), 3097 SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
3088 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", 3098 SND_PCI_QUIRK(0x1028, 0x02f5, "Dell",
3089 CXT5066_DELL_LAPTOP), 3099 CXT5066_DELL_LAPTOP),
3090 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), 3100 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO),
3091 SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO),
3092 SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO),
3093 SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), 3101 SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
3094 SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), 3102 SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
3095 SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), 3103 SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
3096 SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), 3104 SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
3097 SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), 3105 SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
3106 SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
3107 CXT5066_LAPTOP),
3108 SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
3098 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), 3109 SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
3099 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), 3110 SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD),
3100 SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), 3111 SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD),
@@ -3196,7 +3207,7 @@ static int patch_cxt5066(struct hda_codec *codec)
3196 spec->capture_prepare = cxt5066_olpc_capture_prepare; 3207 spec->capture_prepare = cxt5066_olpc_capture_prepare;
3197 spec->capture_cleanup = cxt5066_olpc_capture_cleanup; 3208 spec->capture_cleanup = cxt5066_olpc_capture_cleanup;
3198 break; 3209 break;
3199 case CXT5066_DELL_VOSTO: 3210 case CXT5066_DELL_VOSTRO:
3200 codec->patch_ops.init = cxt5066_init; 3211 codec->patch_ops.init = cxt5066_init;
3201 codec->patch_ops.unsol_event = cxt5066_vostro_event; 3212 codec->patch_ops.unsol_event = cxt5066_vostro_event;
3202 spec->init_verbs[0] = cxt5066_init_verbs_vostro; 3213 spec->init_verbs[0] = cxt5066_init_verbs_vostro;
@@ -3254,6 +3265,604 @@ static int patch_cxt5066(struct hda_codec *codec)
3254} 3265}
3255 3266
3256/* 3267/*
3268 * Automatic parser for CX20641 & co
3269 */
3270
3271static hda_nid_t cx_auto_adc_nids[] = { 0x14 };
3272
3273/* get the connection index of @nid in the widget @mux */
3274static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
3275 hda_nid_t nid)
3276{
3277 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
3278 int i, nums;
3279
3280 nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
3281 for (i = 0; i < nums; i++)
3282 if (conn[i] == nid)
3283 return i;
3284 return -1;
3285}
3286
3287/* get an unassigned DAC from the given list.
3288 * Return the nid if found and reduce the DAC list, or return zero if
3289 * not found
3290 */
3291static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin,
3292 hda_nid_t *dacs, int *num_dacs)
3293{
3294 int i, nums = *num_dacs;
3295 hda_nid_t ret = 0;
3296
3297 for (i = 0; i < nums; i++) {
3298 if (get_connection_index(codec, pin, dacs[i]) >= 0) {
3299 ret = dacs[i];
3300 break;
3301 }
3302 }
3303 if (!ret)
3304 return 0;
3305 if (--nums > 0)
3306 memmove(dacs, dacs + 1, nums * sizeof(hda_nid_t));
3307 *num_dacs = nums;
3308 return ret;
3309}
3310
3311#define MAX_AUTO_DACS 5
3312
3313/* fill analog DAC list from the widget tree */
3314static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs)
3315{
3316 hda_nid_t nid, end_nid;
3317 int nums = 0;
3318
3319 end_nid = codec->start_nid + codec->num_nodes;
3320 for (nid = codec->start_nid; nid < end_nid; nid++) {
3321 unsigned int wcaps = get_wcaps(codec, nid);
3322 unsigned int type = get_wcaps_type(wcaps);
3323 if (type == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) {
3324 dacs[nums++] = nid;
3325 if (nums >= MAX_AUTO_DACS)
3326 break;
3327 }
3328 }
3329 return nums;
3330}
3331
3332/* fill pin_dac_pair list from the pin and dac list */
3333static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins,
3334 int num_pins, hda_nid_t *dacs, int *rest,
3335 struct pin_dac_pair *filled, int type)
3336{
3337 int i, nums;
3338
3339 nums = 0;
3340 for (i = 0; i < num_pins; i++) {
3341 filled[nums].pin = pins[i];
3342 filled[nums].type = type;
3343 filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest);
3344 nums++;
3345 }
3346 return nums;
3347}
3348
3349/* parse analog output paths */
3350static void cx_auto_parse_output(struct hda_codec *codec)
3351{
3352 struct conexant_spec *spec = codec->spec;
3353 struct auto_pin_cfg *cfg = &spec->autocfg;
3354 hda_nid_t dacs[MAX_AUTO_DACS];
3355 int i, j, nums, rest;
3356
3357 rest = fill_cx_auto_dacs(codec, dacs);
3358 /* parse all analog output pins */
3359 nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs,
3360 dacs, &rest, spec->dac_info,
3361 AUTO_PIN_LINE_OUT);
3362 nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs,
3363 dacs, &rest, spec->dac_info + nums,
3364 AUTO_PIN_HP_OUT);
3365 nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs,
3366 dacs, &rest, spec->dac_info + nums,
3367 AUTO_PIN_SPEAKER_OUT);
3368 spec->dac_info_filled = nums;
3369 /* fill multiout struct */
3370 for (i = 0; i < nums; i++) {
3371 hda_nid_t dac = spec->dac_info[i].dac;
3372 if (!dac)
3373 continue;
3374 switch (spec->dac_info[i].type) {
3375 case AUTO_PIN_LINE_OUT:
3376 spec->private_dac_nids[spec->multiout.num_dacs] = dac;
3377 spec->multiout.num_dacs++;
3378 break;
3379 case AUTO_PIN_HP_OUT:
3380 case AUTO_PIN_SPEAKER_OUT:
3381 if (!spec->multiout.hp_nid) {
3382 spec->multiout.hp_nid = dac;
3383 break;
3384 }
3385 for (j = 0; j < ARRAY_SIZE(spec->multiout.extra_out_nid); j++)
3386 if (!spec->multiout.extra_out_nid[j]) {
3387 spec->multiout.extra_out_nid[j] = dac;
3388 break;
3389 }
3390 break;
3391 }
3392 }
3393 spec->multiout.dac_nids = spec->private_dac_nids;
3394 spec->multiout.max_channels = nums * 2;
3395
3396 if (cfg->hp_outs > 0)
3397 spec->auto_mute = 1;
3398 spec->vmaster_nid = spec->private_dac_nids[0];
3399}
3400
3401/* auto-mute/unmute speaker and line outs according to headphone jack */
3402static void cx_auto_hp_automute(struct hda_codec *codec)
3403{
3404 struct conexant_spec *spec = codec->spec;
3405 struct auto_pin_cfg *cfg = &spec->autocfg;
3406 int i, present;
3407
3408 if (!spec->auto_mute)
3409 return;
3410 present = 0;
3411 for (i = 0; i < cfg->hp_outs; i++) {
3412 if (snd_hda_jack_detect(codec, cfg->hp_pins[i])) {
3413 present = 1;
3414 break;
3415 }
3416 }
3417 for (i = 0; i < cfg->line_outs; i++) {
3418 snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
3419 AC_VERB_SET_PIN_WIDGET_CONTROL,
3420 present ? 0 : PIN_OUT);
3421 }
3422 for (i = 0; i < cfg->speaker_outs; i++) {
3423 snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
3424 AC_VERB_SET_PIN_WIDGET_CONTROL,
3425 present ? 0 : PIN_OUT);
3426 }
3427}
3428
3429/* automatic switch internal and external mic */
3430static void cx_auto_automic(struct hda_codec *codec)
3431{
3432 struct conexant_spec *spec = codec->spec;
3433 struct auto_pin_cfg *cfg = &spec->autocfg;
3434 struct hda_input_mux *imux = &spec->private_imux;
3435 int ext_idx = spec->auto_mic_ext;
3436
3437 if (!spec->auto_mic)
3438 return;
3439 if (snd_hda_jack_detect(codec, cfg->inputs[ext_idx].pin)) {
3440 snd_hda_codec_write(codec, spec->adc_nids[0], 0,
3441 AC_VERB_SET_CONNECT_SEL,
3442 imux->items[ext_idx].index);
3443 } else {
3444 snd_hda_codec_write(codec, spec->adc_nids[0], 0,
3445 AC_VERB_SET_CONNECT_SEL,
3446 imux->items[!ext_idx].index);
3447 }
3448}
3449
3450static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
3451{
3452 int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
3453 switch (res >> 26) {
3454 case CONEXANT_HP_EVENT:
3455 cx_auto_hp_automute(codec);
3456 conexant_report_jack(codec, nid);
3457 break;
3458 case CONEXANT_MIC_EVENT:
3459 cx_auto_automic(codec);
3460 conexant_report_jack(codec, nid);
3461 break;
3462 }
3463}
3464
3465/* return true if it's an internal-mic pin */
3466static int is_int_mic(struct hda_codec *codec, hda_nid_t pin)
3467{
3468 unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
3469 return get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
3470 snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT;
3471}
3472
3473/* return true if it's an external-mic pin */
3474static int is_ext_mic(struct hda_codec *codec, hda_nid_t pin)
3475{
3476 unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
3477 return get_defcfg_device(def_conf) == AC_JACK_MIC_IN &&
3478 snd_hda_get_input_pin_attr(def_conf) >= INPUT_PIN_ATTR_NORMAL &&
3479 (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_PRES_DETECT);
3480}
3481
3482/* check whether the pin config is suitable for auto-mic switching;
3483 * auto-mic is enabled only when one int-mic and one-ext mic exist
3484 */
3485static void cx_auto_check_auto_mic(struct hda_codec *codec)
3486{
3487 struct conexant_spec *spec = codec->spec;
3488 struct auto_pin_cfg *cfg = &spec->autocfg;
3489
3490 if (is_ext_mic(codec, cfg->inputs[0].pin) &&
3491 is_int_mic(codec, cfg->inputs[1].pin)) {
3492 spec->auto_mic = 1;
3493 spec->auto_mic_ext = 1;
3494 return;
3495 }
3496 if (is_int_mic(codec, cfg->inputs[1].pin) &&
3497 is_ext_mic(codec, cfg->inputs[0].pin)) {
3498 spec->auto_mic = 1;
3499 spec->auto_mic_ext = 0;
3500 return;
3501 }
3502}
3503
3504static void cx_auto_parse_input(struct hda_codec *codec)
3505{
3506 struct conexant_spec *spec = codec->spec;
3507 struct auto_pin_cfg *cfg = &spec->autocfg;
3508 struct hda_input_mux *imux;
3509 int i;
3510
3511 imux = &spec->private_imux;
3512 for (i = 0; i < cfg->num_inputs; i++) {
3513 int idx = get_connection_index(codec, spec->adc_nids[0],
3514 cfg->inputs[i].pin);
3515 if (idx >= 0) {
3516 const char *label;
3517 label = hda_get_autocfg_input_label(codec, cfg, i);
3518 snd_hda_add_imux_item(imux, label, idx, NULL);
3519 }
3520 }
3521 if (imux->num_items == 2 && cfg->num_inputs == 2)
3522 cx_auto_check_auto_mic(codec);
3523 if (imux->num_items > 1 && !spec->auto_mic)
3524 spec->input_mux = imux;
3525}
3526
3527/* get digital-input audio widget corresponding to the given pin */
3528static hda_nid_t cx_auto_get_dig_in(struct hda_codec *codec, hda_nid_t pin)
3529{
3530 hda_nid_t nid, end_nid;
3531
3532 end_nid = codec->start_nid + codec->num_nodes;
3533 for (nid = codec->start_nid; nid < end_nid; nid++) {
3534 unsigned int wcaps = get_wcaps(codec, nid);
3535 unsigned int type = get_wcaps_type(wcaps);
3536 if (type == AC_WID_AUD_IN && (wcaps & AC_WCAP_DIGITAL)) {
3537 if (get_connection_index(codec, nid, pin) >= 0)
3538 return nid;
3539 }
3540 }
3541 return 0;
3542}
3543
3544static void cx_auto_parse_digital(struct hda_codec *codec)
3545{
3546 struct conexant_spec *spec = codec->spec;
3547 struct auto_pin_cfg *cfg = &spec->autocfg;
3548 hda_nid_t nid;
3549
3550 if (cfg->dig_outs &&
3551 snd_hda_get_connections(codec, cfg->dig_out_pins[0], &nid, 1) == 1)
3552 spec->multiout.dig_out_nid = nid;
3553 if (cfg->dig_in_pin)
3554 spec->dig_in_nid = cx_auto_get_dig_in(codec, cfg->dig_in_pin);
3555}
3556
3557#ifdef CONFIG_SND_HDA_INPUT_BEEP
3558static void cx_auto_parse_beep(struct hda_codec *codec)
3559{
3560 struct conexant_spec *spec = codec->spec;
3561 hda_nid_t nid, end_nid;
3562
3563 end_nid = codec->start_nid + codec->num_nodes;
3564 for (nid = codec->start_nid; nid < end_nid; nid++)
3565 if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) {
3566 set_beep_amp(spec, nid, 0, HDA_OUTPUT);
3567 break;
3568 }
3569}
3570#else
3571#define cx_auto_parse_beep(codec)
3572#endif
3573
3574static int cx_auto_parse_auto_config(struct hda_codec *codec)
3575{
3576 struct conexant_spec *spec = codec->spec;
3577 int err;
3578
3579 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
3580 if (err < 0)
3581 return err;
3582
3583 cx_auto_parse_output(codec);
3584 cx_auto_parse_input(codec);
3585 cx_auto_parse_digital(codec);
3586 cx_auto_parse_beep(codec);
3587 return 0;
3588}
3589
3590static void cx_auto_turn_on_eapd(struct hda_codec *codec, int num_pins,
3591 hda_nid_t *pins)
3592{
3593 int i;
3594 for (i = 0; i < num_pins; i++) {
3595 if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD)
3596 snd_hda_codec_write(codec, pins[i], 0,
3597 AC_VERB_SET_EAPD_BTLENABLE, 0x02);
3598 }
3599}
3600
3601static void select_connection(struct hda_codec *codec, hda_nid_t pin,
3602 hda_nid_t src)
3603{
3604 int idx = get_connection_index(codec, pin, src);
3605 if (idx >= 0)
3606 snd_hda_codec_write(codec, pin, 0,
3607 AC_VERB_SET_CONNECT_SEL, idx);
3608}
3609
3610static void cx_auto_init_output(struct hda_codec *codec)
3611{
3612 struct conexant_spec *spec = codec->spec;
3613 struct auto_pin_cfg *cfg = &spec->autocfg;
3614 hda_nid_t nid;
3615 int i;
3616
3617 for (i = 0; i < spec->multiout.num_dacs; i++)
3618 snd_hda_codec_write(codec, spec->multiout.dac_nids[i], 0,
3619 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
3620
3621 for (i = 0; i < cfg->hp_outs; i++)
3622 snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
3623 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
3624 if (spec->auto_mute) {
3625 for (i = 0; i < cfg->hp_outs; i++) {
3626 snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
3627 AC_VERB_SET_UNSOLICITED_ENABLE,
3628 AC_USRSP_EN | CONEXANT_HP_EVENT);
3629 }
3630 cx_auto_hp_automute(codec);
3631 } else {
3632 for (i = 0; i < cfg->line_outs; i++)
3633 snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
3634 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
3635 for (i = 0; i < cfg->speaker_outs; i++)
3636 snd_hda_codec_write(codec, cfg->speaker_pins[i], 0,
3637 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
3638 }
3639
3640 for (i = 0; i < spec->dac_info_filled; i++) {
3641 nid = spec->dac_info[i].dac;
3642 if (!nid)
3643 nid = spec->multiout.dac_nids[0];
3644 select_connection(codec, spec->dac_info[i].pin, nid);
3645 }
3646
3647 /* turn on EAPD */
3648 cx_auto_turn_on_eapd(codec, cfg->line_outs, cfg->line_out_pins);
3649 cx_auto_turn_on_eapd(codec, cfg->hp_outs, cfg->hp_pins);
3650 cx_auto_turn_on_eapd(codec, cfg->speaker_outs, cfg->speaker_pins);
3651}
3652
3653static void cx_auto_init_input(struct hda_codec *codec)
3654{
3655 struct conexant_spec *spec = codec->spec;
3656 struct auto_pin_cfg *cfg = &spec->autocfg;
3657 int i;
3658
3659 for (i = 0; i < spec->num_adc_nids; i++)
3660 snd_hda_codec_write(codec, spec->adc_nids[i], 0,
3661 AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0));
3662
3663 for (i = 0; i < cfg->num_inputs; i++) {
3664 unsigned int type;
3665 if (cfg->inputs[i].type == AUTO_PIN_MIC)
3666 type = PIN_VREF80;
3667 else
3668 type = PIN_IN;
3669 snd_hda_codec_write(codec, cfg->inputs[i].pin, 0,
3670 AC_VERB_SET_PIN_WIDGET_CONTROL, type);
3671 }
3672
3673 if (spec->auto_mic) {
3674 int ext_idx = spec->auto_mic_ext;
3675 snd_hda_codec_write(codec, cfg->inputs[ext_idx].pin, 0,
3676 AC_VERB_SET_UNSOLICITED_ENABLE,
3677 AC_USRSP_EN | CONEXANT_MIC_EVENT);
3678 cx_auto_automic(codec);
3679 } else {
3680 for (i = 0; i < spec->num_adc_nids; i++) {
3681 snd_hda_codec_write(codec, spec->adc_nids[i], 0,
3682 AC_VERB_SET_CONNECT_SEL,
3683 spec->private_imux.items[0].index);
3684 }
3685 }
3686}
3687
3688static void cx_auto_init_digital(struct hda_codec *codec)
3689{
3690 struct conexant_spec *spec = codec->spec;
3691 struct auto_pin_cfg *cfg = &spec->autocfg;
3692
3693 if (spec->multiout.dig_out_nid)
3694 snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0,
3695 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
3696 if (spec->dig_in_nid)
3697 snd_hda_codec_write(codec, cfg->dig_in_pin, 0,
3698 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN);
3699}
3700
3701static int cx_auto_init(struct hda_codec *codec)
3702{
3703 /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/
3704 cx_auto_init_output(codec);
3705 cx_auto_init_input(codec);
3706 cx_auto_init_digital(codec);
3707 return 0;
3708}
3709
3710static int cx_auto_add_volume(struct hda_codec *codec, const char *basename,
3711 const char *dir, int cidx,
3712 hda_nid_t nid, int hda_dir)
3713{
3714 static char name[32];
3715 static struct snd_kcontrol_new knew[] = {
3716 HDA_CODEC_VOLUME(name, 0, 0, 0),
3717 HDA_CODEC_MUTE(name, 0, 0, 0),
3718 };
3719 static char *sfx[2] = { "Volume", "Switch" };
3720 int i, err;
3721
3722 for (i = 0; i < 2; i++) {
3723 struct snd_kcontrol *kctl;
3724 knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, hda_dir);
3725 knew[i].subdevice = HDA_SUBDEV_AMP_FLAG;
3726 knew[i].index = cidx;
3727 snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]);
3728 kctl = snd_ctl_new1(&knew[i], codec);
3729 if (!kctl)
3730 return -ENOMEM;
3731 err = snd_hda_ctl_add(codec, nid, kctl);
3732 if (err < 0)
3733 return err;
3734 if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
3735 break;
3736 }
3737 return 0;
3738}
3739
3740#define cx_auto_add_pb_volume(codec, nid, str, idx) \
3741 cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT)
3742
3743static int cx_auto_build_output_controls(struct hda_codec *codec)
3744{
3745 struct conexant_spec *spec = codec->spec;
3746 int i, err;
3747 int num_line = 0, num_hp = 0, num_spk = 0;
3748 static const char *texts[3] = { "Front", "Surround", "CLFE" };
3749
3750 if (spec->dac_info_filled == 1)
3751 return cx_auto_add_pb_volume(codec, spec->dac_info[0].dac,
3752 "Master", 0);
3753 for (i = 0; i < spec->dac_info_filled; i++) {
3754 const char *label;
3755 int idx, type;
3756 if (!spec->dac_info[i].dac)
3757 continue;
3758 type = spec->dac_info[i].type;
3759 if (type == AUTO_PIN_LINE_OUT)
3760 type = spec->autocfg.line_out_type;
3761 switch (type) {
3762 case AUTO_PIN_LINE_OUT:
3763 default:
3764 label = texts[num_line++];
3765 idx = 0;
3766 break;
3767 case AUTO_PIN_HP_OUT:
3768 label = "Headphone";
3769 idx = num_hp++;
3770 break;
3771 case AUTO_PIN_SPEAKER_OUT:
3772 label = "Speaker";
3773 idx = num_spk++;
3774 break;
3775 }
3776 err = cx_auto_add_pb_volume(codec, spec->dac_info[i].dac,
3777 label, idx);
3778 if (err < 0)
3779 return err;
3780 }
3781 return 0;
3782}
3783
3784static int cx_auto_build_input_controls(struct hda_codec *codec)
3785{
3786 struct conexant_spec *spec = codec->spec;
3787 struct auto_pin_cfg *cfg = &spec->autocfg;
3788 static const char *prev_label;
3789 int i, err, cidx;
3790
3791 err = cx_auto_add_volume(codec, "Capture", "", 0, spec->adc_nids[0],
3792 HDA_INPUT);
3793 if (err < 0)
3794 return err;
3795 prev_label = NULL;
3796 cidx = 0;
3797 for (i = 0; i < cfg->num_inputs; i++) {
3798 hda_nid_t nid = cfg->inputs[i].pin;
3799 const char *label;
3800 if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP))
3801 continue;
3802 label = hda_get_autocfg_input_label(codec, cfg, i);
3803 if (label == prev_label)
3804 cidx++;
3805 else
3806 cidx = 0;
3807 prev_label = label;
3808 err = cx_auto_add_volume(codec, label, " Capture", cidx,
3809 nid, HDA_INPUT);
3810 if (err < 0)
3811 return err;
3812 }
3813 return 0;
3814}
3815
3816static int cx_auto_build_controls(struct hda_codec *codec)
3817{
3818 int err;
3819
3820 err = cx_auto_build_output_controls(codec);
3821 if (err < 0)
3822 return err;
3823 err = cx_auto_build_input_controls(codec);
3824 if (err < 0)
3825 return err;
3826 return conexant_build_controls(codec);
3827}
3828
3829static struct hda_codec_ops cx_auto_patch_ops = {
3830 .build_controls = cx_auto_build_controls,
3831 .build_pcms = conexant_build_pcms,
3832 .init = cx_auto_init,
3833 .free = conexant_free,
3834 .unsol_event = cx_auto_unsol_event,
3835#ifdef CONFIG_SND_HDA_POWER_SAVE
3836 .suspend = conexant_suspend,
3837#endif
3838 .reboot_notify = snd_hda_shutup_pins,
3839};
3840
3841static int patch_conexant_auto(struct hda_codec *codec)
3842{
3843 struct conexant_spec *spec;
3844 int err;
3845
3846 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3847 if (!spec)
3848 return -ENOMEM;
3849 codec->spec = spec;
3850 spec->adc_nids = cx_auto_adc_nids;
3851 spec->num_adc_nids = ARRAY_SIZE(cx_auto_adc_nids);
3852 spec->capsrc_nids = spec->adc_nids;
3853 err = cx_auto_parse_auto_config(codec);
3854 if (err < 0) {
3855 kfree(codec->spec);
3856 codec->spec = NULL;
3857 return err;
3858 }
3859 codec->patch_ops = cx_auto_patch_ops;
3860 if (spec->beep_amp)
3861 snd_hda_attach_beep_device(codec, spec->beep_amp);
3862 return 0;
3863}
3864
3865/*
3257 */ 3866 */
3258 3867
3259static struct hda_codec_preset snd_hda_preset_conexant[] = { 3868static struct hda_codec_preset snd_hda_preset_conexant[] = {
@@ -3271,6 +3880,22 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
3271 .patch = patch_cxt5066 }, 3880 .patch = patch_cxt5066 },
3272 { .id = 0x14f15069, .name = "CX20585", 3881 { .id = 0x14f15069, .name = "CX20585",
3273 .patch = patch_cxt5066 }, 3882 .patch = patch_cxt5066 },
3883 { .id = 0x14f15097, .name = "CX20631",
3884 .patch = patch_conexant_auto },
3885 { .id = 0x14f15098, .name = "CX20632",
3886 .patch = patch_conexant_auto },
3887 { .id = 0x14f150a1, .name = "CX20641",
3888 .patch = patch_conexant_auto },
3889 { .id = 0x14f150a2, .name = "CX20642",
3890 .patch = patch_conexant_auto },
3891 { .id = 0x14f150ab, .name = "CX20651",
3892 .patch = patch_conexant_auto },
3893 { .id = 0x14f150ac, .name = "CX20652",
3894 .patch = patch_conexant_auto },
3895 { .id = 0x14f150b8, .name = "CX20664",
3896 .patch = patch_conexant_auto },
3897 { .id = 0x14f150b9, .name = "CX20665",
3898 .patch = patch_conexant_auto },
3274 {} /* terminator */ 3899 {} /* terminator */
3275}; 3900};
3276 3901
@@ -3281,6 +3906,14 @@ MODULE_ALIAS("snd-hda-codec-id:14f15066");
3281MODULE_ALIAS("snd-hda-codec-id:14f15067"); 3906MODULE_ALIAS("snd-hda-codec-id:14f15067");
3282MODULE_ALIAS("snd-hda-codec-id:14f15068"); 3907MODULE_ALIAS("snd-hda-codec-id:14f15068");
3283MODULE_ALIAS("snd-hda-codec-id:14f15069"); 3908MODULE_ALIAS("snd-hda-codec-id:14f15069");
3909MODULE_ALIAS("snd-hda-codec-id:14f15097");
3910MODULE_ALIAS("snd-hda-codec-id:14f15098");
3911MODULE_ALIAS("snd-hda-codec-id:14f150a1");
3912MODULE_ALIAS("snd-hda-codec-id:14f150a2");
3913MODULE_ALIAS("snd-hda-codec-id:14f150ab");
3914MODULE_ALIAS("snd-hda-codec-id:14f150ac");
3915MODULE_ALIAS("snd-hda-codec-id:14f150b8");
3916MODULE_ALIAS("snd-hda-codec-id:14f150b9");
3284 3917
3285MODULE_LICENSE("GPL"); 3918MODULE_LICENSE("GPL");
3286MODULE_DESCRIPTION("Conexant HD-audio codec"); 3919MODULE_DESCRIPTION("Conexant HD-audio codec");
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index afd6022a96a7..d3e49aa5b9ec 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -3,6 +3,9 @@
3 * patch_hdmi.c - routines for HDMI/DisplayPort codecs 3 * patch_hdmi.c - routines for HDMI/DisplayPort codecs
4 * 4 *
5 * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. 5 * Copyright(c) 2008-2010 Intel Corporation. All rights reserved.
6 * Copyright (c) 2006 ATI Technologies Inc.
7 * Copyright (c) 2008 NVIDIA Corp. All rights reserved.
8 * Copyright (c) 2008 Wei Ni <wni@nvidia.com>
6 * 9 *
7 * Authors: 10 * Authors:
8 * Wu Fengguang <wfg@linux.intel.com> 11 * Wu Fengguang <wfg@linux.intel.com>
@@ -25,6 +28,22 @@
25 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 28 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */ 29 */
27 30
31#include <linux/init.h>
32#include <linux/delay.h>
33#include <linux/slab.h>
34#include <sound/core.h>
35#include "hda_codec.h"
36#include "hda_local.h"
37
38/*
39 * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
40 * could support two independent pipes, each of them can be connected to one or
41 * more ports (DVI, HDMI or DisplayPort).
42 *
43 * The HDA correspondence of pipes/ports are converter/pin nodes.
44 */
45#define MAX_HDMI_CVTS 3
46#define MAX_HDMI_PINS 3
28 47
29struct hdmi_spec { 48struct hdmi_spec {
30 int num_cvts; 49 int num_cvts;
@@ -49,10 +68,10 @@ struct hdmi_spec {
49 struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; 68 struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS];
50 69
51 /* 70 /*
52 * nvhdmi specific 71 * ati/nvhdmi specific
53 */ 72 */
54 struct hda_multi_out multiout; 73 struct hda_multi_out multiout;
55 unsigned int codec_type; 74 struct hda_pcm_stream *pcm_playback;
56 75
57 /* misc flags */ 76 /* misc flags */
58 /* PD bit indicates only the update, not the current state */ 77 /* PD bit indicates only the update, not the current state */
@@ -65,13 +84,25 @@ struct hdmi_audio_infoframe {
65 u8 ver; /* 0x01 */ 84 u8 ver; /* 0x01 */
66 u8 len; /* 0x0a */ 85 u8 len; /* 0x0a */
67 86
68 u8 checksum; /* PB0 */ 87 u8 checksum;
88
69 u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ 89 u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
70 u8 SS01_SF24; 90 u8 SS01_SF24;
71 u8 CXT04; 91 u8 CXT04;
72 u8 CA; 92 u8 CA;
73 u8 LFEPBL01_LSV36_DM_INH7; 93 u8 LFEPBL01_LSV36_DM_INH7;
74 u8 reserved[5]; /* PB6 - PB10 */ 94};
95
96struct dp_audio_infoframe {
97 u8 type; /* 0x84 */
98 u8 len; /* 0x1b */
99 u8 ver; /* 0x11 << 2 */
100
101 u8 CC02_CT47; /* match with HDMI infoframe from this on */
102 u8 SS01_SF24;
103 u8 CXT04;
104 u8 CA;
105 u8 LFEPBL01_LSV36_DM_INH7;
75}; 106};
76 107
77/* 108/*
@@ -162,7 +193,7 @@ static int hdmi_channel_mapping[0x32][8] = {
162 /* 4ch */ 193 /* 4ch */
163 [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, 194 [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
164 /* surround41 */ 195 /* surround41 */
165 [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, 196 [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 },
166 /* surround50 */ 197 /* surround50 */
167 [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, 198 [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
168 /* surround51 */ 199 /* surround51 */
@@ -175,7 +206,7 @@ static int hdmi_channel_mapping[0x32][8] = {
175 * This is an ordered list! 206 * This is an ordered list!
176 * 207 *
177 * The preceding ones have better chances to be selected by 208 * The preceding ones have better chances to be selected by
178 * hdmi_setup_channel_allocation(). 209 * hdmi_channel_allocation().
179 */ 210 */
180static struct cea_channel_speaker_allocation channel_allocations[] = { 211static struct cea_channel_speaker_allocation channel_allocations[] = {
181/* channel: 7 6 5 4 3 2 1 0 */ 212/* channel: 7 6 5 4 3 2 1 0 */
@@ -352,14 +383,14 @@ static void init_channel_allocations(void)
352 * 383 *
353 * TODO: it could select the wrong CA from multiple candidates. 384 * TODO: it could select the wrong CA from multiple candidates.
354*/ 385*/
355static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, 386static int hdmi_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
356 struct hdmi_audio_infoframe *ai) 387 int channels)
357{ 388{
358 struct hdmi_spec *spec = codec->spec; 389 struct hdmi_spec *spec = codec->spec;
359 struct hdmi_eld *eld; 390 struct hdmi_eld *eld;
360 int i; 391 int i;
392 int ca = 0;
361 int spk_mask = 0; 393 int spk_mask = 0;
362 int channels = 1 + (ai->CC02_CT47 & 0x7);
363 char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; 394 char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
364 395
365 /* 396 /*
@@ -397,16 +428,16 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
397 if (channels == channel_allocations[i].channels && 428 if (channels == channel_allocations[i].channels &&
398 (spk_mask & channel_allocations[i].spk_mask) == 429 (spk_mask & channel_allocations[i].spk_mask) ==
399 channel_allocations[i].spk_mask) { 430 channel_allocations[i].spk_mask) {
400 ai->CA = channel_allocations[i].ca_index; 431 ca = channel_allocations[i].ca_index;
401 break; 432 break;
402 } 433 }
403 } 434 }
404 435
405 snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); 436 snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
406 snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", 437 snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
407 ai->CA, channels, buf); 438 ca, channels, buf);
408 439
409 return ai->CA; 440 return ca;
410} 441}
411 442
412static void hdmi_debug_channel_mapping(struct hda_codec *codec, 443static void hdmi_debug_channel_mapping(struct hda_codec *codec,
@@ -428,10 +459,9 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec,
428 459
429static void hdmi_setup_channel_mapping(struct hda_codec *codec, 460static void hdmi_setup_channel_mapping(struct hda_codec *codec,
430 hda_nid_t pin_nid, 461 hda_nid_t pin_nid,
431 struct hdmi_audio_infoframe *ai) 462 int ca)
432{ 463{
433 int i; 464 int i;
434 int ca = ai->CA;
435 int err; 465 int err;
436 466
437 if (hdmi_channel_mapping[ca][1] == 0) { 467 if (hdmi_channel_mapping[ca][1] == 0) {
@@ -528,41 +558,37 @@ static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
528#endif 558#endif
529} 559}
530 560
531static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) 561static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai)
532{ 562{
533 u8 *bytes = (u8 *)ai; 563 u8 *bytes = (u8 *)hdmi_ai;
534 u8 sum = 0; 564 u8 sum = 0;
535 int i; 565 int i;
536 566
537 ai->checksum = 0; 567 hdmi_ai->checksum = 0;
538 568
539 for (i = 0; i < sizeof(*ai); i++) 569 for (i = 0; i < sizeof(*hdmi_ai); i++)
540 sum += bytes[i]; 570 sum += bytes[i];
541 571
542 ai->checksum = -sum; 572 hdmi_ai->checksum = -sum;
543} 573}
544 574
545static void hdmi_fill_audio_infoframe(struct hda_codec *codec, 575static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
546 hda_nid_t pin_nid, 576 hda_nid_t pin_nid,
547 struct hdmi_audio_infoframe *ai) 577 u8 *dip, int size)
548{ 578{
549 u8 *bytes = (u8 *)ai;
550 int i; 579 int i;
551 580
552 hdmi_debug_dip_size(codec, pin_nid); 581 hdmi_debug_dip_size(codec, pin_nid);
553 hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ 582 hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
554 583
555 hdmi_checksum_audio_infoframe(ai);
556
557 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); 584 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
558 for (i = 0; i < sizeof(*ai); i++) 585 for (i = 0; i < size; i++)
559 hdmi_write_dip_byte(codec, pin_nid, bytes[i]); 586 hdmi_write_dip_byte(codec, pin_nid, dip[i]);
560} 587}
561 588
562static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, 589static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
563 struct hdmi_audio_infoframe *ai) 590 u8 *dip, int size)
564{ 591{
565 u8 *bytes = (u8 *)ai;
566 u8 val; 592 u8 val;
567 int i; 593 int i;
568 594
@@ -571,10 +597,10 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
571 return false; 597 return false;
572 598
573 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); 599 hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
574 for (i = 0; i < sizeof(*ai); i++) { 600 for (i = 0; i < size; i++) {
575 val = snd_hda_codec_read(codec, pin_nid, 0, 601 val = snd_hda_codec_read(codec, pin_nid, 0,
576 AC_VERB_GET_HDMI_DIP_DATA, 0); 602 AC_VERB_GET_HDMI_DIP_DATA, 0);
577 if (val != bytes[i]) 603 if (val != dip[i])
578 return false; 604 return false;
579 } 605 }
580 606
@@ -586,15 +612,13 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
586{ 612{
587 struct hdmi_spec *spec = codec->spec; 613 struct hdmi_spec *spec = codec->spec;
588 hda_nid_t pin_nid; 614 hda_nid_t pin_nid;
615 int channels = substream->runtime->channels;
616 int ca;
589 int i; 617 int i;
590 struct hdmi_audio_infoframe ai = { 618 u8 ai[max(sizeof(struct hdmi_audio_infoframe),
591 .type = 0x84, 619 sizeof(struct dp_audio_infoframe))];
592 .ver = 0x01,
593 .len = 0x0a,
594 .CC02_CT47 = substream->runtime->channels - 1,
595 };
596 620
597 hdmi_setup_channel_allocation(codec, nid, &ai); 621 ca = hdmi_channel_allocation(codec, nid, channels);
598 622
599 for (i = 0; i < spec->num_pins; i++) { 623 for (i = 0; i < spec->num_pins; i++) {
600 if (spec->pin_cvt[i] != nid) 624 if (spec->pin_cvt[i] != nid)
@@ -603,14 +627,45 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
603 continue; 627 continue;
604 628
605 pin_nid = spec->pin[i]; 629 pin_nid = spec->pin[i];
606 if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { 630
631 memset(ai, 0, sizeof(ai));
632 if (spec->sink_eld[i].conn_type == 0) { /* HDMI */
633 struct hdmi_audio_infoframe *hdmi_ai;
634
635 hdmi_ai = (struct hdmi_audio_infoframe *)ai;
636 hdmi_ai->type = 0x84;
637 hdmi_ai->ver = 0x01;
638 hdmi_ai->len = 0x0a;
639 hdmi_ai->CC02_CT47 = channels - 1;
640 hdmi_checksum_audio_infoframe(hdmi_ai);
641 } else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */
642 struct dp_audio_infoframe *dp_ai;
643
644 dp_ai = (struct dp_audio_infoframe *)ai;
645 dp_ai->type = 0x84;
646 dp_ai->len = 0x1b;
647 dp_ai->ver = 0x11 << 2;
648 dp_ai->CC02_CT47 = channels - 1;
649 } else {
650 snd_printd("HDMI: unknown connection type at pin %d\n",
651 pin_nid);
652 continue;
653 }
654
655 /*
656 * sizeof(ai) is used instead of sizeof(*hdmi_ai) or
657 * sizeof(*dp_ai) to avoid partial match/update problems when
658 * the user switches between HDMI/DP monitors.
659 */
660 if (!hdmi_infoframe_uptodate(codec, pin_nid, ai, sizeof(ai))) {
607 snd_printdd("hdmi_setup_audio_infoframe: " 661 snd_printdd("hdmi_setup_audio_infoframe: "
608 "cvt=%d pin=%d channels=%d\n", 662 "cvt=%d pin=%d channels=%d\n",
609 nid, pin_nid, 663 nid, pin_nid,
610 substream->runtime->channels); 664 channels);
611 hdmi_setup_channel_mapping(codec, pin_nid, &ai); 665 hdmi_setup_channel_mapping(codec, pin_nid, ca);
612 hdmi_stop_infoframe_trans(codec, pin_nid); 666 hdmi_stop_infoframe_trans(codec, pin_nid);
613 hdmi_fill_audio_infoframe(codec, pin_nid, &ai); 667 hdmi_fill_audio_infoframe(codec, pin_nid,
668 ai, sizeof(ai));
614 hdmi_start_infoframe_trans(codec, pin_nid); 669 hdmi_start_infoframe_trans(codec, pin_nid);
615 } 670 }
616 } 671 }
@@ -791,7 +846,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
791/* 846/*
792 * HDA/HDMI auto parsing 847 * HDA/HDMI auto parsing
793 */ 848 */
794
795static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) 849static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
796{ 850{
797 struct hdmi_spec *spec = codec->spec; 851 struct hdmi_spec *spec = codec->spec;
@@ -922,3 +976,664 @@ static int hdmi_parse_codec(struct hda_codec *codec)
922 return 0; 976 return 0;
923} 977}
924 978
979/*
980 */
981static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = {
982 "HDMI 0",
983 "HDMI 1",
984 "HDMI 2",
985};
986
987/*
988 * HDMI callbacks
989 */
990
991static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
992 struct hda_codec *codec,
993 unsigned int stream_tag,
994 unsigned int format,
995 struct snd_pcm_substream *substream)
996{
997 hdmi_set_channel_count(codec, hinfo->nid,
998 substream->runtime->channels);
999
1000 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
1001
1002 return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
1003}
1004
1005static struct hda_pcm_stream generic_hdmi_pcm_playback = {
1006 .substreams = 1,
1007 .channels_min = 2,
1008 .ops = {
1009 .open = hdmi_pcm_open,
1010 .prepare = generic_hdmi_playback_pcm_prepare,
1011 },
1012};
1013
1014static int generic_hdmi_build_pcms(struct hda_codec *codec)
1015{
1016 struct hdmi_spec *spec = codec->spec;
1017 struct hda_pcm *info = spec->pcm_rec;
1018 int i;
1019
1020 codec->num_pcms = spec->num_cvts;
1021 codec->pcm_info = info;
1022
1023 for (i = 0; i < codec->num_pcms; i++, info++) {
1024 unsigned int chans;
1025 struct hda_pcm_stream *pstr;
1026
1027 chans = get_wcaps(codec, spec->cvt[i]);
1028 chans = get_wcaps_channels(chans);
1029
1030 info->name = generic_hdmi_pcm_names[i];
1031 info->pcm_type = HDA_PCM_TYPE_HDMI;
1032 pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
1033 if (spec->pcm_playback)
1034 *pstr = *spec->pcm_playback;
1035 else
1036 *pstr = generic_hdmi_pcm_playback;
1037 pstr->nid = spec->cvt[i];
1038 if (pstr->channels_max <= 2 && chans && chans <= 16)
1039 pstr->channels_max = chans;
1040 }
1041
1042 return 0;
1043}
1044
1045static int generic_hdmi_build_controls(struct hda_codec *codec)
1046{
1047 struct hdmi_spec *spec = codec->spec;
1048 int err;
1049 int i;
1050
1051 for (i = 0; i < codec->num_pcms; i++) {
1052 err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]);
1053 if (err < 0)
1054 return err;
1055 }
1056
1057 return 0;
1058}
1059
1060static int generic_hdmi_init(struct hda_codec *codec)
1061{
1062 struct hdmi_spec *spec = codec->spec;
1063 int i;
1064
1065 for (i = 0; spec->pin[i]; i++) {
1066 hdmi_enable_output(codec, spec->pin[i]);
1067 snd_hda_codec_write(codec, spec->pin[i], 0,
1068 AC_VERB_SET_UNSOLICITED_ENABLE,
1069 AC_USRSP_EN | spec->pin[i]);
1070 }
1071 return 0;
1072}
1073
1074static void generic_hdmi_free(struct hda_codec *codec)
1075{
1076 struct hdmi_spec *spec = codec->spec;
1077 int i;
1078
1079 for (i = 0; i < spec->num_pins; i++)
1080 snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
1081
1082 kfree(spec);
1083}
1084
1085static struct hda_codec_ops generic_hdmi_patch_ops = {
1086 .init = generic_hdmi_init,
1087 .free = generic_hdmi_free,
1088 .build_pcms = generic_hdmi_build_pcms,
1089 .build_controls = generic_hdmi_build_controls,
1090 .unsol_event = hdmi_unsol_event,
1091};
1092
1093static int patch_generic_hdmi(struct hda_codec *codec)
1094{
1095 struct hdmi_spec *spec;
1096 int i;
1097
1098 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1099 if (spec == NULL)
1100 return -ENOMEM;
1101
1102 codec->spec = spec;
1103 if (hdmi_parse_codec(codec) < 0) {
1104 codec->spec = NULL;
1105 kfree(spec);
1106 return -EINVAL;
1107 }
1108 codec->patch_ops = generic_hdmi_patch_ops;
1109
1110 for (i = 0; i < spec->num_pins; i++)
1111 snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
1112
1113 init_channel_allocations();
1114
1115 return 0;
1116}
1117
1118/*
1119 * Nvidia specific implementations
1120 */
1121
1122#define Nv_VERB_SET_Channel_Allocation 0xF79
1123#define Nv_VERB_SET_Info_Frame_Checksum 0xF7A
1124#define Nv_VERB_SET_Audio_Protection_On 0xF98
1125#define Nv_VERB_SET_Audio_Protection_Off 0xF99
1126
1127#define nvhdmi_master_con_nid_7x 0x04
1128#define nvhdmi_master_pin_nid_7x 0x05
1129
1130static hda_nid_t nvhdmi_con_nids_7x[4] = {
1131 /*front, rear, clfe, rear_surr */
1132 0x6, 0x8, 0xa, 0xc,
1133};
1134
1135static struct hda_verb nvhdmi_basic_init_7x[] = {
1136 /* set audio protect on */
1137 { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
1138 /* enable digital output on pin widget */
1139 { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
1140 { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
1141 { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
1142 { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
1143 { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
1144 {} /* terminator */
1145};
1146
1147#ifdef LIMITED_RATE_FMT_SUPPORT
1148/* support only the safe format and rate */
1149#define SUPPORTED_RATES SNDRV_PCM_RATE_48000
1150#define SUPPORTED_MAXBPS 16
1151#define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE
1152#else
1153/* support all rates and formats */
1154#define SUPPORTED_RATES \
1155 (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
1156 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
1157 SNDRV_PCM_RATE_192000)
1158#define SUPPORTED_MAXBPS 24
1159#define SUPPORTED_FORMATS \
1160 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
1161#endif
1162
1163static int nvhdmi_7x_init(struct hda_codec *codec)
1164{
1165 snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
1166 return 0;
1167}
1168
1169static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo,
1170 struct hda_codec *codec,
1171 struct snd_pcm_substream *substream)
1172{
1173 struct hdmi_spec *spec = codec->spec;
1174 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
1175}
1176
1177static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo,
1178 struct hda_codec *codec,
1179 struct snd_pcm_substream *substream)
1180{
1181 struct hdmi_spec *spec = codec->spec;
1182 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
1183}
1184
1185static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1186 struct hda_codec *codec,
1187 unsigned int stream_tag,
1188 unsigned int format,
1189 struct snd_pcm_substream *substream)
1190{
1191 struct hdmi_spec *spec = codec->spec;
1192 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
1193 stream_tag, format, substream);
1194}
1195
1196static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
1197 struct hda_codec *codec,
1198 struct snd_pcm_substream *substream)
1199{
1200 struct hdmi_spec *spec = codec->spec;
1201 int i;
1202
1203 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
1204 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
1205 for (i = 0; i < 4; i++) {
1206 /* set the stream id */
1207 snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
1208 AC_VERB_SET_CHANNEL_STREAMID, 0);
1209 /* set the stream format */
1210 snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
1211 AC_VERB_SET_STREAM_FORMAT, 0);
1212 }
1213
1214 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
1215}
1216
1217static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
1218 struct hda_codec *codec,
1219 unsigned int stream_tag,
1220 unsigned int format,
1221 struct snd_pcm_substream *substream)
1222{
1223 int chs;
1224 unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
1225 int i;
1226
1227 mutex_lock(&codec->spdif_mutex);
1228
1229 chs = substream->runtime->channels;
1230 chan = chs ? (chs - 1) : 1;
1231
1232 switch (chs) {
1233 default:
1234 case 0:
1235 case 2:
1236 chanmask = 0x00;
1237 break;
1238 case 4:
1239 chanmask = 0x08;
1240 break;
1241 case 6:
1242 chanmask = 0x0b;
1243 break;
1244 case 8:
1245 chanmask = 0x13;
1246 break;
1247 }
1248 dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
1249 dataDCC2 = 0x2;
1250
1251 /* set the Audio InforFrame Channel Allocation */
1252 snd_hda_codec_write(codec, 0x1, 0,
1253 Nv_VERB_SET_Channel_Allocation, chanmask);
1254
1255 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
1256 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
1257 snd_hda_codec_write(codec,
1258 nvhdmi_master_con_nid_7x,
1259 0,
1260 AC_VERB_SET_DIGI_CONVERT_1,
1261 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
1262
1263 /* set the stream id */
1264 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
1265 AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
1266
1267 /* set the stream format */
1268 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
1269 AC_VERB_SET_STREAM_FORMAT, format);
1270
1271 /* turn on again (if needed) */
1272 /* enable and set the channel status audio/data flag */
1273 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
1274 snd_hda_codec_write(codec,
1275 nvhdmi_master_con_nid_7x,
1276 0,
1277 AC_VERB_SET_DIGI_CONVERT_1,
1278 codec->spdif_ctls & 0xff);
1279 snd_hda_codec_write(codec,
1280 nvhdmi_master_con_nid_7x,
1281 0,
1282 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
1283 }
1284
1285 for (i = 0; i < 4; i++) {
1286 if (chs == 2)
1287 channel_id = 0;
1288 else
1289 channel_id = i * 2;
1290
1291 /* turn off SPDIF once;
1292 *otherwise the IEC958 bits won't be updated
1293 */
1294 if (codec->spdif_status_reset &&
1295 (codec->spdif_ctls & AC_DIG1_ENABLE))
1296 snd_hda_codec_write(codec,
1297 nvhdmi_con_nids_7x[i],
1298 0,
1299 AC_VERB_SET_DIGI_CONVERT_1,
1300 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
1301 /* set the stream id */
1302 snd_hda_codec_write(codec,
1303 nvhdmi_con_nids_7x[i],
1304 0,
1305 AC_VERB_SET_CHANNEL_STREAMID,
1306 (stream_tag << 4) | channel_id);
1307 /* set the stream format */
1308 snd_hda_codec_write(codec,
1309 nvhdmi_con_nids_7x[i],
1310 0,
1311 AC_VERB_SET_STREAM_FORMAT,
1312 format);
1313 /* turn on again (if needed) */
1314 /* enable and set the channel status audio/data flag */
1315 if (codec->spdif_status_reset &&
1316 (codec->spdif_ctls & AC_DIG1_ENABLE)) {
1317 snd_hda_codec_write(codec,
1318 nvhdmi_con_nids_7x[i],
1319 0,
1320 AC_VERB_SET_DIGI_CONVERT_1,
1321 codec->spdif_ctls & 0xff);
1322 snd_hda_codec_write(codec,
1323 nvhdmi_con_nids_7x[i],
1324 0,
1325 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
1326 }
1327 }
1328
1329 /* set the Audio Info Frame Checksum */
1330 snd_hda_codec_write(codec, 0x1, 0,
1331 Nv_VERB_SET_Info_Frame_Checksum,
1332 (0x71 - chan - chanmask));
1333
1334 mutex_unlock(&codec->spdif_mutex);
1335 return 0;
1336}
1337
1338static struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = {
1339 .substreams = 1,
1340 .channels_min = 2,
1341 .channels_max = 8,
1342 .nid = nvhdmi_master_con_nid_7x,
1343 .rates = SUPPORTED_RATES,
1344 .maxbps = SUPPORTED_MAXBPS,
1345 .formats = SUPPORTED_FORMATS,
1346 .ops = {
1347 .open = simple_playback_pcm_open,
1348 .close = nvhdmi_8ch_7x_pcm_close,
1349 .prepare = nvhdmi_8ch_7x_pcm_prepare
1350 },
1351};
1352
1353static struct hda_pcm_stream nvhdmi_pcm_playback_2ch = {
1354 .substreams = 1,
1355 .channels_min = 2,
1356 .channels_max = 2,
1357 .nid = nvhdmi_master_con_nid_7x,
1358 .rates = SUPPORTED_RATES,
1359 .maxbps = SUPPORTED_MAXBPS,
1360 .formats = SUPPORTED_FORMATS,
1361 .ops = {
1362 .open = simple_playback_pcm_open,
1363 .close = simple_playback_pcm_close,
1364 .prepare = simple_playback_pcm_prepare
1365 },
1366};
1367
1368static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
1369 .build_controls = generic_hdmi_build_controls,
1370 .build_pcms = generic_hdmi_build_pcms,
1371 .init = nvhdmi_7x_init,
1372 .free = generic_hdmi_free,
1373};
1374
1375static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
1376 .build_controls = generic_hdmi_build_controls,
1377 .build_pcms = generic_hdmi_build_pcms,
1378 .init = nvhdmi_7x_init,
1379 .free = generic_hdmi_free,
1380};
1381
1382static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
1383{
1384 struct hdmi_spec *spec;
1385 int err = patch_generic_hdmi(codec);
1386
1387 if (err < 0)
1388 return err;
1389 spec = codec->spec;
1390 spec->old_pin_detect = 1;
1391 return 0;
1392}
1393
1394static int patch_nvhdmi_2ch(struct hda_codec *codec)
1395{
1396 struct hdmi_spec *spec;
1397
1398 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1399 if (spec == NULL)
1400 return -ENOMEM;
1401
1402 codec->spec = spec;
1403
1404 spec->multiout.num_dacs = 0; /* no analog */
1405 spec->multiout.max_channels = 2;
1406 spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
1407 spec->old_pin_detect = 1;
1408 spec->num_cvts = 1;
1409 spec->cvt[0] = nvhdmi_master_con_nid_7x;
1410 spec->pcm_playback = &nvhdmi_pcm_playback_2ch;
1411
1412 codec->patch_ops = nvhdmi_patch_ops_2ch;
1413
1414 return 0;
1415}
1416
1417static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
1418{
1419 struct hdmi_spec *spec;
1420 int err = patch_nvhdmi_2ch(codec);
1421
1422 if (err < 0)
1423 return err;
1424 spec = codec->spec;
1425 spec->multiout.max_channels = 8;
1426 spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x;
1427 codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
1428 return 0;
1429}
1430
1431/*
1432 * ATI-specific implementations
1433 *
1434 * FIXME: we may omit the whole this and use the generic code once after
1435 * it's confirmed to work.
1436 */
1437
1438#define ATIHDMI_CVT_NID 0x02 /* audio converter */
1439#define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */
1440
1441static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
1442 struct hda_codec *codec,
1443 unsigned int stream_tag,
1444 unsigned int format,
1445 struct snd_pcm_substream *substream)
1446{
1447 struct hdmi_spec *spec = codec->spec;
1448 int chans = substream->runtime->channels;
1449 int i, err;
1450
1451 err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format,
1452 substream);
1453 if (err < 0)
1454 return err;
1455 snd_hda_codec_write(codec, spec->cvt[0], 0, AC_VERB_SET_CVT_CHAN_COUNT,
1456 chans - 1);
1457 /* FIXME: XXX */
1458 for (i = 0; i < chans; i++) {
1459 snd_hda_codec_write(codec, spec->cvt[0], 0,
1460 AC_VERB_SET_HDMI_CHAN_SLOT,
1461 (i << 4) | i);
1462 }
1463 return 0;
1464}
1465
1466static struct hda_pcm_stream atihdmi_pcm_digital_playback = {
1467 .substreams = 1,
1468 .channels_min = 2,
1469 .channels_max = 2,
1470 .nid = ATIHDMI_CVT_NID,
1471 .ops = {
1472 .open = simple_playback_pcm_open,
1473 .close = simple_playback_pcm_close,
1474 .prepare = atihdmi_playback_pcm_prepare
1475 },
1476};
1477
1478static struct hda_verb atihdmi_basic_init[] = {
1479 /* enable digital output on pin widget */
1480 { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1481 {} /* terminator */
1482};
1483
1484static int atihdmi_init(struct hda_codec *codec)
1485{
1486 struct hdmi_spec *spec = codec->spec;
1487
1488 snd_hda_sequence_write(codec, atihdmi_basic_init);
1489 /* SI codec requires to unmute the pin */
1490 if (get_wcaps(codec, spec->pin[0]) & AC_WCAP_OUT_AMP)
1491 snd_hda_codec_write(codec, spec->pin[0], 0,
1492 AC_VERB_SET_AMP_GAIN_MUTE,
1493 AMP_OUT_UNMUTE);
1494 return 0;
1495}
1496
1497static struct hda_codec_ops atihdmi_patch_ops = {
1498 .build_controls = generic_hdmi_build_controls,
1499 .build_pcms = generic_hdmi_build_pcms,
1500 .init = atihdmi_init,
1501 .free = generic_hdmi_free,
1502};
1503
1504
1505static int patch_atihdmi(struct hda_codec *codec)
1506{
1507 struct hdmi_spec *spec;
1508
1509 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1510 if (spec == NULL)
1511 return -ENOMEM;
1512
1513 codec->spec = spec;
1514
1515 spec->multiout.num_dacs = 0; /* no analog */
1516 spec->multiout.max_channels = 2;
1517 spec->multiout.dig_out_nid = ATIHDMI_CVT_NID;
1518 spec->num_cvts = 1;
1519 spec->cvt[0] = ATIHDMI_CVT_NID;
1520 spec->pin[0] = ATIHDMI_PIN_NID;
1521 spec->pcm_playback = &atihdmi_pcm_digital_playback;
1522
1523 codec->patch_ops = atihdmi_patch_ops;
1524
1525 return 0;
1526}
1527
1528
1529/*
1530 * patch entries
1531 */
1532static struct hda_codec_preset snd_hda_preset_hdmi[] = {
1533{ .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi },
1534{ .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi },
1535{ .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi },
1536{ .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi },
1537{ .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi },
1538{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi },
1539{ .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi },
1540{ .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
1541{ .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
1542{ .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
1543{ .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
1544{ .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x },
1545{ .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1546{ .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1547{ .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 },
1548{ .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1549{ .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1550{ .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1551{ .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1552{ .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1553{ .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1554{ .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1555{ .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1556{ .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1557{ .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1558{ .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1559{ .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1560{ .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1561{ .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1562{ .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1563{ .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
1564{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
1565{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
1566{ .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi },
1567{ .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi },
1568{ .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi },
1569{ .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi },
1570{ .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi },
1571{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi },
1572{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi },
1573{} /* terminator */
1574};
1575
1576MODULE_ALIAS("snd-hda-codec-id:1002793c");
1577MODULE_ALIAS("snd-hda-codec-id:10027919");
1578MODULE_ALIAS("snd-hda-codec-id:1002791a");
1579MODULE_ALIAS("snd-hda-codec-id:1002aa01");
1580MODULE_ALIAS("snd-hda-codec-id:10951390");
1581MODULE_ALIAS("snd-hda-codec-id:10951392");
1582MODULE_ALIAS("snd-hda-codec-id:10de0002");
1583MODULE_ALIAS("snd-hda-codec-id:10de0003");
1584MODULE_ALIAS("snd-hda-codec-id:10de0005");
1585MODULE_ALIAS("snd-hda-codec-id:10de0006");
1586MODULE_ALIAS("snd-hda-codec-id:10de0007");
1587MODULE_ALIAS("snd-hda-codec-id:10de000a");
1588MODULE_ALIAS("snd-hda-codec-id:10de000b");
1589MODULE_ALIAS("snd-hda-codec-id:10de000c");
1590MODULE_ALIAS("snd-hda-codec-id:10de000d");
1591MODULE_ALIAS("snd-hda-codec-id:10de0010");
1592MODULE_ALIAS("snd-hda-codec-id:10de0011");
1593MODULE_ALIAS("snd-hda-codec-id:10de0012");
1594MODULE_ALIAS("snd-hda-codec-id:10de0013");
1595MODULE_ALIAS("snd-hda-codec-id:10de0014");
1596MODULE_ALIAS("snd-hda-codec-id:10de0018");
1597MODULE_ALIAS("snd-hda-codec-id:10de0019");
1598MODULE_ALIAS("snd-hda-codec-id:10de001a");
1599MODULE_ALIAS("snd-hda-codec-id:10de001b");
1600MODULE_ALIAS("snd-hda-codec-id:10de001c");
1601MODULE_ALIAS("snd-hda-codec-id:10de0040");
1602MODULE_ALIAS("snd-hda-codec-id:10de0041");
1603MODULE_ALIAS("snd-hda-codec-id:10de0042");
1604MODULE_ALIAS("snd-hda-codec-id:10de0043");
1605MODULE_ALIAS("snd-hda-codec-id:10de0044");
1606MODULE_ALIAS("snd-hda-codec-id:10de0067");
1607MODULE_ALIAS("snd-hda-codec-id:10de8001");
1608MODULE_ALIAS("snd-hda-codec-id:17e80047");
1609MODULE_ALIAS("snd-hda-codec-id:80860054");
1610MODULE_ALIAS("snd-hda-codec-id:80862801");
1611MODULE_ALIAS("snd-hda-codec-id:80862802");
1612MODULE_ALIAS("snd-hda-codec-id:80862803");
1613MODULE_ALIAS("snd-hda-codec-id:80862804");
1614MODULE_ALIAS("snd-hda-codec-id:80862805");
1615MODULE_ALIAS("snd-hda-codec-id:808629fb");
1616
1617MODULE_LICENSE("GPL");
1618MODULE_DESCRIPTION("HDMI HD-audio codec");
1619MODULE_ALIAS("snd-hda-codec-intelhdmi");
1620MODULE_ALIAS("snd-hda-codec-nvhdmi");
1621MODULE_ALIAS("snd-hda-codec-atihdmi");
1622
1623static struct hda_codec_preset_list intel_list = {
1624 .preset = snd_hda_preset_hdmi,
1625 .owner = THIS_MODULE,
1626};
1627
1628static int __init patch_hdmi_init(void)
1629{
1630 return snd_hda_add_codec_preset(&intel_list);
1631}
1632
1633static void __exit patch_hdmi_exit(void)
1634{
1635 snd_hda_delete_codec_preset(&intel_list);
1636}
1637
1638module_init(patch_hdmi_init)
1639module_exit(patch_hdmi_exit)
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
deleted file mode 100644
index 36a9b83a6174..000000000000
--- a/sound/pci/hda/patch_intelhdmi.c
+++ /dev/null
@@ -1,220 +0,0 @@
1/*
2 *
3 * patch_intelhdmi.c - Patch for Intel HDMI codecs
4 *
5 * Copyright(c) 2008 Intel Corporation. All rights reserved.
6 *
7 * Authors:
8 * Jiang Zhe <zhe.jiang@intel.com>
9 * Wu Fengguang <wfg@linux.intel.com>
10 *
11 * Maintained by:
12 * Wu Fengguang <wfg@linux.intel.com>
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29#include <linux/init.h>
30#include <linux/delay.h>
31#include <linux/slab.h>
32#include <sound/core.h>
33#include "hda_codec.h"
34#include "hda_local.h"
35
36/*
37 * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device
38 * could support two independent pipes, each of them can be connected to one or
39 * more ports (DVI, HDMI or DisplayPort).
40 *
41 * The HDA correspondence of pipes/ports are converter/pin nodes.
42 */
43#define MAX_HDMI_CVTS 3
44#define MAX_HDMI_PINS 3
45
46#include "patch_hdmi.c"
47
48static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
49 "INTEL HDMI 0",
50 "INTEL HDMI 1",
51 "INTEL HDMI 2",
52};
53
54/*
55 * HDMI callbacks
56 */
57
58static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
59 struct hda_codec *codec,
60 unsigned int stream_tag,
61 unsigned int format,
62 struct snd_pcm_substream *substream)
63{
64 hdmi_set_channel_count(codec, hinfo->nid,
65 substream->runtime->channels);
66
67 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
68
69 return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
70}
71
72static struct hda_pcm_stream intel_hdmi_pcm_playback = {
73 .substreams = 1,
74 .channels_min = 2,
75 .ops = {
76 .open = hdmi_pcm_open,
77 .prepare = intel_hdmi_playback_pcm_prepare,
78 },
79};
80
81static int intel_hdmi_build_pcms(struct hda_codec *codec)
82{
83 struct hdmi_spec *spec = codec->spec;
84 struct hda_pcm *info = spec->pcm_rec;
85 int i;
86
87 codec->num_pcms = spec->num_cvts;
88 codec->pcm_info = info;
89
90 for (i = 0; i < codec->num_pcms; i++, info++) {
91 unsigned int chans;
92
93 chans = get_wcaps(codec, spec->cvt[i]);
94 chans = get_wcaps_channels(chans);
95
96 info->name = intel_hdmi_pcm_names[i];
97 info->pcm_type = HDA_PCM_TYPE_HDMI;
98 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
99 intel_hdmi_pcm_playback;
100 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
101 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
102 }
103
104 return 0;
105}
106
107static int intel_hdmi_build_controls(struct hda_codec *codec)
108{
109 struct hdmi_spec *spec = codec->spec;
110 int err;
111 int i;
112
113 for (i = 0; i < codec->num_pcms; i++) {
114 err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]);
115 if (err < 0)
116 return err;
117 }
118
119 return 0;
120}
121
122static int intel_hdmi_init(struct hda_codec *codec)
123{
124 struct hdmi_spec *spec = codec->spec;
125 int i;
126
127 for (i = 0; spec->pin[i]; i++) {
128 hdmi_enable_output(codec, spec->pin[i]);
129 snd_hda_codec_write(codec, spec->pin[i], 0,
130 AC_VERB_SET_UNSOLICITED_ENABLE,
131 AC_USRSP_EN | spec->pin[i]);
132 }
133 return 0;
134}
135
136static void intel_hdmi_free(struct hda_codec *codec)
137{
138 struct hdmi_spec *spec = codec->spec;
139 int i;
140
141 for (i = 0; i < spec->num_pins; i++)
142 snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
143
144 kfree(spec);
145}
146
147static struct hda_codec_ops intel_hdmi_patch_ops = {
148 .init = intel_hdmi_init,
149 .free = intel_hdmi_free,
150 .build_pcms = intel_hdmi_build_pcms,
151 .build_controls = intel_hdmi_build_controls,
152 .unsol_event = hdmi_unsol_event,
153};
154
155static int patch_intel_hdmi(struct hda_codec *codec)
156{
157 struct hdmi_spec *spec;
158 int i;
159
160 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
161 if (spec == NULL)
162 return -ENOMEM;
163
164 codec->spec = spec;
165 if (hdmi_parse_codec(codec) < 0) {
166 codec->spec = NULL;
167 kfree(spec);
168 return -EINVAL;
169 }
170 codec->patch_ops = intel_hdmi_patch_ops;
171
172 for (i = 0; i < spec->num_pins; i++)
173 snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
174
175 init_channel_allocations();
176
177 return 0;
178}
179
180static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
181{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_intel_hdmi },
182{ .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_intel_hdmi },
183{ .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_intel_hdmi },
184{ .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_intel_hdmi },
185{ .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi },
186{ .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi },
187{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_intel_hdmi },
188{ .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi },
189{} /* terminator */
190};
191
192MODULE_ALIAS("snd-hda-codec-id:808629fb");
193MODULE_ALIAS("snd-hda-codec-id:80862801");
194MODULE_ALIAS("snd-hda-codec-id:80862802");
195MODULE_ALIAS("snd-hda-codec-id:80862803");
196MODULE_ALIAS("snd-hda-codec-id:80862804");
197MODULE_ALIAS("snd-hda-codec-id:80862805");
198MODULE_ALIAS("snd-hda-codec-id:80860054");
199MODULE_ALIAS("snd-hda-codec-id:10951392");
200
201MODULE_LICENSE("GPL");
202MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
203
204static struct hda_codec_preset_list intel_list = {
205 .preset = snd_hda_preset_intelhdmi,
206 .owner = THIS_MODULE,
207};
208
209static int __init patch_intelhdmi_init(void)
210{
211 return snd_hda_add_codec_preset(&intel_list);
212}
213
214static void __exit patch_intelhdmi_exit(void)
215{
216 snd_hda_delete_codec_preset(&intel_list);
217}
218
219module_init(patch_intelhdmi_init)
220module_exit(patch_intelhdmi_exit)
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
deleted file mode 100644
index baa108b9d6aa..000000000000
--- a/sound/pci/hda/patch_nvhdmi.c
+++ /dev/null
@@ -1,608 +0,0 @@
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * HD audio interface patch for NVIDIA HDMI codecs
5 *
6 * Copyright (c) 2008 NVIDIA Corp. All rights reserved.
7 * Copyright (c) 2008 Wei Ni <wni@nvidia.com>
8 *
9 *
10 * This driver is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This driver is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <linux/init.h>
26#include <linux/delay.h>
27#include <linux/slab.h>
28#include <sound/core.h>
29#include "hda_codec.h"
30#include "hda_local.h"
31
32#define MAX_HDMI_CVTS 1
33#define MAX_HDMI_PINS 1
34
35#include "patch_hdmi.c"
36
37static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
38 "NVIDIA HDMI",
39};
40
41/* define below to restrict the supported rates and formats */
42/* #define LIMITED_RATE_FMT_SUPPORT */
43
44enum HDACodec {
45 HDA_CODEC_NVIDIA_MCP7X,
46 HDA_CODEC_NVIDIA_MCP89,
47 HDA_CODEC_NVIDIA_GT21X,
48 HDA_CODEC_INVALID
49};
50
51#define Nv_VERB_SET_Channel_Allocation 0xF79
52#define Nv_VERB_SET_Info_Frame_Checksum 0xF7A
53#define Nv_VERB_SET_Audio_Protection_On 0xF98
54#define Nv_VERB_SET_Audio_Protection_Off 0xF99
55
56#define nvhdmi_master_con_nid_7x 0x04
57#define nvhdmi_master_pin_nid_7x 0x05
58
59#define nvhdmi_master_con_nid_89 0x04
60#define nvhdmi_master_pin_nid_89 0x05
61
62static hda_nid_t nvhdmi_con_nids_7x[4] = {
63 /*front, rear, clfe, rear_surr */
64 0x6, 0x8, 0xa, 0xc,
65};
66
67static struct hda_verb nvhdmi_basic_init_7x[] = {
68 /* set audio protect on */
69 { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
70 /* enable digital output on pin widget */
71 { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
72 { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
73 { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
74 { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
75 { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 },
76 {} /* terminator */
77};
78
79#ifdef LIMITED_RATE_FMT_SUPPORT
80/* support only the safe format and rate */
81#define SUPPORTED_RATES SNDRV_PCM_RATE_48000
82#define SUPPORTED_MAXBPS 16
83#define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE
84#else
85/* support all rates and formats */
86#define SUPPORTED_RATES \
87 (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
88 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\
89 SNDRV_PCM_RATE_192000)
90#define SUPPORTED_MAXBPS 24
91#define SUPPORTED_FORMATS \
92 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
93#endif
94
95/*
96 * Controls
97 */
98static int nvhdmi_build_controls(struct hda_codec *codec)
99{
100 struct hdmi_spec *spec = codec->spec;
101 int err;
102 int i;
103
104 if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
105 || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
106 for (i = 0; i < codec->num_pcms; i++) {
107 err = snd_hda_create_spdif_out_ctls(codec,
108 spec->cvt[i]);
109 if (err < 0)
110 return err;
111 }
112 } else {
113 err = snd_hda_create_spdif_out_ctls(codec,
114 spec->multiout.dig_out_nid);
115 if (err < 0)
116 return err;
117 }
118
119 return 0;
120}
121
122static int nvhdmi_init(struct hda_codec *codec)
123{
124 struct hdmi_spec *spec = codec->spec;
125 int i;
126 if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
127 || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
128 for (i = 0; spec->pin[i]; i++) {
129 hdmi_enable_output(codec, spec->pin[i]);
130 snd_hda_codec_write(codec, spec->pin[i], 0,
131 AC_VERB_SET_UNSOLICITED_ENABLE,
132 AC_USRSP_EN | spec->pin[i]);
133 }
134 } else {
135 snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
136 }
137 return 0;
138}
139
140static void nvhdmi_free(struct hda_codec *codec)
141{
142 struct hdmi_spec *spec = codec->spec;
143 int i;
144
145 if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
146 || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
147 for (i = 0; i < spec->num_pins; i++)
148 snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
149 }
150
151 kfree(spec);
152}
153
154/*
155 * Digital out
156 */
157static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
158 struct hda_codec *codec,
159 struct snd_pcm_substream *substream)
160{
161 struct hdmi_spec *spec = codec->spec;
162 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
163}
164
165static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
166 struct hda_codec *codec,
167 struct snd_pcm_substream *substream)
168{
169 struct hdmi_spec *spec = codec->spec;
170 int i;
171
172 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
173 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
174 for (i = 0; i < 4; i++) {
175 /* set the stream id */
176 snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
177 AC_VERB_SET_CHANNEL_STREAMID, 0);
178 /* set the stream format */
179 snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
180 AC_VERB_SET_STREAM_FORMAT, 0);
181 }
182
183 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
184}
185
186static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
187 struct hda_codec *codec,
188 struct snd_pcm_substream *substream)
189{
190 struct hdmi_spec *spec = codec->spec;
191 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
192}
193
194static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
195 struct hda_codec *codec,
196 unsigned int stream_tag,
197 unsigned int format,
198 struct snd_pcm_substream *substream)
199{
200 hdmi_set_channel_count(codec, hinfo->nid,
201 substream->runtime->channels);
202
203 hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
204
205 return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
206}
207
208static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
209 struct hda_codec *codec,
210 unsigned int stream_tag,
211 unsigned int format,
212 struct snd_pcm_substream *substream)
213{
214 int chs;
215 unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
216 int i;
217
218 mutex_lock(&codec->spdif_mutex);
219
220 chs = substream->runtime->channels;
221 chan = chs ? (chs - 1) : 1;
222
223 switch (chs) {
224 default:
225 case 0:
226 case 2:
227 chanmask = 0x00;
228 break;
229 case 4:
230 chanmask = 0x08;
231 break;
232 case 6:
233 chanmask = 0x0b;
234 break;
235 case 8:
236 chanmask = 0x13;
237 break;
238 }
239 dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
240 dataDCC2 = 0x2;
241
242 /* set the Audio InforFrame Channel Allocation */
243 snd_hda_codec_write(codec, 0x1, 0,
244 Nv_VERB_SET_Channel_Allocation, chanmask);
245
246 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
247 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
248 snd_hda_codec_write(codec,
249 nvhdmi_master_con_nid_7x,
250 0,
251 AC_VERB_SET_DIGI_CONVERT_1,
252 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
253
254 /* set the stream id */
255 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
256 AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
257
258 /* set the stream format */
259 snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
260 AC_VERB_SET_STREAM_FORMAT, format);
261
262 /* turn on again (if needed) */
263 /* enable and set the channel status audio/data flag */
264 if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
265 snd_hda_codec_write(codec,
266 nvhdmi_master_con_nid_7x,
267 0,
268 AC_VERB_SET_DIGI_CONVERT_1,
269 codec->spdif_ctls & 0xff);
270 snd_hda_codec_write(codec,
271 nvhdmi_master_con_nid_7x,
272 0,
273 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
274 }
275
276 for (i = 0; i < 4; i++) {
277 if (chs == 2)
278 channel_id = 0;
279 else
280 channel_id = i * 2;
281
282 /* turn off SPDIF once;
283 *otherwise the IEC958 bits won't be updated
284 */
285 if (codec->spdif_status_reset &&
286 (codec->spdif_ctls & AC_DIG1_ENABLE))
287 snd_hda_codec_write(codec,
288 nvhdmi_con_nids_7x[i],
289 0,
290 AC_VERB_SET_DIGI_CONVERT_1,
291 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
292 /* set the stream id */
293 snd_hda_codec_write(codec,
294 nvhdmi_con_nids_7x[i],
295 0,
296 AC_VERB_SET_CHANNEL_STREAMID,
297 (stream_tag << 4) | channel_id);
298 /* set the stream format */
299 snd_hda_codec_write(codec,
300 nvhdmi_con_nids_7x[i],
301 0,
302 AC_VERB_SET_STREAM_FORMAT,
303 format);
304 /* turn on again (if needed) */
305 /* enable and set the channel status audio/data flag */
306 if (codec->spdif_status_reset &&
307 (codec->spdif_ctls & AC_DIG1_ENABLE)) {
308 snd_hda_codec_write(codec,
309 nvhdmi_con_nids_7x[i],
310 0,
311 AC_VERB_SET_DIGI_CONVERT_1,
312 codec->spdif_ctls & 0xff);
313 snd_hda_codec_write(codec,
314 nvhdmi_con_nids_7x[i],
315 0,
316 AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
317 }
318 }
319
320 /* set the Audio Info Frame Checksum */
321 snd_hda_codec_write(codec, 0x1, 0,
322 Nv_VERB_SET_Info_Frame_Checksum,
323 (0x71 - chan - chanmask));
324
325 mutex_unlock(&codec->spdif_mutex);
326 return 0;
327}
328
329static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
330 struct hda_codec *codec,
331 unsigned int stream_tag,
332 unsigned int format,
333 struct snd_pcm_substream *substream)
334{
335 struct hdmi_spec *spec = codec->spec;
336 return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
337 format, substream);
338}
339
340static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
341 .substreams = 1,
342 .channels_min = 2,
343 .ops = {
344 .open = hdmi_pcm_open,
345 .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
346 },
347};
348
349static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
350 .substreams = 1,
351 .channels_min = 2,
352 .channels_max = 8,
353 .nid = nvhdmi_master_con_nid_7x,
354 .rates = SUPPORTED_RATES,
355 .maxbps = SUPPORTED_MAXBPS,
356 .formats = SUPPORTED_FORMATS,
357 .ops = {
358 .open = nvhdmi_dig_playback_pcm_open,
359 .close = nvhdmi_dig_playback_pcm_close_8ch_7x,
360 .prepare = nvhdmi_dig_playback_pcm_prepare_8ch
361 },
362};
363
364static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
365 .substreams = 1,
366 .channels_min = 2,
367 .channels_max = 2,
368 .nid = nvhdmi_master_con_nid_7x,
369 .rates = SUPPORTED_RATES,
370 .maxbps = SUPPORTED_MAXBPS,
371 .formats = SUPPORTED_FORMATS,
372 .ops = {
373 .open = nvhdmi_dig_playback_pcm_open,
374 .close = nvhdmi_dig_playback_pcm_close_2ch,
375 .prepare = nvhdmi_dig_playback_pcm_prepare_2ch
376 },
377};
378
379static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
380{
381 struct hdmi_spec *spec = codec->spec;
382 struct hda_pcm *info = spec->pcm_rec;
383 int i;
384
385 codec->num_pcms = spec->num_cvts;
386 codec->pcm_info = info;
387
388 for (i = 0; i < codec->num_pcms; i++, info++) {
389 unsigned int chans;
390
391 chans = get_wcaps(codec, spec->cvt[i]);
392 chans = get_wcaps_channels(chans);
393
394 info->name = nvhdmi_pcm_names[i];
395 info->pcm_type = HDA_PCM_TYPE_HDMI;
396 info->stream[SNDRV_PCM_STREAM_PLAYBACK]
397 = nvhdmi_pcm_digital_playback_8ch_89;
398 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
399 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
400 }
401
402 return 0;
403}
404
405static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
406{
407 struct hdmi_spec *spec = codec->spec;
408 struct hda_pcm *info = spec->pcm_rec;
409
410 codec->num_pcms = 1;
411 codec->pcm_info = info;
412
413 info->name = "NVIDIA HDMI";
414 info->pcm_type = HDA_PCM_TYPE_HDMI;
415 info->stream[SNDRV_PCM_STREAM_PLAYBACK]
416 = nvhdmi_pcm_digital_playback_8ch_7x;
417
418 return 0;
419}
420
421static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
422{
423 struct hdmi_spec *spec = codec->spec;
424 struct hda_pcm *info = spec->pcm_rec;
425
426 codec->num_pcms = 1;
427 codec->pcm_info = info;
428
429 info->name = "NVIDIA HDMI";
430 info->pcm_type = HDA_PCM_TYPE_HDMI;
431 info->stream[SNDRV_PCM_STREAM_PLAYBACK]
432 = nvhdmi_pcm_digital_playback_2ch;
433
434 return 0;
435}
436
437static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
438 .build_controls = nvhdmi_build_controls,
439 .build_pcms = nvhdmi_build_pcms_8ch_89,
440 .init = nvhdmi_init,
441 .free = nvhdmi_free,
442 .unsol_event = hdmi_unsol_event,
443};
444
445static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
446 .build_controls = nvhdmi_build_controls,
447 .build_pcms = nvhdmi_build_pcms_8ch_7x,
448 .init = nvhdmi_init,
449 .free = nvhdmi_free,
450};
451
452static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
453 .build_controls = nvhdmi_build_controls,
454 .build_pcms = nvhdmi_build_pcms_2ch,
455 .init = nvhdmi_init,
456 .free = nvhdmi_free,
457};
458
459static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
460{
461 struct hdmi_spec *spec;
462 int i;
463
464 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
465 if (spec == NULL)
466 return -ENOMEM;
467
468 codec->spec = spec;
469 spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
470 spec->old_pin_detect = 1;
471
472 if (hdmi_parse_codec(codec) < 0) {
473 codec->spec = NULL;
474 kfree(spec);
475 return -EINVAL;
476 }
477 codec->patch_ops = nvhdmi_patch_ops_8ch_89;
478
479 for (i = 0; i < spec->num_pins; i++)
480 snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
481
482 init_channel_allocations();
483
484 return 0;
485}
486
487static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
488{
489 struct hdmi_spec *spec;
490
491 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
492 if (spec == NULL)
493 return -ENOMEM;
494
495 codec->spec = spec;
496
497 spec->multiout.num_dacs = 0; /* no analog */
498 spec->multiout.max_channels = 8;
499 spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
500 spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
501 spec->old_pin_detect = 1;
502
503 codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
504
505 return 0;
506}
507
508static int patch_nvhdmi_2ch(struct hda_codec *codec)
509{
510 struct hdmi_spec *spec;
511
512 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
513 if (spec == NULL)
514 return -ENOMEM;
515
516 codec->spec = spec;
517
518 spec->multiout.num_dacs = 0; /* no analog */
519 spec->multiout.max_channels = 2;
520 spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
521 spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
522 spec->old_pin_detect = 1;
523
524 codec->patch_ops = nvhdmi_patch_ops_2ch;
525
526 return 0;
527}
528
529/*
530 * patch entries
531 */
532static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
533 { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
534 { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
535 { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
536 { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x },
537 { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x },
538 { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
539 { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
540 { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 },
541 { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
542 { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
543 { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
544 { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
545 { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
546 { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
547 { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
548 { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
549 { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
550 { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
551 { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
552 { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
553 { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
554 { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
555 { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
556 { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 },
557 { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
558 { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
559 {} /* terminator */
560};
561
562MODULE_ALIAS("snd-hda-codec-id:10de0002");
563MODULE_ALIAS("snd-hda-codec-id:10de0003");
564MODULE_ALIAS("snd-hda-codec-id:10de0005");
565MODULE_ALIAS("snd-hda-codec-id:10de0006");
566MODULE_ALIAS("snd-hda-codec-id:10de0007");
567MODULE_ALIAS("snd-hda-codec-id:10de000a");
568MODULE_ALIAS("snd-hda-codec-id:10de000b");
569MODULE_ALIAS("snd-hda-codec-id:10de000c");
570MODULE_ALIAS("snd-hda-codec-id:10de000d");
571MODULE_ALIAS("snd-hda-codec-id:10de0010");
572MODULE_ALIAS("snd-hda-codec-id:10de0011");
573MODULE_ALIAS("snd-hda-codec-id:10de0012");
574MODULE_ALIAS("snd-hda-codec-id:10de0013");
575MODULE_ALIAS("snd-hda-codec-id:10de0014");
576MODULE_ALIAS("snd-hda-codec-id:10de0018");
577MODULE_ALIAS("snd-hda-codec-id:10de0019");
578MODULE_ALIAS("snd-hda-codec-id:10de001a");
579MODULE_ALIAS("snd-hda-codec-id:10de001b");
580MODULE_ALIAS("snd-hda-codec-id:10de001c");
581MODULE_ALIAS("snd-hda-codec-id:10de0040");
582MODULE_ALIAS("snd-hda-codec-id:10de0041");
583MODULE_ALIAS("snd-hda-codec-id:10de0042");
584MODULE_ALIAS("snd-hda-codec-id:10de0043");
585MODULE_ALIAS("snd-hda-codec-id:10de0044");
586MODULE_ALIAS("snd-hda-codec-id:10de0067");
587MODULE_ALIAS("snd-hda-codec-id:10de8001");
588
589MODULE_LICENSE("GPL");
590MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
591
592static struct hda_codec_preset_list nvhdmi_list = {
593 .preset = snd_hda_preset_nvhdmi,
594 .owner = THIS_MODULE,
595};
596
597static int __init patch_nvhdmi_init(void)
598{
599 return snd_hda_add_codec_preset(&nvhdmi_list);
600}
601
602static void __exit patch_nvhdmi_exit(void)
603{
604 snd_hda_delete_codec_preset(&nvhdmi_list);
605}
606
607module_init(patch_nvhdmi_init)
608module_exit(patch_nvhdmi_exit)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index a432e6efd19b..5f00589cb791 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -28,6 +28,7 @@
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/pci.h> 29#include <linux/pci.h>
30#include <sound/core.h> 30#include <sound/core.h>
31#include <sound/jack.h>
31#include "hda_codec.h" 32#include "hda_codec.h"
32#include "hda_local.h" 33#include "hda_local.h"
33#include "hda_beep.h" 34#include "hda_beep.h"
@@ -282,6 +283,12 @@ struct alc_mic_route {
282 unsigned char amix_idx; 283 unsigned char amix_idx;
283}; 284};
284 285
286struct alc_jack {
287 hda_nid_t nid;
288 int type;
289 struct snd_jack *jack;
290};
291
285#define MUX_IDX_UNDEF ((unsigned char)-1) 292#define MUX_IDX_UNDEF ((unsigned char)-1)
286 293
287struct alc_customize_define { 294struct alc_customize_define {
@@ -294,6 +301,7 @@ struct alc_customize_define {
294 unsigned int platform_type:1; 301 unsigned int platform_type:1;
295 unsigned int swap:1; 302 unsigned int swap:1;
296 unsigned int override:1; 303 unsigned int override:1;
304 unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */
297}; 305};
298 306
299struct alc_spec { 307struct alc_spec {
@@ -357,6 +365,9 @@ struct alc_spec {
357 /* PCM information */ 365 /* PCM information */
358 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ 366 struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */
359 367
368 /* jack detection */
369 struct snd_array jacks;
370
360 /* dynamic controls, init_verbs and input_mux */ 371 /* dynamic controls, init_verbs and input_mux */
361 struct auto_pin_cfg autocfg; 372 struct auto_pin_cfg autocfg;
362 struct alc_customize_define cdefine; 373 struct alc_customize_define cdefine;
@@ -383,6 +394,7 @@ struct alc_spec {
383 unsigned int no_analog :1; /* digital I/O only */ 394 unsigned int no_analog :1; /* digital I/O only */
384 unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ 395 unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
385 int init_amp; 396 int init_amp;
397 int codec_variant; /* flag for other variants */
386 398
387 /* for virtual master */ 399 /* for virtual master */
388 hda_nid_t vmaster_nid; 400 hda_nid_t vmaster_nid;
@@ -846,7 +858,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
846{ 858{
847 unsigned int val = PIN_IN; 859 unsigned int val = PIN_IN;
848 860
849 if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { 861 if (auto_pin_type == AUTO_PIN_MIC) {
850 unsigned int pincap; 862 unsigned int pincap;
851 unsigned int oldval; 863 unsigned int oldval;
852 oldval = snd_hda_codec_read(codec, nid, 0, 864 oldval = snd_hda_codec_read(codec, nid, 0,
@@ -866,6 +878,28 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid,
866 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); 878 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val);
867} 879}
868 880
881static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
882{
883 struct alc_spec *spec = codec->spec;
884 struct auto_pin_cfg *cfg = &spec->autocfg;
885
886 if (!cfg->line_outs) {
887 while (cfg->line_outs < AUTO_CFG_MAX_OUTS &&
888 cfg->line_out_pins[cfg->line_outs])
889 cfg->line_outs++;
890 }
891 if (!cfg->speaker_outs) {
892 while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS &&
893 cfg->speaker_pins[cfg->speaker_outs])
894 cfg->speaker_outs++;
895 }
896 if (!cfg->hp_outs) {
897 while (cfg->hp_outs < AUTO_CFG_MAX_OUTS &&
898 cfg->hp_pins[cfg->hp_outs])
899 cfg->hp_outs++;
900 }
901}
902
869/* 903/*
870 */ 904 */
871static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) 905static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
@@ -934,6 +968,8 @@ static void setup_preset(struct hda_codec *codec,
934 968
935 if (preset->setup) 969 if (preset->setup)
936 preset->setup(codec); 970 preset->setup(codec);
971
972 alc_fixup_autocfg_pin_nums(codec);
937} 973}
938 974
939/* Enable GPIO mask and set output */ 975/* Enable GPIO mask and set output */
@@ -990,25 +1026,136 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
990 alc_fix_pll(codec); 1026 alc_fix_pll(codec);
991} 1027}
992 1028
993static void alc_automute_pin(struct hda_codec *codec) 1029#ifdef CONFIG_SND_HDA_INPUT_JACK
1030static void alc_free_jack_priv(struct snd_jack *jack)
1031{
1032 struct alc_jack *jacks = jack->private_data;
1033 jacks->nid = 0;
1034 jacks->jack = NULL;
1035}
1036
1037static int alc_add_jack(struct hda_codec *codec,
1038 hda_nid_t nid, int type)
1039{
1040 struct alc_spec *spec;
1041 struct alc_jack *jack;
1042 const char *name;
1043 int err;
1044
1045 spec = codec->spec;
1046 snd_array_init(&spec->jacks, sizeof(*jack), 32);
1047 jack = snd_array_new(&spec->jacks);
1048 if (!jack)
1049 return -ENOMEM;
1050
1051 jack->nid = nid;
1052 jack->type = type;
1053 name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ;
1054
1055 err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
1056 if (err < 0)
1057 return err;
1058 jack->jack->private_data = jack;
1059 jack->jack->private_free = alc_free_jack_priv;
1060 return 0;
1061}
1062
1063static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
994{ 1064{
995 struct alc_spec *spec = codec->spec; 1065 struct alc_spec *spec = codec->spec;
996 unsigned int nid = spec->autocfg.hp_pins[0]; 1066 struct alc_jack *jacks = spec->jacks.list;
1067
1068 if (jacks) {
1069 int i;
1070 for (i = 0; i < spec->jacks.used; i++) {
1071 if (jacks->nid == nid) {
1072 unsigned int present;
1073 present = snd_hda_jack_detect(codec, nid);
1074
1075 present = (present) ? jacks->type : 0;
1076
1077 snd_jack_report(jacks->jack, present);
1078 }
1079 jacks++;
1080 }
1081 }
1082}
1083
1084static int alc_init_jacks(struct hda_codec *codec)
1085{
1086 struct alc_spec *spec = codec->spec;
1087 int err;
1088 unsigned int hp_nid = spec->autocfg.hp_pins[0];
1089 unsigned int mic_nid = spec->ext_mic.pin;
1090
1091 if (hp_nid) {
1092 err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE);
1093 if (err < 0)
1094 return err;
1095 alc_report_jack(codec, hp_nid);
1096 }
1097
1098 if (mic_nid) {
1099 err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE);
1100 if (err < 0)
1101 return err;
1102 alc_report_jack(codec, mic_nid);
1103 }
1104
1105 return 0;
1106}
1107#else
1108static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid)
1109{
1110}
1111
1112static inline int alc_init_jacks(struct hda_codec *codec)
1113{
1114 return 0;
1115}
1116#endif
1117
1118static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
1119{
1120 struct alc_spec *spec = codec->spec;
1121 unsigned int mute;
1122 hda_nid_t nid;
997 int i; 1123 int i;
998 1124
999 if (!nid) 1125 spec->jack_present = 0;
1000 return; 1126 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
1001 spec->jack_present = snd_hda_jack_detect(codec, nid); 1127 nid = spec->autocfg.hp_pins[i];
1128 if (!nid)
1129 break;
1130 if (snd_hda_jack_detect(codec, nid)) {
1131 spec->jack_present = 1;
1132 break;
1133 }
1134 alc_report_jack(codec, spec->autocfg.hp_pins[i]);
1135 }
1136
1137 mute = spec->jack_present ? HDA_AMP_MUTE : 0;
1138 /* Toggle internal speakers muting */
1002 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { 1139 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
1003 nid = spec->autocfg.speaker_pins[i]; 1140 nid = spec->autocfg.speaker_pins[i];
1004 if (!nid) 1141 if (!nid)
1005 break; 1142 break;
1006 snd_hda_codec_write(codec, nid, 0, 1143 if (pinctl) {
1144 snd_hda_codec_write(codec, nid, 0,
1007 AC_VERB_SET_PIN_WIDGET_CONTROL, 1145 AC_VERB_SET_PIN_WIDGET_CONTROL,
1008 spec->jack_present ? 0 : PIN_OUT); 1146 spec->jack_present ? 0 : PIN_OUT);
1147 } else {
1148 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1149 HDA_AMP_MUTE, mute);
1150 }
1009 } 1151 }
1010} 1152}
1011 1153
1154static void alc_automute_pin(struct hda_codec *codec)
1155{
1156 alc_automute_speaker(codec, 1);
1157}
1158
1012static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, 1159static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
1013 hda_nid_t nid) 1160 hda_nid_t nid)
1014{ 1161{
@@ -1090,6 +1237,7 @@ static void alc_mic_automute(struct hda_codec *codec)
1090 AC_VERB_SET_CONNECT_SEL, 1237 AC_VERB_SET_CONNECT_SEL,
1091 alive->mux_idx); 1238 alive->mux_idx);
1092 } 1239 }
1240 alc_report_jack(codec, spec->ext_mic.pin);
1093 1241
1094 /* FIXME: analog mixer */ 1242 /* FIXME: analog mixer */
1095} 1243}
@@ -1236,24 +1384,35 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
1236static void alc_init_auto_hp(struct hda_codec *codec) 1384static void alc_init_auto_hp(struct hda_codec *codec)
1237{ 1385{
1238 struct alc_spec *spec = codec->spec; 1386 struct alc_spec *spec = codec->spec;
1387 struct auto_pin_cfg *cfg = &spec->autocfg;
1388 int i;
1239 1389
1240 if (!spec->autocfg.hp_pins[0]) 1390 if (!cfg->hp_pins[0]) {
1241 return; 1391 if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1392 return;
1393 }
1242 1394
1243 if (!spec->autocfg.speaker_pins[0]) { 1395 if (!cfg->speaker_pins[0]) {
1244 if (spec->autocfg.line_out_pins[0] && 1396 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1245 spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
1246 spec->autocfg.speaker_pins[0] =
1247 spec->autocfg.line_out_pins[0];
1248 else
1249 return; 1397 return;
1398 memcpy(cfg->speaker_pins, cfg->line_out_pins,
1399 sizeof(cfg->speaker_pins));
1400 cfg->speaker_outs = cfg->line_outs;
1250 } 1401 }
1251 1402
1252 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", 1403 if (!cfg->hp_pins[0]) {
1253 spec->autocfg.hp_pins[0]); 1404 memcpy(cfg->hp_pins, cfg->line_out_pins,
1254 snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0, 1405 sizeof(cfg->hp_pins));
1406 cfg->hp_outs = cfg->line_outs;
1407 }
1408
1409 for (i = 0; i < cfg->hp_outs; i++) {
1410 snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
1411 cfg->hp_pins[i]);
1412 snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0,
1255 AC_VERB_SET_UNSOLICITED_ENABLE, 1413 AC_VERB_SET_UNSOLICITED_ENABLE,
1256 AC_USRSP_EN | ALC880_HP_EVENT); 1414 AC_USRSP_EN | ALC880_HP_EVENT);
1415 }
1257 spec->unsol_event = alc_sku_unsol_event; 1416 spec->unsol_event = alc_sku_unsol_event;
1258} 1417}
1259 1418
@@ -1265,30 +1424,28 @@ static void alc_init_auto_mic(struct hda_codec *codec)
1265 int i; 1424 int i;
1266 1425
1267 /* there must be only two mic inputs exclusively */ 1426 /* there must be only two mic inputs exclusively */
1268 for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) 1427 for (i = 0; i < cfg->num_inputs; i++)
1269 if (cfg->input_pins[i]) 1428 if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
1270 return; 1429 return;
1271 1430
1272 fixed = ext = 0; 1431 fixed = ext = 0;
1273 for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) { 1432 for (i = 0; i < cfg->num_inputs; i++) {
1274 hda_nid_t nid = cfg->input_pins[i]; 1433 hda_nid_t nid = cfg->inputs[i].pin;
1275 unsigned int defcfg; 1434 unsigned int defcfg;
1276 if (!nid)
1277 return;
1278 defcfg = snd_hda_codec_get_pincfg(codec, nid); 1435 defcfg = snd_hda_codec_get_pincfg(codec, nid);
1279 switch (get_defcfg_connect(defcfg)) { 1436 switch (snd_hda_get_input_pin_attr(defcfg)) {
1280 case AC_JACK_PORT_FIXED: 1437 case INPUT_PIN_ATTR_INT:
1281 if (fixed) 1438 if (fixed)
1282 return; /* already occupied */ 1439 return; /* already occupied */
1283 fixed = nid; 1440 fixed = nid;
1284 break; 1441 break;
1285 case AC_JACK_PORT_COMPLEX: 1442 case INPUT_PIN_ATTR_UNUSED:
1443 return; /* invalid entry */
1444 default:
1286 if (ext) 1445 if (ext)
1287 return; /* already occupied */ 1446 return; /* already occupied */
1288 ext = nid; 1447 ext = nid;
1289 break; 1448 break;
1290 default:
1291 return; /* invalid entry */
1292 } 1449 }
1293 } 1450 }
1294 if (!ext || !fixed) 1451 if (!ext || !fixed)
@@ -1308,6 +1465,11 @@ static void alc_init_auto_mic(struct hda_codec *codec)
1308 spec->unsol_event = alc_sku_unsol_event; 1465 spec->unsol_event = alc_sku_unsol_event;
1309} 1466}
1310 1467
1468/* Could be any non-zero and even value. When used as fixup, tells
1469 * the driver to ignore any present sku defines.
1470 */
1471#define ALC_FIXUP_SKU_IGNORE (2)
1472
1311static int alc_auto_parse_customize_define(struct hda_codec *codec) 1473static int alc_auto_parse_customize_define(struct hda_codec *codec)
1312{ 1474{
1313 unsigned int ass, tmp, i; 1475 unsigned int ass, tmp, i;
@@ -1316,6 +1478,13 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec)
1316 1478
1317 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */ 1479 spec->cdefine.enable_pcbeep = 1; /* assume always enabled */
1318 1480
1481 if (spec->cdefine.fixup) {
1482 ass = spec->cdefine.sku_cfg;
1483 if (ass == ALC_FIXUP_SKU_IGNORE)
1484 return -1;
1485 goto do_sku;
1486 }
1487
1319 ass = codec->subsystem_id & 0xffff; 1488 ass = codec->subsystem_id & 0xffff;
1320 if (ass != codec->bus->pci->subsystem_device && (ass & 1)) 1489 if (ass != codec->bus->pci->subsystem_device && (ass & 1))
1321 goto do_sku; 1490 goto do_sku;
@@ -1383,6 +1552,13 @@ static int alc_subsystem_id(struct hda_codec *codec,
1383 unsigned nid; 1552 unsigned nid;
1384 struct alc_spec *spec = codec->spec; 1553 struct alc_spec *spec = codec->spec;
1385 1554
1555 if (spec->cdefine.fixup) {
1556 ass = spec->cdefine.sku_cfg;
1557 if (ass == ALC_FIXUP_SKU_IGNORE)
1558 return 0;
1559 goto do_sku;
1560 }
1561
1386 ass = codec->subsystem_id & 0xffff; 1562 ass = codec->subsystem_id & 0xffff;
1387 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) 1563 if ((ass != codec->bus->pci->subsystem_device) && (ass & 1))
1388 goto do_sku; 1564 goto do_sku;
@@ -1502,6 +1678,7 @@ struct alc_pincfg {
1502}; 1678};
1503 1679
1504struct alc_fixup { 1680struct alc_fixup {
1681 unsigned int sku;
1505 const struct alc_pincfg *pins; 1682 const struct alc_pincfg *pins;
1506 const struct hda_verb *verbs; 1683 const struct hda_verb *verbs;
1507}; 1684};
@@ -1512,12 +1689,22 @@ static void alc_pick_fixup(struct hda_codec *codec,
1512 int pre_init) 1689 int pre_init)
1513{ 1690{
1514 const struct alc_pincfg *cfg; 1691 const struct alc_pincfg *cfg;
1692 struct alc_spec *spec;
1515 1693
1516 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); 1694 quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
1517 if (!quirk) 1695 if (!quirk)
1518 return; 1696 return;
1519 fix += quirk->value; 1697 fix += quirk->value;
1520 cfg = fix->pins; 1698 cfg = fix->pins;
1699 if (pre_init && fix->sku) {
1700#ifdef CONFIG_SND_DEBUG_VERBOSE
1701 snd_printdd(KERN_INFO "hda_codec: %s: Apply sku override for %s\n",
1702 codec->chip_name, quirk->name);
1703#endif
1704 spec = codec->spec;
1705 spec->cdefine.sku_cfg = fix->sku;
1706 spec->cdefine.fixup = 1;
1707 }
1521 if (pre_init && cfg) { 1708 if (pre_init && cfg) {
1522#ifdef CONFIG_SND_DEBUG_VERBOSE 1709#ifdef CONFIG_SND_DEBUG_VERBOSE
1523 snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", 1710 snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n",
@@ -1546,6 +1733,15 @@ static int alc_read_coef_idx(struct hda_codec *codec,
1546 return val; 1733 return val;
1547} 1734}
1548 1735
1736static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
1737 unsigned int coef_val)
1738{
1739 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX,
1740 coef_idx);
1741 snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF,
1742 coef_val);
1743}
1744
1549/* set right pin controls for digital I/O */ 1745/* set right pin controls for digital I/O */
1550static void alc_auto_init_digital(struct hda_codec *codec) 1746static void alc_auto_init_digital(struct hda_codec *codec)
1551{ 1747{
@@ -1723,31 +1919,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
1723 1919
1724static void alc_automute_amp(struct hda_codec *codec) 1920static void alc_automute_amp(struct hda_codec *codec)
1725{ 1921{
1726 struct alc_spec *spec = codec->spec; 1922 alc_automute_speaker(codec, 0);
1727 unsigned int mute;
1728 hda_nid_t nid;
1729 int i;
1730
1731 spec->jack_present = 0;
1732 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
1733 nid = spec->autocfg.hp_pins[i];
1734 if (!nid)
1735 break;
1736 if (snd_hda_jack_detect(codec, nid)) {
1737 spec->jack_present = 1;
1738 break;
1739 }
1740 }
1741
1742 mute = spec->jack_present ? HDA_AMP_MUTE : 0;
1743 /* Toggle internal speakers muting */
1744 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
1745 nid = spec->autocfg.speaker_pins[i];
1746 if (!nid)
1747 break;
1748 snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
1749 HDA_AMP_MUTE, mute);
1750 }
1751} 1923}
1752 1924
1753static void alc_automute_amp_unsol_event(struct hda_codec *codec, 1925static void alc_automute_amp_unsol_event(struct hda_codec *codec,
@@ -3602,10 +3774,7 @@ static int alc_init(struct hda_codec *codec)
3602 if (spec->init_hook) 3774 if (spec->init_hook)
3603 spec->init_hook(codec); 3775 spec->init_hook(codec);
3604 3776
3605#ifdef CONFIG_SND_HDA_POWER_SAVE 3777 hda_call_check_power_status(codec, 0x01);
3606 if (codec->patch_ops.check_power_status)
3607 codec->patch_ops.check_power_status(codec, 0x01);
3608#endif
3609 return 0; 3778 return 0;
3610} 3779}
3611 3780
@@ -4001,10 +4170,7 @@ static int alc_resume(struct hda_codec *codec)
4001 codec->patch_ops.init(codec); 4170 codec->patch_ops.init(codec);
4002 snd_hda_codec_resume_amp(codec); 4171 snd_hda_codec_resume_amp(codec);
4003 snd_hda_codec_resume_cache(codec); 4172 snd_hda_codec_resume_cache(codec);
4004#ifdef CONFIG_SND_HDA_POWER_SAVE 4173 hda_call_check_power_status(codec, 0x01);
4005 if (codec->patch_ops.check_power_status)
4006 codec->patch_ops.check_power_status(codec, 0x01);
4007#endif
4008 return 0; 4174 return 0;
4009} 4175}
4010#endif 4176#endif
@@ -4729,7 +4895,7 @@ static struct snd_kcontrol_new alc880_control_templates[] = {
4729 4895
4730/* add dynamic controls */ 4896/* add dynamic controls */
4731static int add_control(struct alc_spec *spec, int type, const char *name, 4897static int add_control(struct alc_spec *spec, int type, const char *name,
4732 unsigned long val) 4898 int cidx, unsigned long val)
4733{ 4899{
4734 struct snd_kcontrol_new *knew; 4900 struct snd_kcontrol_new *knew;
4735 4901
@@ -4741,6 +4907,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
4741 knew->name = kstrdup(name, GFP_KERNEL); 4907 knew->name = kstrdup(name, GFP_KERNEL);
4742 if (!knew->name) 4908 if (!knew->name)
4743 return -ENOMEM; 4909 return -ENOMEM;
4910 knew->index = cidx;
4744 if (get_amp_nid_(val)) 4911 if (get_amp_nid_(val))
4745 knew->subdevice = HDA_SUBDEV_AMP_FLAG; 4912 knew->subdevice = HDA_SUBDEV_AMP_FLAG;
4746 knew->private_value = val; 4913 knew->private_value = val;
@@ -4749,17 +4916,21 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
4749 4916
4750static int add_control_with_pfx(struct alc_spec *spec, int type, 4917static int add_control_with_pfx(struct alc_spec *spec, int type,
4751 const char *pfx, const char *dir, 4918 const char *pfx, const char *dir,
4752 const char *sfx, unsigned long val) 4919 const char *sfx, int cidx, unsigned long val)
4753{ 4920{
4754 char name[32]; 4921 char name[32];
4755 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); 4922 snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
4756 return add_control(spec, type, name, val); 4923 return add_control(spec, type, name, cidx, val);
4757} 4924}
4758 4925
4759#define add_pb_vol_ctrl(spec, type, pfx, val) \ 4926#define add_pb_vol_ctrl(spec, type, pfx, val) \
4760 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val) 4927 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
4761#define add_pb_sw_ctrl(spec, type, pfx, val) \ 4928#define add_pb_sw_ctrl(spec, type, pfx, val) \
4762 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val) 4929 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
4930#define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \
4931 add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
4932#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
4933 add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
4763 4934
4764#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) 4935#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
4765#define alc880_fixed_pin_idx(nid) ((nid) - 0x14) 4936#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
@@ -4912,16 +5083,16 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin,
4912 5083
4913/* create input playback/capture controls for the given pin */ 5084/* create input playback/capture controls for the given pin */
4914static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, 5085static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
4915 const char *ctlname, 5086 const char *ctlname, int ctlidx,
4916 int idx, hda_nid_t mix_nid) 5087 int idx, hda_nid_t mix_nid)
4917{ 5088{
4918 int err; 5089 int err;
4919 5090
4920 err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, 5091 err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx,
4921 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 5092 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4922 if (err < 0) 5093 if (err < 0)
4923 return err; 5094 return err;
4924 err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, 5095 err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx,
4925 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 5096 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
4926 if (err < 0) 5097 if (err < 0)
4927 return err; 5098 return err;
@@ -4942,20 +5113,27 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec,
4942{ 5113{
4943 struct alc_spec *spec = codec->spec; 5114 struct alc_spec *spec = codec->spec;
4944 struct hda_input_mux *imux = &spec->private_imux[0]; 5115 struct hda_input_mux *imux = &spec->private_imux[0];
4945 int i, err, idx; 5116 int i, err, idx, type, type_idx = 0;
4946 5117
4947 for (i = 0; i < AUTO_PIN_LAST; i++) { 5118 for (i = 0; i < cfg->num_inputs; i++) {
4948 hda_nid_t pin; 5119 hda_nid_t pin;
5120 const char *label;
4949 5121
4950 pin = cfg->input_pins[i]; 5122 pin = cfg->inputs[i].pin;
4951 if (!alc_is_input_pin(codec, pin)) 5123 if (!alc_is_input_pin(codec, pin))
4952 continue; 5124 continue;
4953 5125
5126 type = cfg->inputs[i].type;
5127 if (i > 0 && type == cfg->inputs[i - 1].type)
5128 type_idx++;
5129 else
5130 type_idx = 0;
5131 label = hda_get_autocfg_input_label(codec, cfg, i);
4954 if (mixer) { 5132 if (mixer) {
4955 idx = get_connection_index(codec, mixer, pin); 5133 idx = get_connection_index(codec, mixer, pin);
4956 if (idx >= 0) { 5134 if (idx >= 0) {
4957 err = new_analog_input(spec, pin, 5135 err = new_analog_input(spec, pin,
4958 auto_pin_cfg_labels[i], 5136 label, type_idx,
4959 idx, mixer); 5137 idx, mixer);
4960 if (err < 0) 5138 if (err < 0)
4961 return err; 5139 return err;
@@ -4967,12 +5145,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec,
4967 idx = get_connection_index(codec, cap1, pin); 5145 idx = get_connection_index(codec, cap1, pin);
4968 if (idx < 0 && cap2) 5146 if (idx < 0 && cap2)
4969 idx = get_connection_index(codec, cap2, pin); 5147 idx = get_connection_index(codec, cap2, pin);
4970 if (idx >= 0) { 5148 if (idx >= 0)
4971 imux->items[imux->num_items].label = 5149 snd_hda_add_imux_item(imux, label, idx, NULL);
4972 auto_pin_cfg_labels[i];
4973 imux->items[imux->num_items].index = idx;
4974 imux->num_items++;
4975 }
4976 } 5150 }
4977 return 0; 5151 return 0;
4978} 5152}
@@ -5044,12 +5218,13 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec)
5044static void alc880_auto_init_analog_input(struct hda_codec *codec) 5218static void alc880_auto_init_analog_input(struct hda_codec *codec)
5045{ 5219{
5046 struct alc_spec *spec = codec->spec; 5220 struct alc_spec *spec = codec->spec;
5221 struct auto_pin_cfg *cfg = &spec->autocfg;
5047 int i; 5222 int i;
5048 5223
5049 for (i = 0; i < AUTO_PIN_LAST; i++) { 5224 for (i = 0; i < cfg->num_inputs; i++) {
5050 hda_nid_t nid = spec->autocfg.input_pins[i]; 5225 hda_nid_t nid = cfg->inputs[i].pin;
5051 if (alc_is_input_pin(codec, nid)) { 5226 if (alc_is_input_pin(codec, nid)) {
5052 alc_set_input_pin(codec, nid, i); 5227 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
5053 if (nid != ALC880_PIN_CD_NID && 5228 if (nid != ALC880_PIN_CD_NID &&
5054 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) 5229 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
5055 snd_hda_codec_write(codec, nid, 0, 5230 snd_hda_codec_write(codec, nid, 0,
@@ -5214,19 +5389,13 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
5214static void fixup_single_adc(struct hda_codec *codec) 5389static void fixup_single_adc(struct hda_codec *codec)
5215{ 5390{
5216 struct alc_spec *spec = codec->spec; 5391 struct alc_spec *spec = codec->spec;
5217 hda_nid_t pin = 0; 5392 struct auto_pin_cfg *cfg = &spec->autocfg;
5218 int i; 5393 int i;
5219 5394
5220 /* search for the input pin; there must be only one */ 5395 /* search for the input pin; there must be only one */
5221 for (i = 0; i < AUTO_PIN_LAST; i++) { 5396 if (cfg->num_inputs != 1)
5222 if (spec->autocfg.input_pins[i]) {
5223 pin = spec->autocfg.input_pins[i];
5224 break;
5225 }
5226 }
5227 if (!pin)
5228 return; 5397 return;
5229 i = init_capsrc_for_pin(codec, pin); 5398 i = init_capsrc_for_pin(codec, cfg->inputs[0].pin);
5230 if (i >= 0) { 5399 if (i >= 0) {
5231 /* use only this ADC */ 5400 /* use only this ADC */
5232 if (spec->capsrc_nids) 5401 if (spec->capsrc_nids)
@@ -5279,6 +5448,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
5279 int num_nids) 5448 int num_nids)
5280{ 5449{
5281 struct alc_spec *spec = codec->spec; 5450 struct alc_spec *spec = codec->spec;
5451 struct auto_pin_cfg *cfg = &spec->autocfg;
5282 int n; 5452 int n;
5283 hda_nid_t fallback_adc = 0, fallback_cap = 0; 5453 hda_nid_t fallback_adc = 0, fallback_cap = 0;
5284 5454
@@ -5304,10 +5474,8 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
5304 fallback_adc = adc; 5474 fallback_adc = adc;
5305 fallback_cap = cap; 5475 fallback_cap = cap;
5306 } 5476 }
5307 for (i = 0; i < AUTO_PIN_LAST; i++) { 5477 for (i = 0; i < cfg->num_inputs; i++) {
5308 hda_nid_t nid = spec->autocfg.input_pins[i]; 5478 hda_nid_t nid = cfg->inputs[i].pin;
5309 if (!nid)
5310 continue;
5311 for (j = 0; j < nconns; j++) { 5479 for (j = 0; j < nconns; j++) {
5312 if (conn[j] == nid) 5480 if (conn[j] == nid)
5313 break; 5481 break;
@@ -5315,7 +5483,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
5315 if (j >= nconns) 5483 if (j >= nconns)
5316 break; 5484 break;
5317 } 5485 }
5318 if (i >= AUTO_PIN_LAST) { 5486 if (i >= cfg->num_inputs) {
5319 int num_adcs = spec->num_adc_nids; 5487 int num_adcs = spec->num_adc_nids;
5320 spec->private_adc_nids[num_adcs] = adc; 5488 spec->private_adc_nids[num_adcs] = adc;
5321 spec->private_capsrc_nids[num_adcs] = cap; 5489 spec->private_capsrc_nids[num_adcs] = cap;
@@ -6683,12 +6851,13 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec)
6683static void alc260_auto_init_analog_input(struct hda_codec *codec) 6851static void alc260_auto_init_analog_input(struct hda_codec *codec)
6684{ 6852{
6685 struct alc_spec *spec = codec->spec; 6853 struct alc_spec *spec = codec->spec;
6854 struct auto_pin_cfg *cfg = &spec->autocfg;
6686 int i; 6855 int i;
6687 6856
6688 for (i = 0; i < AUTO_PIN_LAST; i++) { 6857 for (i = 0; i < cfg->num_inputs; i++) {
6689 hda_nid_t nid = spec->autocfg.input_pins[i]; 6858 hda_nid_t nid = cfg->inputs[i].pin;
6690 if (nid >= 0x12) { 6859 if (nid >= 0x12) {
6691 alc_set_input_pin(codec, nid, i); 6860 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
6692 if (nid != ALC260_PIN_CD_NID && 6861 if (nid != ALC260_PIN_CD_NID &&
6693 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) 6862 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
6694 snd_hda_codec_write(codec, nid, 0, 6863 snd_hda_codec_write(codec, nid, 0,
@@ -6810,14 +6979,12 @@ enum {
6810 PINFIX_HP_DC5750, 6979 PINFIX_HP_DC5750,
6811}; 6980};
6812 6981
6813static struct alc_pincfg alc260_hp_dc5750_pinfix[] = {
6814 { 0x11, 0x90130110 }, /* speaker */
6815 { }
6816};
6817
6818static const struct alc_fixup alc260_fixups[] = { 6982static const struct alc_fixup alc260_fixups[] = {
6819 [PINFIX_HP_DC5750] = { 6983 [PINFIX_HP_DC5750] = {
6820 .pins = alc260_hp_dc5750_pinfix 6984 .pins = (const struct alc_pincfg[]) {
6985 { 0x11, 0x90130110 }, /* speaker */
6986 { }
6987 }
6821 }, 6988 },
6822}; 6989};
6823 6990
@@ -10461,32 +10628,33 @@ static struct alc_config_preset alc882_presets[] = {
10461enum { 10628enum {
10462 PINFIX_ABIT_AW9D_MAX, 10629 PINFIX_ABIT_AW9D_MAX,
10463 PINFIX_PB_M5210, 10630 PINFIX_PB_M5210,
10464}; 10631 PINFIX_ACER_ASPIRE_7736,
10465
10466static struct alc_pincfg alc882_abit_aw9d_pinfix[] = {
10467 { 0x15, 0x01080104 }, /* side */
10468 { 0x16, 0x01011012 }, /* rear */
10469 { 0x17, 0x01016011 }, /* clfe */
10470 { }
10471};
10472
10473static const struct hda_verb pb_m5210_verbs[] = {
10474 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
10475 {}
10476}; 10632};
10477 10633
10478static const struct alc_fixup alc882_fixups[] = { 10634static const struct alc_fixup alc882_fixups[] = {
10479 [PINFIX_ABIT_AW9D_MAX] = { 10635 [PINFIX_ABIT_AW9D_MAX] = {
10480 .pins = alc882_abit_aw9d_pinfix 10636 .pins = (const struct alc_pincfg[]) {
10637 { 0x15, 0x01080104 }, /* side */
10638 { 0x16, 0x01011012 }, /* rear */
10639 { 0x17, 0x01016011 }, /* clfe */
10640 { }
10641 }
10481 }, 10642 },
10482 [PINFIX_PB_M5210] = { 10643 [PINFIX_PB_M5210] = {
10483 .verbs = pb_m5210_verbs 10644 .verbs = (const struct hda_verb[]) {
10645 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
10646 {}
10647 }
10648 },
10649 [PINFIX_ACER_ASPIRE_7736] = {
10650 .sku = ALC_FIXUP_SKU_IGNORE,
10484 }, 10651 },
10485}; 10652};
10486 10653
10487static struct snd_pci_quirk alc882_fixup_tbl[] = { 10654static struct snd_pci_quirk alc882_fixup_tbl[] = {
10488 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), 10655 SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
10489 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), 10656 SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
10657 SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
10490 {} 10658 {}
10491}; 10659};
10492 10660
@@ -10535,16 +10703,21 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
10535{ 10703{
10536 struct alc_spec *spec = codec->spec; 10704 struct alc_spec *spec = codec->spec;
10537 hda_nid_t pin, dac; 10705 hda_nid_t pin, dac;
10706 int i;
10538 10707
10539 pin = spec->autocfg.hp_pins[0]; 10708 for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
10540 if (pin) { 10709 pin = spec->autocfg.hp_pins[i];
10710 if (!pin)
10711 break;
10541 dac = spec->multiout.hp_nid; 10712 dac = spec->multiout.hp_nid;
10542 if (!dac) 10713 if (!dac)
10543 dac = spec->multiout.dac_nids[0]; /* to front */ 10714 dac = spec->multiout.dac_nids[0]; /* to front */
10544 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); 10715 alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
10545 } 10716 }
10546 pin = spec->autocfg.speaker_pins[0]; 10717 for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
10547 if (pin) { 10718 pin = spec->autocfg.speaker_pins[i];
10719 if (!pin)
10720 break;
10548 dac = spec->multiout.extra_out_nid[0]; 10721 dac = spec->multiout.extra_out_nid[0];
10549 if (!dac) 10722 if (!dac)
10550 dac = spec->multiout.dac_nids[0]; /* to front */ 10723 dac = spec->multiout.dac_nids[0]; /* to front */
@@ -10555,13 +10728,12 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec)
10555static void alc882_auto_init_analog_input(struct hda_codec *codec) 10728static void alc882_auto_init_analog_input(struct hda_codec *codec)
10556{ 10729{
10557 struct alc_spec *spec = codec->spec; 10730 struct alc_spec *spec = codec->spec;
10731 struct auto_pin_cfg *cfg = &spec->autocfg;
10558 int i; 10732 int i;
10559 10733
10560 for (i = 0; i < AUTO_PIN_LAST; i++) { 10734 for (i = 0; i < cfg->num_inputs; i++) {
10561 hda_nid_t nid = spec->autocfg.input_pins[i]; 10735 hda_nid_t nid = cfg->inputs[i].pin;
10562 if (!nid) 10736 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
10563 continue;
10564 alc_set_input_pin(codec, nid, i);
10565 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) 10737 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
10566 snd_hda_codec_write(codec, nid, 0, 10738 snd_hda_codec_write(codec, nid, 0,
10567 AC_VERB_SET_AMP_GAIN_MUTE, 10739 AC_VERB_SET_AMP_GAIN_MUTE,
@@ -10623,24 +10795,23 @@ static void alc882_auto_init_input_src(struct hda_codec *codec)
10623static int alc_auto_add_mic_boost(struct hda_codec *codec) 10795static int alc_auto_add_mic_boost(struct hda_codec *codec)
10624{ 10796{
10625 struct alc_spec *spec = codec->spec; 10797 struct alc_spec *spec = codec->spec;
10626 int err; 10798 struct auto_pin_cfg *cfg = &spec->autocfg;
10799 int i, err;
10627 hda_nid_t nid; 10800 hda_nid_t nid;
10628 10801
10629 nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; 10802 for (i = 0; i < cfg->num_inputs; i++) {
10630 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { 10803 if (cfg->inputs[i].type > AUTO_PIN_MIC)
10631 err = add_control(spec, ALC_CTL_WIDGET_VOL, 10804 break;
10632 "Mic Boost", 10805 nid = cfg->inputs[i].pin;
10633 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); 10806 if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
10634 if (err < 0) 10807 char label[32];
10635 return err; 10808 snprintf(label, sizeof(label), "%s Boost",
10636 } 10809 hda_get_autocfg_input_label(codec, cfg, i));
10637 nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; 10810 err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0,
10638 if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) {
10639 err = add_control(spec, ALC_CTL_WIDGET_VOL,
10640 "Front Mic Boost",
10641 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); 10811 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
10642 if (err < 0) 10812 if (err < 0)
10643 return err; 10813 return err;
10814 }
10644 } 10815 }
10645 return 0; 10816 return 0;
10646} 10817}
@@ -10726,8 +10897,6 @@ static int patch_alc882(struct hda_codec *codec)
10726 10897
10727 codec->spec = spec; 10898 codec->spec = spec;
10728 10899
10729 alc_auto_parse_customize_define(codec);
10730
10731 switch (codec->vendor_id) { 10900 switch (codec->vendor_id) {
10732 case 0x10ec0882: 10901 case 0x10ec0882:
10733 case 0x10ec0885: 10902 case 0x10ec0885:
@@ -10755,6 +10924,8 @@ static int patch_alc882(struct hda_codec *codec)
10755 if (board_config == ALC882_AUTO) 10924 if (board_config == ALC882_AUTO)
10756 alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1); 10925 alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1);
10757 10926
10927 alc_auto_parse_customize_define(codec);
10928
10758 if (board_config == ALC882_AUTO) { 10929 if (board_config == ALC882_AUTO) {
10759 /* automatic parse from the BIOS config */ 10930 /* automatic parse from the BIOS config */
10760 err = alc882_parse_auto_config(codec); 10931 err = alc882_parse_auto_config(codec);
@@ -10835,6 +11006,8 @@ static int patch_alc882(struct hda_codec *codec)
10835 codec->patch_ops = alc_patch_ops; 11006 codec->patch_ops = alc_patch_ops;
10836 if (board_config == ALC882_AUTO) 11007 if (board_config == ALC882_AUTO)
10837 spec->init_hook = alc882_auto_init; 11008 spec->init_hook = alc882_auto_init;
11009
11010 alc_init_jacks(codec);
10838#ifdef CONFIG_SND_HDA_POWER_SAVE 11011#ifdef CONFIG_SND_HDA_POWER_SAVE
10839 if (!spec->loopback.amplist) 11012 if (!spec->loopback.amplist)
10840 spec->loopback.amplist = alc882_loopbacks; 11013 spec->loopback.amplist = alc882_loopbacks;
@@ -11831,7 +12004,7 @@ static int alc262_check_volbit(hda_nid_t nid)
11831} 12004}
11832 12005
11833static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, 12006static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
11834 const char *pfx, int *vbits) 12007 const char *pfx, int *vbits, int idx)
11835{ 12008{
11836 unsigned long val; 12009 unsigned long val;
11837 int vbit; 12010 int vbit;
@@ -11846,11 +12019,11 @@ static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid,
11846 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); 12019 val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT);
11847 else 12020 else
11848 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); 12021 val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT);
11849 return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val); 12022 return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val);
11850} 12023}
11851 12024
11852static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, 12025static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
11853 const char *pfx) 12026 const char *pfx, int idx)
11854{ 12027{
11855 unsigned long val; 12028 unsigned long val;
11856 12029
@@ -11860,7 +12033,7 @@ static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid,
11860 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); 12033 val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT);
11861 else 12034 else
11862 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); 12035 val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
11863 return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); 12036 return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val);
11864} 12037}
11865 12038
11866/* add playback controls from the parsed DAC table */ 12039/* add playback controls from the parsed DAC table */
@@ -11869,7 +12042,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
11869{ 12042{
11870 const char *pfx; 12043 const char *pfx;
11871 int vbits; 12044 int vbits;
11872 int err; 12045 int i, err;
11873 12046
11874 spec->multiout.num_dacs = 1; /* only use one dac */ 12047 spec->multiout.num_dacs = 1; /* only use one dac */
11875 spec->multiout.dac_nids = spec->private_dac_nids; 12048 spec->multiout.dac_nids = spec->private_dac_nids;
@@ -11879,39 +12052,52 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
11879 pfx = "Master"; 12052 pfx = "Master";
11880 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) 12053 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
11881 pfx = "Speaker"; 12054 pfx = "Speaker";
12055 else if (cfg->line_out_type == AUTO_PIN_HP_OUT)
12056 pfx = "Headphone";
11882 else 12057 else
11883 pfx = "Front"; 12058 pfx = "Front";
11884 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx); 12059 for (i = 0; i < 2; i++) {
11885 if (err < 0) 12060 err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i);
11886 return err; 12061 if (err < 0)
11887 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker"); 12062 return err;
11888 if (err < 0) 12063 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
11889 return err; 12064 err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i],
11890 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone"); 12065 "Speaker", i);
11891 if (err < 0) 12066 if (err < 0)
11892 return err; 12067 return err;
12068 }
12069 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
12070 err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i],
12071 "Headphone", i);
12072 if (err < 0)
12073 return err;
12074 }
12075 }
11893 12076
11894 vbits = alc262_check_volbit(cfg->line_out_pins[0]) | 12077 vbits = alc262_check_volbit(cfg->line_out_pins[0]) |
11895 alc262_check_volbit(cfg->speaker_pins[0]) | 12078 alc262_check_volbit(cfg->speaker_pins[0]) |
11896 alc262_check_volbit(cfg->hp_pins[0]); 12079 alc262_check_volbit(cfg->hp_pins[0]);
11897 if (vbits == 1 || vbits == 2) 12080 if (vbits == 1 || vbits == 2)
11898 pfx = "Master"; /* only one mixer is used */ 12081 pfx = "Master"; /* only one mixer is used */
11899 else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
11900 pfx = "Speaker";
11901 else
11902 pfx = "Front";
11903 vbits = 0; 12082 vbits = 0;
11904 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits); 12083 for (i = 0; i < 2; i++) {
11905 if (err < 0) 12084 err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx,
11906 return err; 12085 &vbits, i);
11907 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker", 12086 if (err < 0)
11908 &vbits); 12087 return err;
11909 if (err < 0) 12088 if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
11910 return err; 12089 err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i],
11911 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone", 12090 "Speaker", &vbits, i);
11912 &vbits); 12091 if (err < 0)
11913 if (err < 0) 12092 return err;
11914 return err; 12093 }
12094 if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
12095 err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i],
12096 "Headphone", &vbits, i);
12097 if (err < 0)
12098 return err;
12099 }
12100 }
11915 return 0; 12101 return 0;
11916} 12102}
11917 12103
@@ -12199,6 +12385,35 @@ static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
12199 {} 12385 {}
12200}; 12386};
12201 12387
12388/*
12389 * Pin config fixes
12390 */
12391enum {
12392 PINFIX_FSC_H270,
12393};
12394
12395static const struct alc_fixup alc262_fixups[] = {
12396 [PINFIX_FSC_H270] = {
12397 .pins = (const struct alc_pincfg[]) {
12398 { 0x14, 0x99130110 }, /* speaker */
12399 { 0x15, 0x0221142f }, /* front HP */
12400 { 0x1b, 0x0121141f }, /* rear HP */
12401 { }
12402 }
12403 },
12404 [PINFIX_PB_M5210] = {
12405 .verbs = (const struct hda_verb[]) {
12406 { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
12407 {}
12408 }
12409 },
12410};
12411
12412static struct snd_pci_quirk alc262_fixup_tbl[] = {
12413 SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
12414 {}
12415};
12416
12202 12417
12203#ifdef CONFIG_SND_HDA_POWER_SAVE 12418#ifdef CONFIG_SND_HDA_POWER_SAVE
12204#define alc262_loopbacks alc880_loopbacks 12419#define alc262_loopbacks alc880_loopbacks
@@ -12622,6 +12837,9 @@ static int patch_alc262(struct hda_codec *codec)
12622 board_config = ALC262_AUTO; 12837 board_config = ALC262_AUTO;
12623 } 12838 }
12624 12839
12840 if (board_config == ALC262_AUTO)
12841 alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 1);
12842
12625 if (board_config == ALC262_AUTO) { 12843 if (board_config == ALC262_AUTO) {
12626 /* automatic parse from the BIOS config */ 12844 /* automatic parse from the BIOS config */
12627 err = alc262_parse_auto_config(codec); 12845 err = alc262_parse_auto_config(codec);
@@ -12690,11 +12908,16 @@ static int patch_alc262(struct hda_codec *codec)
12690 if (!spec->no_analog && has_cdefine_beep(codec)) 12908 if (!spec->no_analog && has_cdefine_beep(codec))
12691 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); 12909 set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
12692 12910
12911 if (board_config == ALC262_AUTO)
12912 alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 0);
12913
12693 spec->vmaster_nid = 0x0c; 12914 spec->vmaster_nid = 0x0c;
12694 12915
12695 codec->patch_ops = alc_patch_ops; 12916 codec->patch_ops = alc_patch_ops;
12696 if (board_config == ALC262_AUTO) 12917 if (board_config == ALC262_AUTO)
12697 spec->init_hook = alc262_auto_init; 12918 spec->init_hook = alc262_auto_init;
12919
12920 alc_init_jacks(codec);
12698#ifdef CONFIG_SND_HDA_POWER_SAVE 12921#ifdef CONFIG_SND_HDA_POWER_SAVE
12699 if (!spec->loopback.amplist) 12922 if (!spec->loopback.amplist)
12700 spec->loopback.amplist = alc262_loopbacks; 12923 spec->loopback.amplist = alc262_loopbacks;
@@ -13310,8 +13533,10 @@ static void alc268_auto_set_output_and_unmute(struct hda_codec *codec,
13310static void alc268_auto_init_multi_out(struct hda_codec *codec) 13533static void alc268_auto_init_multi_out(struct hda_codec *codec)
13311{ 13534{
13312 struct alc_spec *spec = codec->spec; 13535 struct alc_spec *spec = codec->spec;
13313 hda_nid_t nid = spec->autocfg.line_out_pins[0]; 13536 int i;
13314 if (nid) { 13537
13538 for (i = 0; i < spec->autocfg.line_outs; i++) {
13539 hda_nid_t nid = spec->autocfg.line_out_pins[i];
13315 int pin_type = get_pin_type(spec->autocfg.line_out_type); 13540 int pin_type = get_pin_type(spec->autocfg.line_out_type);
13316 alc268_auto_set_output_and_unmute(codec, nid, pin_type); 13541 alc268_auto_set_output_and_unmute(codec, nid, pin_type);
13317 } 13542 }
@@ -13321,13 +13546,19 @@ static void alc268_auto_init_hp_out(struct hda_codec *codec)
13321{ 13546{
13322 struct alc_spec *spec = codec->spec; 13547 struct alc_spec *spec = codec->spec;
13323 hda_nid_t pin; 13548 hda_nid_t pin;
13549 int i;
13324 13550
13325 pin = spec->autocfg.hp_pins[0]; 13551 for (i = 0; i < spec->autocfg.hp_outs; i++) {
13326 if (pin) 13552 pin = spec->autocfg.hp_pins[i];
13327 alc268_auto_set_output_and_unmute(codec, pin, PIN_HP); 13553 alc268_auto_set_output_and_unmute(codec, pin, PIN_HP);
13328 pin = spec->autocfg.speaker_pins[0]; 13554 }
13329 if (pin) 13555 for (i = 0; i < spec->autocfg.speaker_outs; i++) {
13556 pin = spec->autocfg.speaker_pins[i];
13330 alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT); 13557 alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT);
13558 }
13559 if (spec->autocfg.mono_out_pin)
13560 snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0,
13561 AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
13331} 13562}
13332 13563
13333static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) 13564static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec)
@@ -13766,6 +13997,8 @@ static int patch_alc268(struct hda_codec *codec)
13766 if (board_config == ALC268_AUTO) 13997 if (board_config == ALC268_AUTO)
13767 spec->init_hook = alc268_auto_init; 13998 spec->init_hook = alc268_auto_init;
13768 13999
14000 alc_init_jacks(codec);
14001
13769 return 0; 14002 return 0;
13770} 14003}
13771 14004
@@ -14132,6 +14365,7 @@ static void alc269_speaker_automute(struct hda_codec *codec)
14132 HDA_AMP_MUTE, bits); 14365 HDA_AMP_MUTE, bits);
14133 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, 14366 snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
14134 HDA_AMP_MUTE, bits); 14367 HDA_AMP_MUTE, bits);
14368 alc_report_jack(codec, nid);
14135} 14369}
14136 14370
14137/* unsolicited event for HP jack sensing */ 14371/* unsolicited event for HP jack sensing */
@@ -14386,6 +14620,13 @@ static int alc275_setup_dual_adc(struct hda_codec *codec)
14386 return 0; 14620 return 0;
14387} 14621}
14388 14622
14623/* different alc269-variants */
14624enum {
14625 ALC269_TYPE_NORMAL,
14626 ALC269_TYPE_ALC259,
14627 ALC269_TYPE_ALC271X,
14628};
14629
14389/* 14630/*
14390 * BIOS auto configuration 14631 * BIOS auto configuration
14391 */ 14632 */
@@ -14403,7 +14644,11 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
14403 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg); 14644 err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg);
14404 if (err < 0) 14645 if (err < 0)
14405 return err; 14646 return err;
14406 err = alc269_auto_create_input_ctls(codec, &spec->autocfg); 14647 if (spec->codec_variant == ALC269_TYPE_NORMAL)
14648 err = alc269_auto_create_input_ctls(codec, &spec->autocfg);
14649 else
14650 err = alc_auto_create_input_ctls(codec, &spec->autocfg, 0,
14651 0x22, 0);
14407 if (err < 0) 14652 if (err < 0)
14408 return err; 14653 return err;
14409 14654
@@ -14414,7 +14659,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
14414 if (spec->kctls.list) 14659 if (spec->kctls.list)
14415 add_mixer(spec, spec->kctls.list); 14660 add_mixer(spec, spec->kctls.list);
14416 14661
14417 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { 14662 if (spec->codec_variant != ALC269_TYPE_NORMAL) {
14418 add_verb(spec, alc269vb_init_verbs); 14663 add_verb(spec, alc269vb_init_verbs);
14419 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); 14664 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
14420 } else { 14665 } else {
@@ -14461,19 +14706,71 @@ static void alc269_auto_init(struct hda_codec *codec)
14461 alc_inithook(codec); 14706 alc_inithook(codec);
14462} 14707}
14463 14708
14709#ifdef SND_HDA_NEEDS_RESUME
14710static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
14711{
14712 int val = alc_read_coef_idx(codec, 0x04);
14713 if (power_up)
14714 val |= 1 << 11;
14715 else
14716 val &= ~(1 << 11);
14717 alc_write_coef_idx(codec, 0x04, val);
14718}
14719
14720#ifdef CONFIG_SND_HDA_POWER_SAVE
14721static int alc269_suspend(struct hda_codec *codec, pm_message_t state)
14722{
14723 struct alc_spec *spec = codec->spec;
14724
14725 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
14726 alc269_toggle_power_output(codec, 0);
14727 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
14728 alc269_toggle_power_output(codec, 0);
14729 msleep(150);
14730 }
14731
14732 alc_shutup(codec);
14733 if (spec && spec->power_hook)
14734 spec->power_hook(codec);
14735 return 0;
14736}
14737#endif /* CONFIG_SND_HDA_POWER_SAVE */
14738
14739static int alc269_resume(struct hda_codec *codec)
14740{
14741 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
14742 alc269_toggle_power_output(codec, 0);
14743 msleep(150);
14744 }
14745
14746 codec->patch_ops.init(codec);
14747
14748 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
14749 alc269_toggle_power_output(codec, 1);
14750 msleep(200);
14751 }
14752
14753 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
14754 alc269_toggle_power_output(codec, 1);
14755
14756 snd_hda_codec_resume_amp(codec);
14757 snd_hda_codec_resume_cache(codec);
14758 hda_call_check_power_status(codec, 0x01);
14759 return 0;
14760}
14761#endif /* SND_HDA_NEEDS_RESUME */
14762
14464enum { 14763enum {
14465 ALC269_FIXUP_SONY_VAIO, 14764 ALC269_FIXUP_SONY_VAIO,
14466 ALC269_FIXUP_DELL_M101Z, 14765 ALC269_FIXUP_DELL_M101Z,
14467}; 14766};
14468 14767
14469static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = {
14470 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
14471 {}
14472};
14473
14474static const struct alc_fixup alc269_fixups[] = { 14768static const struct alc_fixup alc269_fixups[] = {
14475 [ALC269_FIXUP_SONY_VAIO] = { 14769 [ALC269_FIXUP_SONY_VAIO] = {
14476 .verbs = alc269_sony_vaio_fixup_verbs 14770 .verbs = (const struct hda_verb[]) {
14771 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD},
14772 {}
14773 }
14477 }, 14774 },
14478 [ALC269_FIXUP_DELL_M101Z] = { 14775 [ALC269_FIXUP_DELL_M101Z] = {
14479 .verbs = (const struct hda_verb[]) { 14776 .verbs = (const struct hda_verb[]) {
@@ -14486,8 +14783,7 @@ static const struct alc_fixup alc269_fixups[] = {
14486}; 14783};
14487 14784
14488static struct snd_pci_quirk alc269_fixup_tbl[] = { 14785static struct snd_pci_quirk alc269_fixup_tbl[] = {
14489 SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), 14786 SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
14490 SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
14491 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), 14787 SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
14492 {} 14788 {}
14493}; 14789};
@@ -14689,12 +14985,46 @@ static struct alc_config_preset alc269_presets[] = {
14689 }, 14985 },
14690}; 14986};
14691 14987
14988static int alc269_fill_coef(struct hda_codec *codec)
14989{
14990 int val;
14991
14992 if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
14993 alc_write_coef_idx(codec, 0xf, 0x960b);
14994 alc_write_coef_idx(codec, 0xe, 0x8817);
14995 }
14996
14997 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
14998 alc_write_coef_idx(codec, 0xf, 0x960b);
14999 alc_write_coef_idx(codec, 0xe, 0x8814);
15000 }
15001
15002 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
15003 val = alc_read_coef_idx(codec, 0x04);
15004 /* Power up output pin */
15005 alc_write_coef_idx(codec, 0x04, val | (1<<11));
15006 }
15007
15008 if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
15009 val = alc_read_coef_idx(codec, 0xd);
15010 if ((val & 0x0c00) >> 10 != 0x1) {
15011 /* Capless ramp up clock control */
15012 alc_write_coef_idx(codec, 0xd, val | 1<<10);
15013 }
15014 val = alc_read_coef_idx(codec, 0x17);
15015 if ((val & 0x01c0) >> 6 != 0x4) {
15016 /* Class D power on reset */
15017 alc_write_coef_idx(codec, 0x17, val | 1<<7);
15018 }
15019 }
15020 return 0;
15021}
15022
14692static int patch_alc269(struct hda_codec *codec) 15023static int patch_alc269(struct hda_codec *codec)
14693{ 15024{
14694 struct alc_spec *spec; 15025 struct alc_spec *spec;
14695 int board_config; 15026 int board_config;
14696 int err; 15027 int err;
14697 int is_alc269vb = 0;
14698 15028
14699 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 15029 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
14700 if (spec == NULL) 15030 if (spec == NULL)
@@ -14706,14 +15036,18 @@ static int patch_alc269(struct hda_codec *codec)
14706 15036
14707 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ 15037 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){
14708 if (codec->bus->pci->subsystem_vendor == 0x1025 && 15038 if (codec->bus->pci->subsystem_vendor == 0x1025 &&
14709 spec->cdefine.platform_type == 1) 15039 spec->cdefine.platform_type == 1) {
14710 alc_codec_rename(codec, "ALC271X"); 15040 alc_codec_rename(codec, "ALC271X");
14711 else 15041 spec->codec_variant = ALC269_TYPE_ALC271X;
15042 } else {
14712 alc_codec_rename(codec, "ALC259"); 15043 alc_codec_rename(codec, "ALC259");
14713 is_alc269vb = 1; 15044 spec->codec_variant = ALC269_TYPE_ALC259;
15045 }
14714 } else 15046 } else
14715 alc_fix_pll_init(codec, 0x20, 0x04, 15); 15047 alc_fix_pll_init(codec, 0x20, 0x04, 15);
14716 15048
15049 alc269_fill_coef(codec);
15050
14717 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, 15051 board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
14718 alc269_models, 15052 alc269_models,
14719 alc269_cfg_tbl); 15053 alc269_cfg_tbl);
@@ -14770,7 +15104,7 @@ static int patch_alc269(struct hda_codec *codec)
14770 spec->stream_digital_capture = &alc269_pcm_digital_capture; 15104 spec->stream_digital_capture = &alc269_pcm_digital_capture;
14771 15105
14772 if (!spec->adc_nids) { /* wasn't filled automatically? use default */ 15106 if (!spec->adc_nids) { /* wasn't filled automatically? use default */
14773 if (!is_alc269vb) { 15107 if (spec->codec_variant != ALC269_TYPE_NORMAL) {
14774 spec->adc_nids = alc269_adc_nids; 15108 spec->adc_nids = alc269_adc_nids;
14775 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); 15109 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
14776 spec->capsrc_nids = alc269_capsrc_nids; 15110 spec->capsrc_nids = alc269_capsrc_nids;
@@ -14792,8 +15126,16 @@ static int patch_alc269(struct hda_codec *codec)
14792 spec->vmaster_nid = 0x02; 15126 spec->vmaster_nid = 0x02;
14793 15127
14794 codec->patch_ops = alc_patch_ops; 15128 codec->patch_ops = alc_patch_ops;
15129#ifdef CONFIG_SND_HDA_POWER_SAVE
15130 codec->patch_ops.suspend = alc269_suspend;
15131#endif
15132#ifdef SND_HDA_NEEDS_RESUME
15133 codec->patch_ops.resume = alc269_resume;
15134#endif
14795 if (board_config == ALC269_AUTO) 15135 if (board_config == ALC269_AUTO)
14796 spec->init_hook = alc269_auto_init; 15136 spec->init_hook = alc269_auto_init;
15137
15138 alc_init_jacks(codec);
14797#ifdef CONFIG_SND_HDA_POWER_SAVE 15139#ifdef CONFIG_SND_HDA_POWER_SAVE
14798 if (!spec->loopback.amplist) 15140 if (!spec->loopback.amplist)
14799 spec->loopback.amplist = alc269_loopbacks; 15141 spec->loopback.amplist = alc269_loopbacks;
@@ -15606,12 +15948,13 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec)
15606static void alc861_auto_init_analog_input(struct hda_codec *codec) 15948static void alc861_auto_init_analog_input(struct hda_codec *codec)
15607{ 15949{
15608 struct alc_spec *spec = codec->spec; 15950 struct alc_spec *spec = codec->spec;
15951 struct auto_pin_cfg *cfg = &spec->autocfg;
15609 int i; 15952 int i;
15610 15953
15611 for (i = 0; i < AUTO_PIN_LAST; i++) { 15954 for (i = 0; i < cfg->num_inputs; i++) {
15612 hda_nid_t nid = spec->autocfg.input_pins[i]; 15955 hda_nid_t nid = cfg->inputs[i].pin;
15613 if (nid >= 0x0c && nid <= 0x11) 15956 if (nid >= 0x0c && nid <= 0x11)
15614 alc_set_input_pin(codec, nid, i); 15957 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
15615 } 15958 }
15616} 15959}
15617 15960
@@ -15840,15 +16183,13 @@ enum {
15840 PINFIX_FSC_AMILO_PI1505, 16183 PINFIX_FSC_AMILO_PI1505,
15841}; 16184};
15842 16185
15843static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = {
15844 { 0x0b, 0x0221101f }, /* HP */
15845 { 0x0f, 0x90170310 }, /* speaker */
15846 { }
15847};
15848
15849static const struct alc_fixup alc861_fixups[] = { 16186static const struct alc_fixup alc861_fixups[] = {
15850 [PINFIX_FSC_AMILO_PI1505] = { 16187 [PINFIX_FSC_AMILO_PI1505] = {
15851 .pins = alc861_fsc_amilo_pi1505_pinfix 16188 .pins = (const struct alc_pincfg[]) {
16189 { 0x0b, 0x0221101f }, /* HP */
16190 { 0x0f, 0x90170310 }, /* speaker */
16191 { }
16192 }
15852 }, 16193 },
15853}; 16194};
15854 16195
@@ -16600,12 +16941,13 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
16600static void alc861vd_auto_init_analog_input(struct hda_codec *codec) 16941static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
16601{ 16942{
16602 struct alc_spec *spec = codec->spec; 16943 struct alc_spec *spec = codec->spec;
16944 struct auto_pin_cfg *cfg = &spec->autocfg;
16603 int i; 16945 int i;
16604 16946
16605 for (i = 0; i < AUTO_PIN_LAST; i++) { 16947 for (i = 0; i < cfg->num_inputs; i++) {
16606 hda_nid_t nid = spec->autocfg.input_pins[i]; 16948 hda_nid_t nid = cfg->inputs[i].pin;
16607 if (alc_is_input_pin(codec, nid)) { 16949 if (alc_is_input_pin(codec, nid)) {
16608 alc_set_input_pin(codec, nid, i); 16950 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
16609 if (nid != ALC861VD_PIN_CD_NID && 16951 if (nid != ALC861VD_PIN_CD_NID &&
16610 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) 16952 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
16611 snd_hda_codec_write(codec, nid, 0, 16953 snd_hda_codec_write(codec, nid, 0,
@@ -16815,16 +17157,14 @@ enum {
16815}; 17157};
16816 17158
16817/* reset GPIO1 */ 17159/* reset GPIO1 */
16818static const struct hda_verb alc660vd_fix_asus_gpio1_verbs[] = {
16819 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
16820 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
16821 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
16822 { }
16823};
16824
16825static const struct alc_fixup alc861vd_fixups[] = { 17160static const struct alc_fixup alc861vd_fixups[] = {
16826 [ALC660VD_FIX_ASUS_GPIO1] = { 17161 [ALC660VD_FIX_ASUS_GPIO1] = {
16827 .verbs = alc660vd_fix_asus_gpio1_verbs, 17162 .verbs = (const struct hda_verb[]) {
17163 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
17164 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
17165 {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
17166 { }
17167 }
16828 }, 17168 },
16829}; 17169};
16830 17170
@@ -18838,12 +19178,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec)
18838static void alc662_auto_init_analog_input(struct hda_codec *codec) 19178static void alc662_auto_init_analog_input(struct hda_codec *codec)
18839{ 19179{
18840 struct alc_spec *spec = codec->spec; 19180 struct alc_spec *spec = codec->spec;
19181 struct auto_pin_cfg *cfg = &spec->autocfg;
18841 int i; 19182 int i;
18842 19183
18843 for (i = 0; i < AUTO_PIN_LAST; i++) { 19184 for (i = 0; i < cfg->num_inputs; i++) {
18844 hda_nid_t nid = spec->autocfg.input_pins[i]; 19185 hda_nid_t nid = cfg->inputs[i].pin;
18845 if (alc_is_input_pin(codec, nid)) { 19186 if (alc_is_input_pin(codec, nid)) {
18846 alc_set_input_pin(codec, nid, i); 19187 alc_set_input_pin(codec, nid, cfg->inputs[i].type);
18847 if (nid != ALC662_PIN_CD_NID && 19188 if (nid != ALC662_PIN_CD_NID &&
18848 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) 19189 (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP))
18849 snd_hda_codec_write(codec, nid, 0, 19190 snd_hda_codec_write(codec, nid, 0,
@@ -18935,10 +19276,40 @@ static void alc662_auto_init(struct hda_codec *codec)
18935 alc_inithook(codec); 19276 alc_inithook(codec);
18936} 19277}
18937 19278
19279enum {
19280 ALC662_FIXUP_ASPIRE,
19281 ALC662_FIXUP_IDEAPAD,
19282};
19283
19284static const struct alc_fixup alc662_fixups[] = {
19285 [ALC662_FIXUP_ASPIRE] = {
19286 .pins = (const struct alc_pincfg[]) {
19287 { 0x15, 0x99130112 }, /* subwoofer */
19288 { }
19289 }
19290 },
19291 [ALC662_FIXUP_IDEAPAD] = {
19292 .pins = (const struct alc_pincfg[]) {
19293 { 0x17, 0x99130112 }, /* subwoofer */
19294 { }
19295 }
19296 },
19297};
19298
19299static struct snd_pci_quirk alc662_fixup_tbl[] = {
19300 SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
19301 SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
19302 SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
19303 {}
19304};
19305
19306
19307
18938static int patch_alc662(struct hda_codec *codec) 19308static int patch_alc662(struct hda_codec *codec)
18939{ 19309{
18940 struct alc_spec *spec; 19310 struct alc_spec *spec;
18941 int err, board_config; 19311 int err, board_config;
19312 int coef;
18942 19313
18943 spec = kzalloc(sizeof(*spec), GFP_KERNEL); 19314 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
18944 if (!spec) 19315 if (!spec)
@@ -18950,12 +19321,15 @@ static int patch_alc662(struct hda_codec *codec)
18950 19321
18951 alc_fix_pll_init(codec, 0x20, 0x04, 15); 19322 alc_fix_pll_init(codec, 0x20, 0x04, 15);
18952 19323
18953 if (alc_read_coef_idx(codec, 0) == 0x8020) 19324 coef = alc_read_coef_idx(codec, 0);
19325 if (coef == 0x8020 || coef == 0x8011)
18954 alc_codec_rename(codec, "ALC661"); 19326 alc_codec_rename(codec, "ALC661");
18955 else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) && 19327 else if (coef & (1 << 14) &&
18956 codec->bus->pci->subsystem_vendor == 0x1025 && 19328 codec->bus->pci->subsystem_vendor == 0x1025 &&
18957 spec->cdefine.platform_type == 1) 19329 spec->cdefine.platform_type == 1)
18958 alc_codec_rename(codec, "ALC272X"); 19330 alc_codec_rename(codec, "ALC272X");
19331 else if (coef == 0x4011)
19332 alc_codec_rename(codec, "ALC656");
18959 19333
18960 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, 19334 board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST,
18961 alc662_models, 19335 alc662_models,
@@ -18967,6 +19341,7 @@ static int patch_alc662(struct hda_codec *codec)
18967 } 19341 }
18968 19342
18969 if (board_config == ALC662_AUTO) { 19343 if (board_config == ALC662_AUTO) {
19344 alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 1);
18970 /* automatic parse from the BIOS config */ 19345 /* automatic parse from the BIOS config */
18971 err = alc662_parse_auto_config(codec); 19346 err = alc662_parse_auto_config(codec);
18972 if (err < 0) { 19347 if (err < 0) {
@@ -19025,8 +19400,13 @@ static int patch_alc662(struct hda_codec *codec)
19025 spec->vmaster_nid = 0x02; 19400 spec->vmaster_nid = 0x02;
19026 19401
19027 codec->patch_ops = alc_patch_ops; 19402 codec->patch_ops = alc_patch_ops;
19028 if (board_config == ALC662_AUTO) 19403 if (board_config == ALC662_AUTO) {
19029 spec->init_hook = alc662_auto_init; 19404 spec->init_hook = alc662_auto_init;
19405 alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 0);
19406 }
19407
19408 alc_init_jacks(codec);
19409
19030#ifdef CONFIG_SND_HDA_POWER_SAVE 19410#ifdef CONFIG_SND_HDA_POWER_SAVE
19031 if (!spec->loopback.amplist) 19411 if (!spec->loopback.amplist)
19032 spec->loopback.amplist = alc662_loopbacks; 19412 spec->loopback.amplist = alc662_loopbacks;
@@ -19070,6 +19450,39 @@ static hda_nid_t alc680_adc_nids[3] = {
19070/* 19450/*
19071 * Analog capture ADC cgange 19451 * Analog capture ADC cgange
19072 */ 19452 */
19453static void alc680_rec_autoswitch(struct hda_codec *codec)
19454{
19455 struct alc_spec *spec = codec->spec;
19456 struct auto_pin_cfg *cfg = &spec->autocfg;
19457 int pin_found = 0;
19458 int type_found = AUTO_PIN_LAST;
19459 hda_nid_t nid;
19460 int i;
19461
19462 for (i = 0; i < cfg->num_inputs; i++) {
19463 nid = cfg->inputs[i].pin;
19464 if (!(snd_hda_query_pin_caps(codec, nid) &
19465 AC_PINCAP_PRES_DETECT))
19466 continue;
19467 if (snd_hda_jack_detect(codec, nid)) {
19468 if (cfg->inputs[i].type < type_found) {
19469 type_found = cfg->inputs[i].type;
19470 pin_found = nid;
19471 }
19472 }
19473 }
19474
19475 nid = 0x07;
19476 if (pin_found)
19477 snd_hda_get_connections(codec, pin_found, &nid, 1);
19478
19479 if (nid != spec->cur_adc)
19480 __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
19481 spec->cur_adc = nid;
19482 snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0,
19483 spec->cur_adc_format);
19484}
19485
19073static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 19486static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
19074 struct hda_codec *codec, 19487 struct hda_codec *codec,
19075 unsigned int stream_tag, 19488 unsigned int stream_tag,
@@ -19077,24 +19490,12 @@ static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
19077 struct snd_pcm_substream *substream) 19490 struct snd_pcm_substream *substream)
19078{ 19491{
19079 struct alc_spec *spec = codec->spec; 19492 struct alc_spec *spec = codec->spec;
19080 struct auto_pin_cfg *cfg = &spec->autocfg;
19081 unsigned int pre_mic, pre_line;
19082
19083 pre_mic = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]);
19084 pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]);
19085 19493
19494 spec->cur_adc = 0x07;
19086 spec->cur_adc_stream_tag = stream_tag; 19495 spec->cur_adc_stream_tag = stream_tag;
19087 spec->cur_adc_format = format; 19496 spec->cur_adc_format = format;
19088 19497
19089 if (pre_mic || pre_line) { 19498 alc680_rec_autoswitch(codec);
19090 if (pre_mic)
19091 snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0,
19092 format);
19093 else
19094 snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0,
19095 format);
19096 } else
19097 snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format);
19098 return 0; 19499 return 0;
19099} 19500}
19100 19501
@@ -19180,6 +19581,7 @@ static struct hda_verb alc680_init_verbs[] = {
19180 19581
19181 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, 19582 {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
19182 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, 19583 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
19584 {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN},
19183 19585
19184 { } 19586 { }
19185}; 19587};
@@ -19192,25 +19594,11 @@ static void alc680_base_setup(struct hda_codec *codec)
19192 spec->autocfg.hp_pins[0] = 0x16; 19594 spec->autocfg.hp_pins[0] = 0x16;
19193 spec->autocfg.speaker_pins[0] = 0x14; 19595 spec->autocfg.speaker_pins[0] = 0x14;
19194 spec->autocfg.speaker_pins[1] = 0x15; 19596 spec->autocfg.speaker_pins[1] = 0x15;
19195 spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18; 19597 spec->autocfg.num_inputs = 2;
19196 spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19; 19598 spec->autocfg.inputs[0].pin = 0x18;
19197} 19599 spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
19198 19600 spec->autocfg.inputs[1].pin = 0x19;
19199static void alc680_rec_autoswitch(struct hda_codec *codec) 19601 spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
19200{
19201 struct alc_spec *spec = codec->spec;
19202 struct auto_pin_cfg *cfg = &spec->autocfg;
19203 unsigned int present;
19204 hda_nid_t new_adc;
19205
19206 present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]);
19207
19208 new_adc = present ? 0x8 : 0x7;
19209 __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1);
19210 snd_hda_codec_setup_stream(codec, new_adc,
19211 spec->cur_adc_stream_tag, 0,
19212 spec->cur_adc_format);
19213
19214} 19602}
19215 19603
19216static void alc680_unsol_event(struct hda_codec *codec, 19604static void alc680_unsol_event(struct hda_codec *codec,
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index c16c5ba0fda0..82ebeb9544fe 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -32,6 +32,7 @@
32#include <sound/core.h> 32#include <sound/core.h>
33#include <sound/asoundef.h> 33#include <sound/asoundef.h>
34#include <sound/jack.h> 34#include <sound/jack.h>
35#include <sound/tlv.h>
35#include "hda_codec.h" 36#include "hda_codec.h"
36#include "hda_local.h" 37#include "hda_local.h"
37#include "hda_beep.h" 38#include "hda_beep.h"
@@ -263,6 +264,7 @@ struct sigmatel_spec {
263 264
264 struct sigmatel_mic_route ext_mic; 265 struct sigmatel_mic_route ext_mic;
265 struct sigmatel_mic_route int_mic; 266 struct sigmatel_mic_route int_mic;
267 struct sigmatel_mic_route dock_mic;
266 268
267 const char **spdif_labels; 269 const char **spdif_labels;
268 270
@@ -382,6 +384,11 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = {
382 0x03, 0x0c, 0x20, 0x40, 384 0x03, 0x0c, 0x20, 0x40,
383}; 385};
384 386
387#define STAC92HD83XXX_NUM_DMICS 2
388static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
389 0x11, 0x20, 0
390};
391
385#define STAC92HD83XXX_NUM_CAPS 2 392#define STAC92HD83XXX_NUM_CAPS 2
386static unsigned long stac92hd83xxx_capvols[] = { 393static unsigned long stac92hd83xxx_capvols[] = {
387 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), 394 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
@@ -986,7 +993,7 @@ static struct hda_verb stac9205_core_init[] = {
986 } 993 }
987 994
988static struct snd_kcontrol_new stac9200_mixer[] = { 995static struct snd_kcontrol_new stac9200_mixer[] = {
989 HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), 996 HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
990 HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), 997 HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
991 HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), 998 HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
992 HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), 999 HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
@@ -1014,7 +1021,7 @@ static struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
1014}; 1021};
1015 1022
1016static struct snd_kcontrol_new stac925x_mixer[] = { 1023static struct snd_kcontrol_new stac925x_mixer[] = {
1017 HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), 1024 HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
1018 HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), 1025 HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
1019 { } /* end */ 1026 { } /* end */
1020}; 1027};
@@ -1105,9 +1112,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1105 struct hda_input_mux *smux = &spec->private_smux; 1112 struct hda_input_mux *smux = &spec->private_smux;
1106 /* check for mute support on SPDIF out */ 1113 /* check for mute support on SPDIF out */
1107 if (wcaps & AC_WCAP_OUT_AMP) { 1114 if (wcaps & AC_WCAP_OUT_AMP) {
1108 smux->items[smux->num_items].label = "Off"; 1115 snd_hda_add_imux_item(smux, "Off", 0, NULL);
1109 smux->items[smux->num_items].index = 0;
1110 smux->num_items++;
1111 spec->spdif_mute = 1; 1116 spec->spdif_mute = 1;
1112 } 1117 }
1113 stac_smux_mixer.count = spec->num_smuxes; 1118 stac_smux_mixer.count = spec->num_smuxes;
@@ -1140,6 +1145,8 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1140 HDA_OUTPUT, vmaster_tlv); 1145 HDA_OUTPUT, vmaster_tlv);
1141 /* correct volume offset */ 1146 /* correct volume offset */
1142 vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; 1147 vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
1148 /* minimum value is actually mute */
1149 vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
1143 err = snd_hda_add_vmaster(codec, "Master Playback Volume", 1150 err = snd_hda_add_vmaster(codec, "Master Playback Volume",
1144 vmaster_tlv, slave_vols); 1151 vmaster_tlv, slave_vols);
1145 if (err < 0) 1152 if (err < 0)
@@ -1180,14 +1187,11 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1180 if (err < 0) 1187 if (err < 0)
1181 return err; 1188 return err;
1182 } 1189 }
1183 for (i = 0; i < AUTO_PIN_LAST; i++) { 1190 for (i = 0; i < cfg->num_inputs; i++) {
1184 nid = cfg->input_pins[i]; 1191 nid = cfg->inputs[i].pin;
1185 if (nid) { 1192 err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE);
1186 err = stac92xx_add_jack(codec, nid, 1193 if (err < 0)
1187 SND_JACK_MICROPHONE); 1194 return err;
1188 if (err < 0)
1189 return err;
1190 }
1191 } 1195 }
1192 1196
1193 return 0; 1197 return 0;
@@ -2779,7 +2783,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
2779 struct sigmatel_spec *spec = codec->spec; 2783 struct sigmatel_spec *spec = codec->spec;
2780 char name[22]; 2784 char name[22];
2781 2785
2782 if (!((get_defcfg_connect(def_conf)) & AC_JACK_PORT_FIXED)) { 2786 if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
2783 if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD 2787 if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD
2784 && nid == spec->line_switch) 2788 && nid == spec->line_switch)
2785 control = STAC_CTL_WIDGET_IO_SWITCH; 2789 control = STAC_CTL_WIDGET_IO_SWITCH;
@@ -2791,7 +2795,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
2791 } 2795 }
2792 2796
2793 if (control) { 2797 if (control) {
2794 strcpy(name, auto_pin_cfg_labels[idx]); 2798 strcpy(name, hda_get_input_pin_label(codec, nid, 1));
2795 return stac92xx_add_control(codec->spec, control, 2799 return stac92xx_add_control(codec->spec, control,
2796 strcat(name, " Jack Mode"), nid); 2800 strcat(name, " Jack Mode"), nid);
2797 } 2801 }
@@ -2823,41 +2827,49 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec)
2823 struct auto_pin_cfg *cfg = &spec->autocfg; 2827 struct auto_pin_cfg *cfg = &spec->autocfg;
2824 hda_nid_t nid; 2828 hda_nid_t nid;
2825 unsigned int pincap; 2829 unsigned int pincap;
2830 int i;
2826 2831
2827 if (cfg->line_out_type != AUTO_PIN_LINE_OUT) 2832 if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
2828 return 0; 2833 return 0;
2829 nid = cfg->input_pins[AUTO_PIN_LINE]; 2834 for (i = 0; i < cfg->num_inputs; i++) {
2830 pincap = snd_hda_query_pin_caps(codec, nid); 2835 if (cfg->inputs[i].type == AUTO_PIN_LINE_IN) {
2831 if (pincap & AC_PINCAP_OUT) 2836 nid = cfg->inputs[i].pin;
2832 return nid; 2837 pincap = snd_hda_query_pin_caps(codec, nid);
2838 if (pincap & AC_PINCAP_OUT)
2839 return nid;
2840 }
2841 }
2833 return 0; 2842 return 0;
2834} 2843}
2835 2844
2845static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid);
2846
2836/* check whether the mic-input can be used as line-out */ 2847/* check whether the mic-input can be used as line-out */
2837static hda_nid_t check_mic_out_switch(struct hda_codec *codec) 2848static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac)
2838{ 2849{
2839 struct sigmatel_spec *spec = codec->spec; 2850 struct sigmatel_spec *spec = codec->spec;
2840 struct auto_pin_cfg *cfg = &spec->autocfg; 2851 struct auto_pin_cfg *cfg = &spec->autocfg;
2841 unsigned int def_conf, pincap; 2852 unsigned int def_conf, pincap;
2842 unsigned int mic_pin; 2853 int i;
2843 2854
2855 *dac = 0;
2844 if (cfg->line_out_type != AUTO_PIN_LINE_OUT) 2856 if (cfg->line_out_type != AUTO_PIN_LINE_OUT)
2845 return 0; 2857 return 0;
2846 mic_pin = AUTO_PIN_MIC; 2858 for (i = 0; i < cfg->num_inputs; i++) {
2847 for (;;) { 2859 hda_nid_t nid = cfg->inputs[i].pin;
2848 hda_nid_t nid = cfg->input_pins[mic_pin]; 2860 if (cfg->inputs[i].type != AUTO_PIN_MIC)
2861 continue;
2849 def_conf = snd_hda_codec_get_pincfg(codec, nid); 2862 def_conf = snd_hda_codec_get_pincfg(codec, nid);
2850 /* some laptops have an internal analog microphone 2863 /* some laptops have an internal analog microphone
2851 * which can't be used as a output */ 2864 * which can't be used as a output */
2852 if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { 2865 if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) {
2853 pincap = snd_hda_query_pin_caps(codec, nid); 2866 pincap = snd_hda_query_pin_caps(codec, nid);
2854 if (pincap & AC_PINCAP_OUT) 2867 if (pincap & AC_PINCAP_OUT) {
2855 return nid; 2868 *dac = get_unassigned_dac(codec, nid);
2869 if (*dac)
2870 return nid;
2871 }
2856 } 2872 }
2857 if (mic_pin == AUTO_PIN_MIC)
2858 mic_pin = AUTO_PIN_FRONT_MIC;
2859 else
2860 break;
2861 } 2873 }
2862 return 0; 2874 return 0;
2863} 2875}
@@ -3004,17 +3016,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec)
3004 } 3016 }
3005 } 3017 }
3006 /* add mic as output */ 3018 /* add mic as output */
3007 nid = check_mic_out_switch(codec); 3019 nid = check_mic_out_switch(codec, &dac);
3008 if (nid) { 3020 if (nid && dac) {
3009 dac = get_unassigned_dac(codec, nid); 3021 snd_printdd("STAC: Add mic-in 0x%x as output %d\n",
3010 if (dac) { 3022 nid, cfg->line_outs);
3011 snd_printdd("STAC: Add mic-in 0x%x as output %d\n", 3023 cfg->line_out_pins[cfg->line_outs] = nid;
3012 nid, cfg->line_outs); 3024 cfg->line_outs++;
3013 cfg->line_out_pins[cfg->line_outs] = nid; 3025 spec->mic_switch = nid;
3014 cfg->line_outs++; 3026 add_spec_dacs(spec, dac);
3015 spec->mic_switch = nid;
3016 add_spec_dacs(spec, dac);
3017 }
3018 } 3027 }
3019 3028
3020 snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", 3029 snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
@@ -3204,13 +3213,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec,
3204 return err; 3213 return err;
3205 } 3214 }
3206 3215
3207 for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) { 3216 for (idx = 0; idx < cfg->num_inputs; idx++) {
3208 nid = cfg->input_pins[idx]; 3217 if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
3209 if (nid) { 3218 break;
3210 err = stac92xx_add_jack_mode_control(codec, nid, idx); 3219 nid = cfg->inputs[idx].pin;
3211 if (err < 0) 3220 err = stac92xx_add_jack_mode_control(codec, nid, idx);
3212 return err; 3221 if (err < 0)
3213 } 3222 return err;
3214 } 3223 }
3215 3224
3216 return 0; 3225 return 0;
@@ -3256,12 +3265,9 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec)
3256 if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) 3265 if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels))
3257 return -EINVAL; 3266 return -EINVAL;
3258 3267
3259 for (i = 0; i < num_cons; i++) { 3268 for (i = 0; i < num_cons; i++)
3260 mono_mux->items[mono_mux->num_items].label = 3269 snd_hda_add_imux_item(mono_mux, stac92xx_mono_labels[i], i,
3261 stac92xx_mono_labels[i]; 3270 NULL);
3262 mono_mux->items[mono_mux->num_items].index = i;
3263 mono_mux->num_items++;
3264 }
3265 3271
3266 return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, 3272 return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX,
3267 "Mono Mux", spec->mono_nid); 3273 "Mono Mux", spec->mono_nid);
@@ -3386,11 +3392,8 @@ static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec)
3386 if (!labels) 3392 if (!labels)
3387 labels = stac92xx_spdif_labels; 3393 labels = stac92xx_spdif_labels;
3388 3394
3389 for (i = 0; i < num_cons; i++) { 3395 for (i = 0; i < num_cons; i++)
3390 spdif_mux->items[spdif_mux->num_items].label = labels[i]; 3396 snd_hda_add_imux_item(spdif_mux, labels[i], i, NULL);
3391 spdif_mux->items[spdif_mux->num_items].index = i;
3392 spdif_mux->num_items++;
3393 }
3394 3397
3395 return 0; 3398 return 0;
3396} 3399}
@@ -3417,7 +3420,7 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
3417/* create a volume assigned to the given pin (only if supported) */ 3420/* create a volume assigned to the given pin (only if supported) */
3418/* return 1 if the volume control is created */ 3421/* return 1 if the volume control is created */
3419static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, 3422static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid,
3420 const char *label, int direction) 3423 const char *label, int idx, int direction)
3421{ 3424{
3422 unsigned int caps, nums; 3425 unsigned int caps, nums;
3423 char name[32]; 3426 char name[32];
@@ -3434,8 +3437,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid,
3434 if (!nums) 3437 if (!nums)
3435 return 0; 3438 return 0;
3436 snprintf(name, sizeof(name), "%s Capture Volume", label); 3439 snprintf(name, sizeof(name), "%s Capture Volume", label);
3437 err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name, 3440 err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name,
3438 HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); 3441 HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction));
3439 if (err < 0) 3442 if (err < 0)
3440 return err; 3443 return err;
3441 return 1; 3444 return 1;
@@ -3448,27 +3451,14 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
3448 struct sigmatel_spec *spec = codec->spec; 3451 struct sigmatel_spec *spec = codec->spec;
3449 struct hda_input_mux *imux = &spec->private_imux; 3452 struct hda_input_mux *imux = &spec->private_imux;
3450 struct hda_input_mux *dimux = &spec->private_dimux; 3453 struct hda_input_mux *dimux = &spec->private_dimux;
3451 int err, i, active_mics; 3454 int err, i;
3452 unsigned int def_conf; 3455 unsigned int def_conf;
3453 3456
3454 dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; 3457 snd_hda_add_imux_item(dimux, stac92xx_dmic_labels[0], 0, NULL);
3455 dimux->items[dimux->num_items].index = 0;
3456 dimux->num_items++;
3457
3458 active_mics = 0;
3459 for (i = 0; i < spec->num_dmics; i++) {
3460 /* check the validity: sometimes it's a dead vendor-spec node */
3461 if (get_wcaps_type(get_wcaps(codec, spec->dmic_nids[i]))
3462 != AC_WID_PIN)
3463 continue;
3464 def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]);
3465 if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
3466 active_mics++;
3467 }
3468 3458
3469 for (i = 0; i < spec->num_dmics; i++) { 3459 for (i = 0; i < spec->num_dmics; i++) {
3470 hda_nid_t nid; 3460 hda_nid_t nid;
3471 int index; 3461 int index, type_idx;
3472 const char *label; 3462 const char *label;
3473 3463
3474 nid = spec->dmic_nids[i]; 3464 nid = spec->dmic_nids[i];
@@ -3482,28 +3472,23 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
3482 if (index < 0) 3472 if (index < 0)
3483 continue; 3473 continue;
3484 3474
3485 if (active_mics == 1) 3475 label = hda_get_input_pin_label(codec, nid, 1);
3486 label = "Digital Mic"; 3476 snd_hda_add_imux_item(dimux, label, index, &type_idx);
3487 else
3488 label = stac92xx_dmic_labels[dimux->num_items];
3489 3477
3490 err = create_elem_capture_vol(codec, nid, label, HDA_INPUT); 3478 err = create_elem_capture_vol(codec, nid, label, type_idx,
3479 HDA_INPUT);
3491 if (err < 0) 3480 if (err < 0)
3492 return err; 3481 return err;
3493 if (!err) { 3482 if (!err) {
3494 err = create_elem_capture_vol(codec, nid, label, 3483 err = create_elem_capture_vol(codec, nid, label,
3495 HDA_OUTPUT); 3484 type_idx, HDA_OUTPUT);
3496 if (err < 0) 3485 if (err < 0)
3497 return err; 3486 return err;
3498 } 3487 }
3499 3488
3500 dimux->items[dimux->num_items].label = label;
3501 dimux->items[dimux->num_items].index = index;
3502 dimux->num_items++;
3503 if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) { 3489 if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) {
3504 imux->items[imux->num_items].label = label; 3490 snd_hda_add_imux_item(imux, label, index, NULL);
3505 imux->items[imux->num_items].index = index; 3491 spec->num_analog_muxes++;
3506 imux->num_items++;
3507 } 3492 }
3508 } 3493 }
3509 3494
@@ -3511,20 +3496,27 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
3511} 3496}
3512 3497
3513static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, 3498static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
3514 hda_nid_t *fixed, hda_nid_t *ext) 3499 hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock)
3515{ 3500{
3516 unsigned int cfg; 3501 unsigned int cfg;
3517 3502
3518 if (!nid) 3503 if (!nid)
3519 return 0; 3504 return 0;
3520 cfg = snd_hda_codec_get_pincfg(codec, nid); 3505 cfg = snd_hda_codec_get_pincfg(codec, nid);
3521 switch (get_defcfg_connect(cfg)) { 3506 switch (snd_hda_get_input_pin_attr(cfg)) {
3522 case AC_JACK_PORT_FIXED: 3507 case INPUT_PIN_ATTR_INT:
3523 if (*fixed) 3508 if (*fixed)
3524 return 1; /* already occupied */ 3509 return 1; /* already occupied */
3525 *fixed = nid; 3510 *fixed = nid;
3526 break; 3511 break;
3527 case AC_JACK_PORT_COMPLEX: 3512 case INPUT_PIN_ATTR_UNUSED:
3513 break;
3514 case INPUT_PIN_ATTR_DOCK:
3515 if (*dock)
3516 return 1; /* already occupied */
3517 *dock = nid;
3518 break;
3519 default:
3528 if (*ext) 3520 if (*ext)
3529 return 1; /* already occupied */ 3521 return 1; /* already occupied */
3530 *ext = nid; 3522 *ext = nid;
@@ -3542,10 +3534,13 @@ static int set_mic_route(struct hda_codec *codec,
3542 int i; 3534 int i;
3543 3535
3544 mic->pin = pin; 3536 mic->pin = pin;
3545 for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) 3537 if (pin == 0)
3546 if (pin == cfg->input_pins[i]) 3538 return 0;
3539 for (i = 0; i < cfg->num_inputs; i++) {
3540 if (pin == cfg->inputs[i].pin)
3547 break; 3541 break;
3548 if (i <= AUTO_PIN_FRONT_MIC) { 3542 }
3543 if (i < cfg->num_inputs && cfg->inputs[i].type == AUTO_PIN_MIC) {
3549 /* analog pin */ 3544 /* analog pin */
3550 i = get_connection_index(codec, spec->mux_nids[0], pin); 3545 i = get_connection_index(codec, spec->mux_nids[0], pin);
3551 if (i < 0) 3546 if (i < 0)
@@ -3576,26 +3571,29 @@ static int stac_check_auto_mic(struct hda_codec *codec)
3576{ 3571{
3577 struct sigmatel_spec *spec = codec->spec; 3572 struct sigmatel_spec *spec = codec->spec;
3578 struct auto_pin_cfg *cfg = &spec->autocfg; 3573 struct auto_pin_cfg *cfg = &spec->autocfg;
3579 hda_nid_t fixed, ext; 3574 hda_nid_t fixed, ext, dock;
3580 int i; 3575 int i;
3581 3576
3582 for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) { 3577 for (i = 0; i < cfg->num_inputs; i++) {
3583 if (cfg->input_pins[i]) 3578 if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
3584 return 0; /* must be exclusively mics */ 3579 return 0; /* must be exclusively mics */
3585 } 3580 }
3586 fixed = ext = 0; 3581 fixed = ext = dock = 0;
3587 for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) 3582 for (i = 0; i < cfg->num_inputs; i++)
3588 if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext)) 3583 if (check_mic_pin(codec, cfg->inputs[i].pin,
3584 &fixed, &ext, &dock))
3589 return 0; 3585 return 0;
3590 for (i = 0; i < spec->num_dmics; i++) 3586 for (i = 0; i < spec->num_dmics; i++)
3591 if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext)) 3587 if (check_mic_pin(codec, spec->dmic_nids[i],
3588 &fixed, &ext, &dock))
3592 return 0; 3589 return 0;
3593 if (!fixed || !ext) 3590 if (!fixed && !ext && !dock)
3594 return 0; 3591 return 0; /* no input to switch */
3595 if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) 3592 if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
3596 return 0; /* no unsol support */ 3593 return 0; /* no unsol support */
3597 if (set_mic_route(codec, &spec->ext_mic, ext) || 3594 if (set_mic_route(codec, &spec->ext_mic, ext) ||
3598 set_mic_route(codec, &spec->int_mic, fixed)) 3595 set_mic_route(codec, &spec->int_mic, fixed) ||
3596 set_mic_route(codec, &spec->dock_mic, dock))
3599 return 0; /* something is wrong */ 3597 return 0; /* something is wrong */
3600 return 1; 3598 return 1;
3601} 3599}
@@ -3606,13 +3604,12 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
3606 struct sigmatel_spec *spec = codec->spec; 3604 struct sigmatel_spec *spec = codec->spec;
3607 struct hda_input_mux *imux = &spec->private_imux; 3605 struct hda_input_mux *imux = &spec->private_imux;
3608 int i, j; 3606 int i, j;
3607 const char *label;
3609 3608
3610 for (i = 0; i < AUTO_PIN_LAST; i++) { 3609 for (i = 0; i < cfg->num_inputs; i++) {
3611 hda_nid_t nid = cfg->input_pins[i]; 3610 hda_nid_t nid = cfg->inputs[i].pin;
3612 int index, err; 3611 int index, err, type_idx;
3613 3612
3614 if (!nid)
3615 continue;
3616 index = -1; 3613 index = -1;
3617 for (j = 0; j < spec->num_muxes; j++) { 3614 for (j = 0; j < spec->num_muxes; j++) {
3618 index = get_connection_index(codec, spec->mux_nids[j], 3615 index = get_connection_index(codec, spec->mux_nids[j],
@@ -3623,15 +3620,14 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
3623 if (index < 0) 3620 if (index < 0)
3624 continue; 3621 continue;
3625 3622
3623 label = hda_get_autocfg_input_label(codec, cfg, i);
3624 snd_hda_add_imux_item(imux, label, index, &type_idx);
3625
3626 err = create_elem_capture_vol(codec, nid, 3626 err = create_elem_capture_vol(codec, nid,
3627 auto_pin_cfg_labels[i], 3627 label, type_idx,
3628 HDA_INPUT); 3628 HDA_INPUT);
3629 if (err < 0) 3629 if (err < 0)
3630 return err; 3630 return err;
3631
3632 imux->items[imux->num_items].label = auto_pin_cfg_labels[i];
3633 imux->items[imux->num_items].index = index;
3634 imux->num_items++;
3635 } 3631 }
3636 spec->num_analog_muxes = imux->num_items; 3632 spec->num_analog_muxes = imux->num_items;
3637 3633
@@ -4305,38 +4301,38 @@ static int stac92xx_init(struct hda_codec *codec)
4305 AC_VERB_SET_CONNECT_SEL, 0); 4301 AC_VERB_SET_CONNECT_SEL, 0);
4306 if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) 4302 if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
4307 stac_issue_unsol_event(codec, spec->ext_mic.pin); 4303 stac_issue_unsol_event(codec, spec->ext_mic.pin);
4308 } 4304 if (enable_pin_detect(codec, spec->dock_mic.pin,
4309 for (i = 0; i < AUTO_PIN_LAST; i++) { 4305 STAC_MIC_EVENT))
4310 hda_nid_t nid = cfg->input_pins[i]; 4306 stac_issue_unsol_event(codec, spec->dock_mic.pin);
4311 if (nid) { 4307 }
4312 unsigned int pinctl, conf; 4308 for (i = 0; i < cfg->num_inputs; i++) {
4313 if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { 4309 hda_nid_t nid = cfg->inputs[i].pin;
4314 /* for mic pins, force to initialize */ 4310 int type = cfg->inputs[i].type;
4315 pinctl = stac92xx_get_default_vref(codec, nid); 4311 unsigned int pinctl, conf;
4312 if (type == AUTO_PIN_MIC) {
4313 /* for mic pins, force to initialize */
4314 pinctl = stac92xx_get_default_vref(codec, nid);
4315 pinctl |= AC_PINCTL_IN_EN;
4316 stac92xx_auto_set_pinctl(codec, nid, pinctl);
4317 } else {
4318 pinctl = snd_hda_codec_read(codec, nid, 0,
4319 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4320 /* if PINCTL already set then skip */
4321 /* Also, if both INPUT and OUTPUT are set,
4322 * it must be a BIOS bug; need to override, too
4323 */
4324 if (!(pinctl & AC_PINCTL_IN_EN) ||
4325 (pinctl & AC_PINCTL_OUT_EN)) {
4326 pinctl &= ~AC_PINCTL_OUT_EN;
4316 pinctl |= AC_PINCTL_IN_EN; 4327 pinctl |= AC_PINCTL_IN_EN;
4317 stac92xx_auto_set_pinctl(codec, nid, pinctl); 4328 stac92xx_auto_set_pinctl(codec, nid, pinctl);
4318 } else {
4319 pinctl = snd_hda_codec_read(codec, nid, 0,
4320 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
4321 /* if PINCTL already set then skip */
4322 /* Also, if both INPUT and OUTPUT are set,
4323 * it must be a BIOS bug; need to override, too
4324 */
4325 if (!(pinctl & AC_PINCTL_IN_EN) ||
4326 (pinctl & AC_PINCTL_OUT_EN)) {
4327 pinctl &= ~AC_PINCTL_OUT_EN;
4328 pinctl |= AC_PINCTL_IN_EN;
4329 stac92xx_auto_set_pinctl(codec, nid,
4330 pinctl);
4331 }
4332 }
4333 conf = snd_hda_codec_get_pincfg(codec, nid);
4334 if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
4335 if (enable_pin_detect(codec, nid,
4336 STAC_INSERT_EVENT))
4337 stac_issue_unsol_event(codec, nid);
4338 } 4329 }
4339 } 4330 }
4331 conf = snd_hda_codec_get_pincfg(codec, nid);
4332 if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
4333 if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT))
4334 stac_issue_unsol_event(codec, nid);
4335 }
4340 } 4336 }
4341 for (i = 0; i < spec->num_dmics; i++) 4337 for (i = 0; i < spec->num_dmics; i++)
4342 stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], 4338 stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
@@ -4383,11 +4379,9 @@ static int stac92xx_init(struct hda_codec *codec)
4383 stac_issue_unsol_event(codec, nid); 4379 stac_issue_unsol_event(codec, nid);
4384 } 4380 }
4385 4381
4386#ifdef CONFIG_SND_HDA_POWER_SAVE
4387 /* sync mute LED */ 4382 /* sync mute LED */
4388 if (spec->gpio_led && codec->patch_ops.check_power_status) 4383 if (spec->gpio_led)
4389 codec->patch_ops.check_power_status(codec, 0x01); 4384 hda_call_check_power_status(codec, 0x01);
4390#endif
4391 if (spec->dac_list) 4385 if (spec->dac_list)
4392 stac92xx_power_down(codec); 4386 stac92xx_power_down(codec);
4393 return 0; 4387 return 0;
@@ -4688,6 +4682,36 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
4688 } 4682 }
4689} 4683}
4690 4684
4685/* get the pin connection (fixed, none, etc) */
4686static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
4687{
4688 struct sigmatel_spec *spec = codec->spec;
4689 unsigned int cfg;
4690
4691 cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
4692 return get_defcfg_connect(cfg);
4693}
4694
4695static int stac92xx_connected_ports(struct hda_codec *codec,
4696 hda_nid_t *nids, int num_nids)
4697{
4698 struct sigmatel_spec *spec = codec->spec;
4699 int idx, num;
4700 unsigned int def_conf;
4701
4702 for (num = 0; num < num_nids; num++) {
4703 for (idx = 0; idx < spec->num_pins; idx++)
4704 if (spec->pin_nids[idx] == nids[num])
4705 break;
4706 if (idx >= spec->num_pins)
4707 break;
4708 def_conf = stac_get_defcfg_connect(codec, idx);
4709 if (def_conf == AC_JACK_PORT_NONE)
4710 break;
4711 }
4712 return num;
4713}
4714
4691static void stac92xx_mic_detect(struct hda_codec *codec) 4715static void stac92xx_mic_detect(struct hda_codec *codec)
4692{ 4716{
4693 struct sigmatel_spec *spec = codec->spec; 4717 struct sigmatel_spec *spec = codec->spec;
@@ -4695,6 +4719,8 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
4695 4719
4696 if (get_pin_presence(codec, spec->ext_mic.pin)) 4720 if (get_pin_presence(codec, spec->ext_mic.pin))
4697 mic = &spec->ext_mic; 4721 mic = &spec->ext_mic;
4722 else if (get_pin_presence(codec, spec->dock_mic.pin))
4723 mic = &spec->dock_mic;
4698 else 4724 else
4699 mic = &spec->int_mic; 4725 mic = &spec->int_mic;
4700 if (mic->dmux_idx >= 0) 4726 if (mic->dmux_idx >= 0)
@@ -4937,11 +4963,9 @@ static int stac92xx_resume(struct hda_codec *codec)
4937 stac_issue_unsol_event(codec, 4963 stac_issue_unsol_event(codec,
4938 spec->autocfg.line_out_pins[0]); 4964 spec->autocfg.line_out_pins[0]);
4939 } 4965 }
4940#ifdef CONFIG_SND_HDA_POWER_SAVE
4941 /* sync mute LED */ 4966 /* sync mute LED */
4942 if (spec->gpio_led && codec->patch_ops.check_power_status) 4967 if (spec->gpio_led)
4943 codec->patch_ops.check_power_status(codec, 0x01); 4968 hda_call_check_power_status(codec, 0x01);
4944#endif
4945 return 0; 4969 return 0;
4946} 4970}
4947 4971
@@ -5313,11 +5337,16 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
5313 if (spec == NULL) 5337 if (spec == NULL)
5314 return -ENOMEM; 5338 return -ENOMEM;
5315 5339
5340 /* reset pin power-down; Windows may leave these bits after reboot */
5341 snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0);
5342 snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0);
5316 codec->no_trigger_sense = 1; 5343 codec->no_trigger_sense = 1;
5317 codec->spec = spec; 5344 codec->spec = spec;
5318 spec->linear_tone_beep = 1; 5345 spec->linear_tone_beep = 1;
5319 codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; 5346 codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
5320 spec->digbeep_nid = 0x21; 5347 spec->digbeep_nid = 0x21;
5348 spec->dmic_nids = stac92hd83xxx_dmic_nids;
5349 spec->dmux_nids = stac92hd83xxx_mux_nids;
5321 spec->mux_nids = stac92hd83xxx_mux_nids; 5350 spec->mux_nids = stac92hd83xxx_mux_nids;
5322 spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); 5351 spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids);
5323 spec->adc_nids = stac92hd83xxx_adc_nids; 5352 spec->adc_nids = stac92hd83xxx_adc_nids;
@@ -5363,9 +5392,13 @@ again:
5363 case 0x111d76d4: 5392 case 0x111d76d4:
5364 case 0x111d7605: 5393 case 0x111d7605:
5365 case 0x111d76d5: 5394 case 0x111d76d5:
5395 case 0x111d76e7:
5366 if (spec->board_config == STAC_92HD83XXX_PWR_REF) 5396 if (spec->board_config == STAC_92HD83XXX_PWR_REF)
5367 break; 5397 break;
5368 spec->num_pwrs = 0; 5398 spec->num_pwrs = 0;
5399 spec->num_dmics = stac92xx_connected_ports(codec,
5400 stac92hd83xxx_dmic_nids,
5401 STAC92HD83XXX_NUM_DMICS);
5369 break; 5402 break;
5370 } 5403 }
5371 5404
@@ -5424,36 +5457,6 @@ again:
5424 return 0; 5457 return 0;
5425} 5458}
5426 5459
5427/* get the pin connection (fixed, none, etc) */
5428static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
5429{
5430 struct sigmatel_spec *spec = codec->spec;
5431 unsigned int cfg;
5432
5433 cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
5434 return get_defcfg_connect(cfg);
5435}
5436
5437static int stac92hd71bxx_connected_ports(struct hda_codec *codec,
5438 hda_nid_t *nids, int num_nids)
5439{
5440 struct sigmatel_spec *spec = codec->spec;
5441 int idx, num;
5442 unsigned int def_conf;
5443
5444 for (num = 0; num < num_nids; num++) {
5445 for (idx = 0; idx < spec->num_pins; idx++)
5446 if (spec->pin_nids[idx] == nids[num])
5447 break;
5448 if (idx >= spec->num_pins)
5449 break;
5450 def_conf = stac_get_defcfg_connect(codec, idx);
5451 if (def_conf == AC_JACK_PORT_NONE)
5452 break;
5453 }
5454 return num;
5455}
5456
5457static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, 5460static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec,
5458 hda_nid_t dig0pin) 5461 hda_nid_t dig0pin)
5459{ 5462{
@@ -5592,7 +5595,7 @@ again:
5592 case 0x111d76b5: 5595 case 0x111d76b5:
5593 spec->init = stac92hd71bxx_core_init; 5596 spec->init = stac92hd71bxx_core_init;
5594 codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; 5597 codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
5595 spec->num_dmics = stac92hd71bxx_connected_ports(codec, 5598 spec->num_dmics = stac92xx_connected_ports(codec,
5596 stac92hd71bxx_dmic_nids, 5599 stac92hd71bxx_dmic_nids,
5597 STAC92HD71BXX_NUM_DMICS); 5600 STAC92HD71BXX_NUM_DMICS);
5598 break; 5601 break;
@@ -5624,7 +5627,7 @@ again:
5624 snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); 5627 snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
5625 snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); 5628 snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
5626 stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; 5629 stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0;
5627 spec->num_dmics = stac92hd71bxx_connected_ports(codec, 5630 spec->num_dmics = stac92xx_connected_ports(codec,
5628 stac92hd71bxx_dmic_nids, 5631 stac92hd71bxx_dmic_nids,
5629 STAC92HD71BXX_NUM_DMICS - 1); 5632 STAC92HD71BXX_NUM_DMICS - 1);
5630 break; 5633 break;
@@ -5638,7 +5641,7 @@ again:
5638 default: 5641 default:
5639 spec->init = stac92hd71bxx_core_init; 5642 spec->init = stac92hd71bxx_core_init;
5640 codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; 5643 codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
5641 spec->num_dmics = stac92hd71bxx_connected_ports(codec, 5644 spec->num_dmics = stac92xx_connected_ports(codec,
5642 stac92hd71bxx_dmic_nids, 5645 stac92hd71bxx_dmic_nids,
5643 STAC92HD71BXX_NUM_DMICS); 5646 STAC92HD71BXX_NUM_DMICS);
5644 break; 5647 break;
@@ -6320,6 +6323,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
6320 { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, 6323 { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx },
6321 { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, 6324 { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx },
6322 { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, 6325 { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx },
6326 { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx},
6327 { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx},
6323 {} /* terminator */ 6328 {} /* terminator */
6324}; 6329};
6325 6330
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index ae3acb2b42d1..d1c3f8defc48 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -444,8 +444,8 @@ static hda_nid_t vt1812_adc_nids[2] = {
444 444
445 445
446/* add dynamic controls */ 446/* add dynamic controls */
447static int via_add_control(struct via_spec *spec, int type, const char *name, 447static int __via_add_control(struct via_spec *spec, int type, const char *name,
448 unsigned long val) 448 int idx, unsigned long val)
449{ 449{
450 struct snd_kcontrol_new *knew; 450 struct snd_kcontrol_new *knew;
451 451
@@ -463,6 +463,9 @@ static int via_add_control(struct via_spec *spec, int type, const char *name,
463 return 0; 463 return 0;
464} 464}
465 465
466#define via_add_control(spec, type, name, val) \
467 __via_add_control(spec, type, name, 0, val)
468
466static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, 469static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec,
467 struct snd_kcontrol_new *tmpl) 470 struct snd_kcontrol_new *tmpl)
468{ 471{
@@ -494,18 +497,18 @@ static void via_free_kctls(struct hda_codec *codec)
494 497
495/* create input playback/capture controls for the given pin */ 498/* create input playback/capture controls for the given pin */
496static int via_new_analog_input(struct via_spec *spec, const char *ctlname, 499static int via_new_analog_input(struct via_spec *spec, const char *ctlname,
497 int idx, int mix_nid) 500 int type_idx, int idx, int mix_nid)
498{ 501{
499 char name[32]; 502 char name[32];
500 int err; 503 int err;
501 504
502 sprintf(name, "%s Playback Volume", ctlname); 505 sprintf(name, "%s Playback Volume", ctlname);
503 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, 506 err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx,
504 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 507 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
505 if (err < 0) 508 if (err < 0)
506 return err; 509 return err;
507 sprintf(name, "%s Playback Switch", ctlname); 510 sprintf(name, "%s Playback Switch", ctlname);
508 err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, 511 err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx,
509 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); 512 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
510 if (err < 0) 513 if (err < 0)
511 return err; 514 return err;
@@ -557,17 +560,15 @@ static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
557static void via_auto_init_analog_input(struct hda_codec *codec) 560static void via_auto_init_analog_input(struct hda_codec *codec)
558{ 561{
559 struct via_spec *spec = codec->spec; 562 struct via_spec *spec = codec->spec;
563 const struct auto_pin_cfg *cfg = &spec->autocfg;
560 unsigned int ctl; 564 unsigned int ctl;
561 int i; 565 int i;
562 566
563 for (i = 0; i < AUTO_PIN_LAST; i++) { 567 for (i = 0; i < cfg->num_inputs; i++) {
564 hda_nid_t nid = spec->autocfg.input_pins[i]; 568 hda_nid_t nid = cfg->inputs[i].pin;
565 if (!nid)
566 continue;
567
568 if (spec->smart51_enabled && is_smart51_pins(spec, nid)) 569 if (spec->smart51_enabled && is_smart51_pins(spec, nid))
569 ctl = PIN_OUT; 570 ctl = PIN_OUT;
570 else if (i <= AUTO_PIN_FRONT_MIC) 571 else if (i == AUTO_PIN_MIC)
571 ctl = PIN_VREF50; 572 ctl = PIN_VREF50;
572 else 573 else
573 ctl = PIN_IN; 574 ctl = PIN_IN;
@@ -1322,15 +1323,14 @@ static void mute_aa_path(struct hda_codec *codec, int mute)
1322} 1323}
1323static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) 1324static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin)
1324{ 1325{
1325 int res = 0; 1326 const struct auto_pin_cfg *cfg = &spec->autocfg;
1326 int index; 1327 int i;
1327 for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) { 1328
1328 if (pin == spec->autocfg.input_pins[index]) { 1329 for (i = 0; i < cfg->num_inputs; i++) {
1329 res = 1; 1330 if (pin == cfg->inputs[i].pin)
1330 break; 1331 return cfg->inputs[i].type <= AUTO_PIN_LINE_IN;
1331 }
1332 } 1332 }
1333 return res; 1333 return 0;
1334} 1334}
1335 1335
1336static int via_smart51_info(struct snd_kcontrol *kcontrol, 1336static int via_smart51_info(struct snd_kcontrol *kcontrol,
@@ -1348,25 +1348,21 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol,
1348{ 1348{
1349 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1349 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1350 struct via_spec *spec = codec->spec; 1350 struct via_spec *spec = codec->spec;
1351 int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; 1351 const struct auto_pin_cfg *cfg = &spec->autocfg;
1352 int on = 1; 1352 int on = 1;
1353 int i; 1353 int i;
1354 1354
1355 for (i = 0; i < ARRAY_SIZE(index); i++) { 1355 for (i = 0; i < cfg->num_inputs; i++) {
1356 hda_nid_t nid = spec->autocfg.input_pins[index[i]]; 1356 hda_nid_t nid = cfg->inputs[i].pin;
1357 if (nid) { 1357 int ctl = snd_hda_codec_read(codec, nid, 0,
1358 int ctl = 1358 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1359 snd_hda_codec_read(codec, nid, 0, 1359 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1360 AC_VERB_GET_PIN_WIDGET_CONTROL, 1360 continue;
1361 0); 1361 if (cfg->inputs[i].type == AUTO_PIN_MIC &&
1362 if (i == AUTO_PIN_FRONT_MIC 1362 spec->hp_independent_mode && spec->codec_type != VT1718S)
1363 && spec->hp_independent_mode 1363 continue; /* ignore FMic for independent HP */
1364 && spec->codec_type != VT1718S) 1364 if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN))
1365 continue; /* ignore FMic for independent HP */ 1365 on = 0;
1366 if (ctl & AC_PINCTL_IN_EN
1367 && !(ctl & AC_PINCTL_OUT_EN))
1368 on = 0;
1369 }
1370 } 1366 }
1371 *ucontrol->value.integer.value = on; 1367 *ucontrol->value.integer.value = on;
1372 return 0; 1368 return 0;
@@ -1377,36 +1373,38 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
1377{ 1373{
1378 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 1374 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1379 struct via_spec *spec = codec->spec; 1375 struct via_spec *spec = codec->spec;
1376 const struct auto_pin_cfg *cfg = &spec->autocfg;
1380 int out_in = *ucontrol->value.integer.value 1377 int out_in = *ucontrol->value.integer.value
1381 ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; 1378 ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN;
1382 int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
1383 int i; 1379 int i;
1384 1380
1385 for (i = 0; i < ARRAY_SIZE(index); i++) { 1381 for (i = 0; i < cfg->num_inputs; i++) {
1386 hda_nid_t nid = spec->autocfg.input_pins[index[i]]; 1382 hda_nid_t nid = cfg->inputs[i].pin;
1387 if (i == AUTO_PIN_FRONT_MIC 1383 unsigned int parm;
1388 && spec->hp_independent_mode 1384
1389 && spec->codec_type != VT1718S) 1385 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1386 continue;
1387 if (cfg->inputs[i].type == AUTO_PIN_MIC &&
1388 spec->hp_independent_mode && spec->codec_type != VT1718S)
1390 continue; /* don't retask FMic for independent HP */ 1389 continue; /* don't retask FMic for independent HP */
1391 if (nid) { 1390
1392 unsigned int parm = snd_hda_codec_read( 1391 parm = snd_hda_codec_read(codec, nid, 0,
1393 codec, nid, 0, 1392 AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
1394 AC_VERB_GET_PIN_WIDGET_CONTROL, 0); 1393 parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
1395 parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); 1394 parm |= out_in;
1396 parm |= out_in; 1395 snd_hda_codec_write(codec, nid, 0,
1397 snd_hda_codec_write(codec, nid, 0, 1396 AC_VERB_SET_PIN_WIDGET_CONTROL,
1398 AC_VERB_SET_PIN_WIDGET_CONTROL, 1397 parm);
1399 parm); 1398 if (out_in == AC_PINCTL_OUT_EN) {
1400 if (out_in == AC_PINCTL_OUT_EN) { 1399 mute_aa_path(codec, 1);
1401 mute_aa_path(codec, 1); 1400 notify_aa_path_ctls(codec);
1402 notify_aa_path_ctls(codec); 1401 }
1403 } 1402 if (spec->codec_type == VT1718S) {
1404 if (spec->codec_type == VT1718S) 1403 snd_hda_codec_amp_stereo(
1405 snd_hda_codec_amp_stereo(
1406 codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, 1404 codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE,
1407 HDA_AMP_UNMUTE); 1405 HDA_AMP_UNMUTE);
1408 } 1406 }
1409 if (i == AUTO_PIN_FRONT_MIC) { 1407 if (cfg->inputs[i].type == AUTO_PIN_MIC) {
1410 if (spec->codec_type == VT1708S 1408 if (spec->codec_type == VT1708S
1411 || spec->codec_type == VT1716S) { 1409 || spec->codec_type == VT1716S) {
1412 /* input = index 1 (AOW3) */ 1410 /* input = index 1 (AOW3) */
@@ -1442,7 +1440,7 @@ static struct snd_kcontrol_new via_smart51_mixer[2] = {
1442static int via_smart51_build(struct via_spec *spec) 1440static int via_smart51_build(struct via_spec *spec)
1443{ 1441{
1444 struct snd_kcontrol_new *knew; 1442 struct snd_kcontrol_new *knew;
1445 int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; 1443 const struct auto_pin_cfg *cfg = &spec->autocfg;
1446 hda_nid_t nid; 1444 hda_nid_t nid;
1447 int i; 1445 int i;
1448 1446
@@ -1450,13 +1448,14 @@ static int via_smart51_build(struct via_spec *spec)
1450 if (knew == NULL) 1448 if (knew == NULL)
1451 return -ENOMEM; 1449 return -ENOMEM;
1452 1450
1453 for (i = 0; i < ARRAY_SIZE(index); i++) { 1451 for (i = 0; i < cfg->num_inputs; i++) {
1454 nid = spec->autocfg.input_pins[index[i]]; 1452 nid = cfg->inputs[i].pin;
1455 if (nid) { 1453 if (cfg->inputs[i].type <= AUTO_PIN_LINE_IN) {
1456 knew = via_clone_control(spec, &via_smart51_mixer[1]); 1454 knew = via_clone_control(spec, &via_smart51_mixer[1]);
1457 if (knew == NULL) 1455 if (knew == NULL)
1458 return -ENOMEM; 1456 return -ENOMEM;
1459 knew->subdevice = nid; 1457 knew->subdevice = nid;
1458 break;
1460 } 1459 }
1461 } 1460 }
1462 1461
@@ -2375,13 +2374,8 @@ static void create_hp_imux(struct via_spec *spec)
2375 static const char *texts[] = { "OFF", "ON", NULL}; 2374 static const char *texts[] = { "OFF", "ON", NULL};
2376 2375
2377 /* for hp mode select */ 2376 /* for hp mode select */
2378 i = 0; 2377 for (i = 0; texts[i]; i++)
2379 while (texts[i] != NULL) { 2378 snd_hda_add_imux_item(imux, texts[i], i, NULL);
2380 imux->items[imux->num_items].label = texts[i];
2381 imux->items[imux->num_items].index = i;
2382 imux->num_items++;
2383 i++;
2384 }
2385 2379
2386 spec->hp_mux = &spec->private_imux[1]; 2380 spec->hp_mux = &spec->private_imux[1];
2387} 2381}
@@ -2413,51 +2407,53 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
2413} 2407}
2414 2408
2415/* create playback/capture controls for input pins */ 2409/* create playback/capture controls for input pins */
2416static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, 2410static int vt_auto_create_analog_input_ctls(struct hda_codec *codec,
2417 const struct auto_pin_cfg *cfg) 2411 const struct auto_pin_cfg *cfg,
2412 hda_nid_t cap_nid,
2413 hda_nid_t pin_idxs[], int num_idxs)
2418{ 2414{
2419 static char *labels[] = { 2415 struct via_spec *spec = codec->spec;
2420 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
2421 };
2422 struct hda_input_mux *imux = &spec->private_imux[0]; 2416 struct hda_input_mux *imux = &spec->private_imux[0];
2423 int i, err, idx = 0; 2417 int i, err, idx, type, type_idx = 0;
2424 2418
2425 /* for internal loopback recording select */ 2419 /* for internal loopback recording select */
2426 imux->items[imux->num_items].label = "Stereo Mixer"; 2420 for (idx = 0; idx < num_idxs; idx++) {
2427 imux->items[imux->num_items].index = idx; 2421 if (pin_idxs[idx] == 0xff) {
2428 imux->num_items++; 2422 snd_hda_add_imux_item(imux, "Stereo Mixer", idx, NULL);
2429
2430 for (i = 0; i < AUTO_PIN_LAST; i++) {
2431 if (!cfg->input_pins[i])
2432 continue;
2433
2434 switch (cfg->input_pins[i]) {
2435 case 0x1d: /* Mic */
2436 idx = 2;
2437 break;
2438
2439 case 0x1e: /* Line In */
2440 idx = 3;
2441 break;
2442
2443 case 0x21: /* Front Mic */
2444 idx = 4;
2445 break;
2446
2447 case 0x24: /* CD */
2448 idx = 1;
2449 break; 2423 break;
2450 } 2424 }
2451 err = via_new_analog_input(spec, labels[i], idx, 0x17); 2425 }
2426
2427 for (i = 0; i < cfg->num_inputs; i++) {
2428 const char *label;
2429 type = cfg->inputs[i].type;
2430 for (idx = 0; idx < num_idxs; idx++)
2431 if (pin_idxs[idx] == cfg->inputs[i].pin)
2432 break;
2433 if (idx >= num_idxs)
2434 continue;
2435 if (i > 0 && type == cfg->inputs[i - 1].type)
2436 type_idx++;
2437 else
2438 type_idx = 0;
2439 label = hda_get_autocfg_input_label(codec, cfg, i);
2440 err = via_new_analog_input(spec, label, type_idx, idx, cap_nid);
2452 if (err < 0) 2441 if (err < 0)
2453 return err; 2442 return err;
2454 imux->items[imux->num_items].label = labels[i]; 2443 snd_hda_add_imux_item(imux, label, idx, NULL);
2455 imux->items[imux->num_items].index = idx;
2456 imux->num_items++;
2457 } 2444 }
2458 return 0; 2445 return 0;
2459} 2446}
2460 2447
2448/* create playback/capture controls for input pins */
2449static int vt1708_auto_create_analog_input_ctls(struct hda_codec *codec,
2450 const struct auto_pin_cfg *cfg)
2451{
2452 static hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 };
2453 return vt_auto_create_analog_input_ctls(codec, cfg, 0x17, pin_idxs,
2454 ARRAY_SIZE(pin_idxs));
2455}
2456
2461#ifdef CONFIG_SND_HDA_POWER_SAVE 2457#ifdef CONFIG_SND_HDA_POWER_SAVE
2462static struct hda_amp_list vt1708_loopbacks[] = { 2458static struct hda_amp_list vt1708_loopbacks[] = {
2463 { 0x17, HDA_INPUT, 1 }, 2459 { 0x17, HDA_INPUT, 1 },
@@ -2554,7 +2550,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
2554 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 2550 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
2555 if (err < 0) 2551 if (err < 0)
2556 return err; 2552 return err;
2557 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg); 2553 err = vt1708_auto_create_analog_input_ctls(codec, &spec->autocfg);
2558 if (err < 0) 2554 if (err < 0)
2559 return err; 2555 return err;
2560 /* add jack detect on/off control */ 2556 /* add jack detect on/off control */
@@ -3021,49 +3017,12 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
3021} 3017}
3022 3018
3023/* create playback/capture controls for input pins */ 3019/* create playback/capture controls for input pins */
3024static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec, 3020static int vt1709_auto_create_analog_input_ctls(struct hda_codec *codec,
3025 const struct auto_pin_cfg *cfg) 3021 const struct auto_pin_cfg *cfg)
3026{ 3022{
3027 static char *labels[] = { 3023 static hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 };
3028 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL 3024 return vt_auto_create_analog_input_ctls(codec, cfg, 0x18, pin_idxs,
3029 }; 3025 ARRAY_SIZE(pin_idxs));
3030 struct hda_input_mux *imux = &spec->private_imux[0];
3031 int i, err, idx = 0;
3032
3033 /* for internal loopback recording select */
3034 imux->items[imux->num_items].label = "Stereo Mixer";
3035 imux->items[imux->num_items].index = idx;
3036 imux->num_items++;
3037
3038 for (i = 0; i < AUTO_PIN_LAST; i++) {
3039 if (!cfg->input_pins[i])
3040 continue;
3041
3042 switch (cfg->input_pins[i]) {
3043 case 0x1d: /* Mic */
3044 idx = 2;
3045 break;
3046
3047 case 0x1e: /* Line In */
3048 idx = 3;
3049 break;
3050
3051 case 0x21: /* Front Mic */
3052 idx = 4;
3053 break;
3054
3055 case 0x23: /* CD */
3056 idx = 1;
3057 break;
3058 }
3059 err = via_new_analog_input(spec, labels[i], idx, 0x18);
3060 if (err < 0)
3061 return err;
3062 imux->items[imux->num_items].label = labels[i];
3063 imux->items[imux->num_items].index = idx;
3064 imux->num_items++;
3065 }
3066 return 0;
3067} 3026}
3068 3027
3069static int vt1709_parse_auto_config(struct hda_codec *codec) 3028static int vt1709_parse_auto_config(struct hda_codec *codec)
@@ -3086,7 +3045,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
3086 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 3045 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
3087 if (err < 0) 3046 if (err < 0)
3088 return err; 3047 return err;
3089 err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg); 3048 err = vt1709_auto_create_analog_input_ctls(codec, &spec->autocfg);
3090 if (err < 0) 3049 if (err < 0)
3091 return err; 3050 return err;
3092 3051
@@ -3588,49 +3547,12 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
3588} 3547}
3589 3548
3590/* create playback/capture controls for input pins */ 3549/* create playback/capture controls for input pins */
3591static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec, 3550static int vt1708B_auto_create_analog_input_ctls(struct hda_codec *codec,
3592 const struct auto_pin_cfg *cfg) 3551 const struct auto_pin_cfg *cfg)
3593{ 3552{
3594 static char *labels[] = { 3553 static hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e };
3595 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL 3554 return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
3596 }; 3555 ARRAY_SIZE(pin_idxs));
3597 struct hda_input_mux *imux = &spec->private_imux[0];
3598 int i, err, idx = 0;
3599
3600 /* for internal loopback recording select */
3601 imux->items[imux->num_items].label = "Stereo Mixer";
3602 imux->items[imux->num_items].index = idx;
3603 imux->num_items++;
3604
3605 for (i = 0; i < AUTO_PIN_LAST; i++) {
3606 if (!cfg->input_pins[i])
3607 continue;
3608
3609 switch (cfg->input_pins[i]) {
3610 case 0x1a: /* Mic */
3611 idx = 2;
3612 break;
3613
3614 case 0x1b: /* Line In */
3615 idx = 3;
3616 break;
3617
3618 case 0x1e: /* Front Mic */
3619 idx = 4;
3620 break;
3621
3622 case 0x1f: /* CD */
3623 idx = 1;
3624 break;
3625 }
3626 err = via_new_analog_input(spec, labels[i], idx, 0x16);
3627 if (err < 0)
3628 return err;
3629 imux->items[imux->num_items].label = labels[i];
3630 imux->items[imux->num_items].index = idx;
3631 imux->num_items++;
3632 }
3633 return 0;
3634} 3556}
3635 3557
3636static int vt1708B_parse_auto_config(struct hda_codec *codec) 3558static int vt1708B_parse_auto_config(struct hda_codec *codec)
@@ -3653,7 +3575,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
3653 err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 3575 err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
3654 if (err < 0) 3576 if (err < 0)
3655 return err; 3577 return err;
3656 err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg); 3578 err = vt1708B_auto_create_analog_input_ctls(codec, &spec->autocfg);
3657 if (err < 0) 3579 if (err < 0)
3658 return err; 3580 return err;
3659 3581
@@ -4061,49 +3983,12 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
4061} 3983}
4062 3984
4063/* create playback/capture controls for input pins */ 3985/* create playback/capture controls for input pins */
4064static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec, 3986static int vt1708S_auto_create_analog_input_ctls(struct hda_codec *codec,
4065 const struct auto_pin_cfg *cfg) 3987 const struct auto_pin_cfg *cfg)
4066{ 3988{
4067 static char *labels[] = { 3989 static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
4068 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL 3990 return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
4069 }; 3991 ARRAY_SIZE(pin_idxs));
4070 struct hda_input_mux *imux = &spec->private_imux[0];
4071 int i, err, idx = 0;
4072
4073 /* for internal loopback recording select */
4074 imux->items[imux->num_items].label = "Stereo Mixer";
4075 imux->items[imux->num_items].index = 5;
4076 imux->num_items++;
4077
4078 for (i = 0; i < AUTO_PIN_LAST; i++) {
4079 if (!cfg->input_pins[i])
4080 continue;
4081
4082 switch (cfg->input_pins[i]) {
4083 case 0x1a: /* Mic */
4084 idx = 2;
4085 break;
4086
4087 case 0x1b: /* Line In */
4088 idx = 3;
4089 break;
4090
4091 case 0x1e: /* Front Mic */
4092 idx = 4;
4093 break;
4094
4095 case 0x1f: /* CD */
4096 idx = 1;
4097 break;
4098 }
4099 err = via_new_analog_input(spec, labels[i], idx, 0x16);
4100 if (err < 0)
4101 return err;
4102 imux->items[imux->num_items].label = labels[i];
4103 imux->items[imux->num_items].index = idx-1;
4104 imux->num_items++;
4105 }
4106 return 0;
4107} 3992}
4108 3993
4109/* fill out digital output widgets; one for master and one for slave outputs */ 3994/* fill out digital output widgets; one for master and one for slave outputs */
@@ -4151,7 +4036,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
4151 err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 4036 err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
4152 if (err < 0) 4037 if (err < 0)
4153 return err; 4038 return err;
4154 err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg); 4039 err = vt1708S_auto_create_analog_input_ctls(codec, &spec->autocfg);
4155 if (err < 0) 4040 if (err < 0)
4156 return err; 4041 return err;
4157 4042
@@ -4441,58 +4326,20 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
4441 imux = &spec->private_imux[1]; 4326 imux = &spec->private_imux[1];
4442 4327
4443 /* for hp mode select */ 4328 /* for hp mode select */
4444 i = 0; 4329 for (i = 0; texts[i]; i++)
4445 while (texts[i] != NULL) { 4330 snd_hda_add_imux_item(imux, texts[i], i, NULL);
4446 imux->items[imux->num_items].label = texts[i];
4447 imux->items[imux->num_items].index = i;
4448 imux->num_items++;
4449 i++;
4450 }
4451 4331
4452 spec->hp_mux = &spec->private_imux[1]; 4332 spec->hp_mux = &spec->private_imux[1];
4453 return 0; 4333 return 0;
4454} 4334}
4455 4335
4456/* create playback/capture controls for input pins */ 4336/* create playback/capture controls for input pins */
4457static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec, 4337static int vt1702_auto_create_analog_input_ctls(struct hda_codec *codec,
4458 const struct auto_pin_cfg *cfg) 4338 const struct auto_pin_cfg *cfg)
4459{ 4339{
4460 static char *labels[] = { 4340 static hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff };
4461 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL 4341 return vt_auto_create_analog_input_ctls(codec, cfg, 0x1a, pin_idxs,
4462 }; 4342 ARRAY_SIZE(pin_idxs));
4463 struct hda_input_mux *imux = &spec->private_imux[0];
4464 int i, err, idx = 0;
4465
4466 /* for internal loopback recording select */
4467 imux->items[imux->num_items].label = "Stereo Mixer";
4468 imux->items[imux->num_items].index = 3;
4469 imux->num_items++;
4470
4471 for (i = 0; i < AUTO_PIN_LAST; i++) {
4472 if (!cfg->input_pins[i])
4473 continue;
4474
4475 switch (cfg->input_pins[i]) {
4476 case 0x14: /* Mic */
4477 idx = 1;
4478 break;
4479
4480 case 0x15: /* Line In */
4481 idx = 2;
4482 break;
4483
4484 case 0x18: /* Front Mic */
4485 idx = 3;
4486 break;
4487 }
4488 err = via_new_analog_input(spec, labels[i], idx, 0x1A);
4489 if (err < 0)
4490 return err;
4491 imux->items[imux->num_items].label = labels[i];
4492 imux->items[imux->num_items].index = idx-1;
4493 imux->num_items++;
4494 }
4495 return 0;
4496} 4343}
4497 4344
4498static int vt1702_parse_auto_config(struct hda_codec *codec) 4345static int vt1702_parse_auto_config(struct hda_codec *codec)
@@ -4521,7 +4368,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
4521 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | 4368 (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
4522 (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | 4369 (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) |
4523 (1 << AC_AMPCAP_MUTE_SHIFT)); 4370 (1 << AC_AMPCAP_MUTE_SHIFT));
4524 err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg); 4371 err = vt1702_auto_create_analog_input_ctls(codec, &spec->autocfg);
4525 if (err < 0) 4372 if (err < 0)
4526 return err; 4373 return err;
4527 4374
@@ -4872,49 +4719,12 @@ static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
4872} 4719}
4873 4720
4874/* create playback/capture controls for input pins */ 4721/* create playback/capture controls for input pins */
4875static int vt1718S_auto_create_analog_input_ctls(struct via_spec *spec, 4722static int vt1718S_auto_create_analog_input_ctls(struct hda_codec *codec,
4876 const struct auto_pin_cfg *cfg) 4723 const struct auto_pin_cfg *cfg)
4877{ 4724{
4878 static char *labels[] = { 4725 static hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff };
4879 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL 4726 return vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
4880 }; 4727 ARRAY_SIZE(pin_idxs));
4881 struct hda_input_mux *imux = &spec->private_imux[0];
4882 int i, err, idx = 0;
4883
4884 /* for internal loopback recording select */
4885 imux->items[imux->num_items].label = "Stereo Mixer";
4886 imux->items[imux->num_items].index = 5;
4887 imux->num_items++;
4888
4889 for (i = 0; i < AUTO_PIN_LAST; i++) {
4890 if (!cfg->input_pins[i])
4891 continue;
4892
4893 switch (cfg->input_pins[i]) {
4894 case 0x2b: /* Mic */
4895 idx = 1;
4896 break;
4897
4898 case 0x2a: /* Line In */
4899 idx = 2;
4900 break;
4901
4902 case 0x29: /* Front Mic */
4903 idx = 3;
4904 break;
4905
4906 case 0x2c: /* CD */
4907 idx = 0;
4908 break;
4909 }
4910 err = via_new_analog_input(spec, labels[i], idx, 0x21);
4911 if (err < 0)
4912 return err;
4913 imux->items[imux->num_items].label = labels[i];
4914 imux->items[imux->num_items].index = idx;
4915 imux->num_items++;
4916 }
4917 return 0;
4918} 4728}
4919 4729
4920static int vt1718S_parse_auto_config(struct hda_codec *codec) 4730static int vt1718S_parse_auto_config(struct hda_codec *codec)
@@ -4938,7 +4748,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec)
4938 err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 4748 err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
4939 if (err < 0) 4749 if (err < 0)
4940 return err; 4750 return err;
4941 err = vt1718S_auto_create_analog_input_ctls(spec, &spec->autocfg); 4751 err = vt1718S_auto_create_analog_input_ctls(codec, &spec->autocfg);
4942 if (err < 0) 4752 if (err < 0)
4943 return err; 4753 return err;
4944 4754
@@ -5371,49 +5181,12 @@ static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
5371} 5181}
5372 5182
5373/* create playback/capture controls for input pins */ 5183/* create playback/capture controls for input pins */
5374static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec, 5184static int vt1716S_auto_create_analog_input_ctls(struct hda_codec *codec,
5375 const struct auto_pin_cfg *cfg) 5185 const struct auto_pin_cfg *cfg)
5376{ 5186{
5377 static char *labels[] = { 5187 static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff };
5378 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL 5188 return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs,
5379 }; 5189 ARRAY_SIZE(pin_idxs));
5380 struct hda_input_mux *imux = &spec->private_imux[0];
5381 int i, err, idx = 0;
5382
5383 /* for internal loopback recording select */
5384 imux->items[imux->num_items].label = "Stereo Mixer";
5385 imux->items[imux->num_items].index = 5;
5386 imux->num_items++;
5387
5388 for (i = 0; i < AUTO_PIN_LAST; i++) {
5389 if (!cfg->input_pins[i])
5390 continue;
5391
5392 switch (cfg->input_pins[i]) {
5393 case 0x1a: /* Mic */
5394 idx = 2;
5395 break;
5396
5397 case 0x1b: /* Line In */
5398 idx = 3;
5399 break;
5400
5401 case 0x1e: /* Front Mic */
5402 idx = 4;
5403 break;
5404
5405 case 0x1f: /* CD */
5406 idx = 1;
5407 break;
5408 }
5409 err = via_new_analog_input(spec, labels[i], idx, 0x16);
5410 if (err < 0)
5411 return err;
5412 imux->items[imux->num_items].label = labels[i];
5413 imux->items[imux->num_items].index = idx-1;
5414 imux->num_items++;
5415 }
5416 return 0;
5417} 5190}
5418 5191
5419static int vt1716S_parse_auto_config(struct hda_codec *codec) 5192static int vt1716S_parse_auto_config(struct hda_codec *codec)
@@ -5436,7 +5209,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec)
5436 err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 5209 err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
5437 if (err < 0) 5210 if (err < 0)
5438 return err; 5211 return err;
5439 err = vt1716S_auto_create_analog_input_ctls(spec, &spec->autocfg); 5212 err = vt1716S_auto_create_analog_input_ctls(codec, &spec->autocfg);
5440 if (err < 0) 5213 if (err < 0)
5441 return err; 5214 return err;
5442 5215
@@ -5717,54 +5490,25 @@ static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
5717} 5490}
5718 5491
5719/* create playback/capture controls for input pins */ 5492/* create playback/capture controls for input pins */
5720static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec, 5493static int vt2002P_auto_create_analog_input_ctls(struct hda_codec *codec,
5721 const struct auto_pin_cfg *cfg) 5494 const struct auto_pin_cfg *cfg)
5722{ 5495{
5723 static char *labels[] = { 5496 struct via_spec *spec = codec->spec;
5724 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
5725 };
5726 struct hda_input_mux *imux = &spec->private_imux[0]; 5497 struct hda_input_mux *imux = &spec->private_imux[0];
5727 int i, err, idx = 0; 5498 static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff };
5728 5499 int err;
5729 for (i = 0; i < AUTO_PIN_LAST; i++) {
5730 if (!cfg->input_pins[i])
5731 continue;
5732
5733 switch (cfg->input_pins[i]) {
5734 case 0x2b: /* Mic */
5735 idx = 0;
5736 break;
5737
5738 case 0x2a: /* Line In */
5739 idx = 1;
5740 break;
5741
5742 case 0x29: /* Front Mic */
5743 idx = 2;
5744 break;
5745 }
5746 err = via_new_analog_input(spec, labels[i], idx, 0x21);
5747 if (err < 0)
5748 return err;
5749 imux->items[imux->num_items].label = labels[i];
5750 imux->items[imux->num_items].index = idx;
5751 imux->num_items++;
5752 }
5753 5500
5501 err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
5502 ARRAY_SIZE(pin_idxs));
5503 if (err < 0)
5504 return err;
5754 /* build volume/mute control of loopback */ 5505 /* build volume/mute control of loopback */
5755 err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21); 5506 err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21);
5756 if (err < 0) 5507 if (err < 0)
5757 return err; 5508 return err;
5758 5509
5759 /* for internal loopback recording select */
5760 imux->items[imux->num_items].label = "Stereo Mixer";
5761 imux->items[imux->num_items].index = 3;
5762 imux->num_items++;
5763
5764 /* for digital mic select */ 5510 /* for digital mic select */
5765 imux->items[imux->num_items].label = "Digital Mic"; 5511 snd_hda_add_imux_item(imux, "Digital Mic", 4, NULL);
5766 imux->items[imux->num_items].index = 4;
5767 imux->num_items++;
5768 5512
5769 return 0; 5513 return 0;
5770} 5514}
@@ -5792,7 +5536,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec)
5792 err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 5536 err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
5793 if (err < 0) 5537 if (err < 0)
5794 return err; 5538 return err;
5795 err = vt2002P_auto_create_analog_input_ctls(spec, &spec->autocfg); 5539 err = vt2002P_auto_create_analog_input_ctls(codec, &spec->autocfg);
5796 if (err < 0) 5540 if (err < 0)
5797 return err; 5541 return err;
5798 5542
@@ -6067,53 +5811,26 @@ static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
6067} 5811}
6068 5812
6069/* create playback/capture controls for input pins */ 5813/* create playback/capture controls for input pins */
6070static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec, 5814static int vt1812_auto_create_analog_input_ctls(struct hda_codec *codec,
6071 const struct auto_pin_cfg *cfg) 5815 const struct auto_pin_cfg *cfg)
6072{ 5816{
6073 static char *labels[] = { 5817 struct via_spec *spec = codec->spec;
6074 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
6075 };
6076 struct hda_input_mux *imux = &spec->private_imux[0]; 5818 struct hda_input_mux *imux = &spec->private_imux[0];
6077 int i, err, idx = 0; 5819 static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff };
6078 5820 int err;
6079 for (i = 0; i < AUTO_PIN_LAST; i++) {
6080 if (!cfg->input_pins[i])
6081 continue;
6082
6083 switch (cfg->input_pins[i]) {
6084 case 0x2b: /* Mic */
6085 idx = 0;
6086 break;
6087 5821
6088 case 0x2a: /* Line In */ 5822 err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs,
6089 idx = 1; 5823 ARRAY_SIZE(pin_idxs));
6090 break; 5824 if (err < 0)
5825 return err;
6091 5826
6092 case 0x29: /* Front Mic */
6093 idx = 2;
6094 break;
6095 }
6096 err = via_new_analog_input(spec, labels[i], idx, 0x21);
6097 if (err < 0)
6098 return err;
6099 imux->items[imux->num_items].label = labels[i];
6100 imux->items[imux->num_items].index = idx;
6101 imux->num_items++;
6102 }
6103 /* build volume/mute control of loopback */ 5827 /* build volume/mute control of loopback */
6104 err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21); 5828 err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21);
6105 if (err < 0) 5829 if (err < 0)
6106 return err; 5830 return err;
6107 5831
6108 /* for internal loopback recording select */
6109 imux->items[imux->num_items].label = "Stereo Mixer";
6110 imux->items[imux->num_items].index = 5;
6111 imux->num_items++;
6112
6113 /* for digital mic select */ 5832 /* for digital mic select */
6114 imux->items[imux->num_items].label = "Digital Mic"; 5833 snd_hda_add_imux_item(imux, "Digital Mic", 6, NULL);
6115 imux->items[imux->num_items].index = 6;
6116 imux->num_items++;
6117 5834
6118 return 0; 5835 return 0;
6119} 5836}
@@ -6141,7 +5858,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec)
6141 err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); 5858 err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
6142 if (err < 0) 5859 if (err < 0)
6143 return err; 5860 return err;
6144 err = vt1812_auto_create_analog_input_ctls(spec, &spec->autocfg); 5861 err = vt1812_auto_create_analog_input_ctls(codec, &spec->autocfg);
6145 if (err < 0) 5862 if (err < 0)
6146 return err; 5863 return err;
6147 5864
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index d216362626d0..712c1710f9a2 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -563,6 +563,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
563 case ICE1712_SUBDEVICE_DELTA1010E: 563 case ICE1712_SUBDEVICE_DELTA1010E:
564 case ICE1712_SUBDEVICE_DELTA1010LT: 564 case ICE1712_SUBDEVICE_DELTA1010LT:
565 case ICE1712_SUBDEVICE_MEDIASTATION: 565 case ICE1712_SUBDEVICE_MEDIASTATION:
566 case ICE1712_SUBDEVICE_EDIROLDA2496:
566 ice->num_total_dacs = 8; 567 ice->num_total_dacs = 8;
567 ice->num_total_adcs = 8; 568 ice->num_total_adcs = 8;
568 break; 569 break;
@@ -635,6 +636,7 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
635 err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice); 636 err = snd_ice1712_akm4xxx_init(ak, &akm_delta410, &akm_delta410_priv, ice);
636 break; 637 break;
637 case ICE1712_SUBDEVICE_DELTA1010LT: 638 case ICE1712_SUBDEVICE_DELTA1010LT:
639 case ICE1712_SUBDEVICE_EDIROLDA2496:
638 err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice); 640 err = snd_ice1712_akm4xxx_init(ak, &akm_delta1010lt, &akm_delta1010lt_priv, ice);
639 break; 641 break;
640 case ICE1712_SUBDEVICE_DELTA66: 642 case ICE1712_SUBDEVICE_DELTA66:
@@ -734,6 +736,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
734 case ICE1712_SUBDEVICE_DELTA66: 736 case ICE1712_SUBDEVICE_DELTA66:
735 case ICE1712_SUBDEVICE_VX442: 737 case ICE1712_SUBDEVICE_VX442:
736 case ICE1712_SUBDEVICE_DELTA66E: 738 case ICE1712_SUBDEVICE_DELTA66E:
739 case ICE1712_SUBDEVICE_EDIROLDA2496:
737 err = snd_ice1712_akm4xxx_build_controls(ice); 740 err = snd_ice1712_akm4xxx_build_controls(ice);
738 if (err < 0) 741 if (err < 0)
739 return err; 742 return err;
@@ -813,5 +816,12 @@ struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
813 .chip_init = snd_ice1712_delta_init, 816 .chip_init = snd_ice1712_delta_init,
814 .build_controls = snd_ice1712_delta_add_controls, 817 .build_controls = snd_ice1712_delta_add_controls,
815 }, 818 },
819 {
820 .subvendor = ICE1712_SUBDEVICE_EDIROLDA2496,
821 .name = "Edirol DA2496",
822 .model = "da2496",
823 .chip_init = snd_ice1712_delta_init,
824 .build_controls = snd_ice1712_delta_add_controls,
825 },
816 { } /* terminator */ 826 { } /* terminator */
817}; 827};
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index f7f14df81f26..1a0ac6cd6501 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -34,7 +34,8 @@
34 "{MidiMan M Audio,Delta 410},"\ 34 "{MidiMan M Audio,Delta 410},"\
35 "{MidiMan M Audio,Audiophile 24/96},"\ 35 "{MidiMan M Audio,Audiophile 24/96},"\
36 "{Digigram,VX442},"\ 36 "{Digigram,VX442},"\
37 "{Lionstracs,Mediastation}," 37 "{Lionstracs,Mediastation},"\
38 "{Edirol,DA2496},"
38 39
39#define ICE1712_SUBDEVICE_DELTA1010 0x121430d6 40#define ICE1712_SUBDEVICE_DELTA1010 0x121430d6
40#define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6 41#define ICE1712_SUBDEVICE_DELTA1010E 0xff1430d6
@@ -47,6 +48,7 @@
47#define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6 48#define ICE1712_SUBDEVICE_DELTA1010LT 0x12143bd6
48#define ICE1712_SUBDEVICE_VX442 0x12143cd6 49#define ICE1712_SUBDEVICE_VX442 0x12143cd6
49#define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100 50#define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100
51#define ICE1712_SUBDEVICE_EDIROLDA2496 0xce164010
50 52
51/* entry point */ 53/* entry point */
52extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; 54extern struct snd_ice1712_card_info snd_ice1712_delta_cards[];
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 6bc3f91b7281..cdb873f5da50 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -638,7 +638,7 @@ static struct snd_kcontrol_new pontis_controls[] __devinitdata = {
638 */ 638 */
639static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 639static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
640{ 640{
641 struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; 641 struct snd_ice1712 *ice = entry->private_data;
642 char line[64]; 642 char line[64];
643 unsigned int reg, val; 643 unsigned int reg, val;
644 mutex_lock(&ice->gpio_mutex); 644 mutex_lock(&ice->gpio_mutex);
@@ -653,7 +653,7 @@ static void wm_proc_regs_write(struct snd_info_entry *entry, struct snd_info_buf
653 653
654static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 654static void wm_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
655{ 655{
656 struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; 656 struct snd_ice1712 *ice = entry->private_data;
657 int reg, val; 657 int reg, val;
658 658
659 mutex_lock(&ice->gpio_mutex); 659 mutex_lock(&ice->gpio_mutex);
@@ -676,7 +676,7 @@ static void wm_proc_init(struct snd_ice1712 *ice)
676 676
677static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 677static void cs_proc_regs_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
678{ 678{
679 struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; 679 struct snd_ice1712 *ice = entry->private_data;
680 int reg, val; 680 int reg, val;
681 681
682 mutex_lock(&ice->gpio_mutex); 682 mutex_lock(&ice->gpio_mutex);
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 2a8e5cd8f2d8..e36ddb94c382 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -654,7 +654,7 @@ static int prodigy192_ak4114_init(struct snd_ice1712 *ice)
654static void stac9460_proc_regs_read(struct snd_info_entry *entry, 654static void stac9460_proc_regs_read(struct snd_info_entry *entry,
655 struct snd_info_buffer *buffer) 655 struct snd_info_buffer *buffer)
656{ 656{
657 struct snd_ice1712 *ice = (struct snd_ice1712 *)entry->private_data; 657 struct snd_ice1712 *ice = entry->private_data;
658 int reg, val; 658 int reg, val;
659 /* registers 0x0 - 0x14 */ 659 /* registers 0x0 - 0x14 */
660 for (reg = 0; reg <= 0x15; reg++) { 660 for (reg = 0; reg <= 0x15; reg++) {
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 6c0a11adb2a8..98a8eb3c92f7 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -79,6 +79,7 @@ static DEFINE_PCI_DEVICE_TABLE(oxygen_ids) = {
79 { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF }, 79 { OXYGEN_PCI_SUBID(0x13f6, 0x0001), .driver_data = MODEL_CMEDIA_REF },
80 { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF }, 80 { OXYGEN_PCI_SUBID(0x13f6, 0x0010), .driver_data = MODEL_CMEDIA_REF },
81 { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF }, 81 { OXYGEN_PCI_SUBID(0x13f6, 0x8788), .driver_data = MODEL_CMEDIA_REF },
82 { OXYGEN_PCI_SUBID(0x13f6, 0xffff), .driver_data = MODEL_CMEDIA_REF },
82 { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF }, 83 { OXYGEN_PCI_SUBID(0x147a, 0xa017), .driver_data = MODEL_CMEDIA_REF },
83 { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF }, 84 { OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF },
84 { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN }, 85 { OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN },
@@ -505,7 +506,8 @@ static const struct oxygen_model model_generic = {
505 PLAYBACK_2_TO_AC97_1 | 506 PLAYBACK_2_TO_AC97_1 |
506 CAPTURE_0_FROM_I2S_1 | 507 CAPTURE_0_FROM_I2S_1 |
507 CAPTURE_1_FROM_SPDIF | 508 CAPTURE_1_FROM_SPDIF |
508 CAPTURE_2_FROM_AC97_1, 509 CAPTURE_2_FROM_AC97_1 |
510 AC97_CD_INPUT,
509 .dac_channels = 8, 511 .dac_channels = 8,
510 .dac_volume_min = 0, 512 .dac_volume_min = 0,
511 .dac_volume_max = 255, 513 .dac_volume_max = 255,
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h
index a3409edcfb50..7d5222caa0a9 100644
--- a/sound/pci/oxygen/oxygen.h
+++ b/sound/pci/oxygen/oxygen.h
@@ -34,6 +34,7 @@
34 /* CAPTURE_3_FROM_I2S_3 not implemented */ 34 /* CAPTURE_3_FROM_I2S_3 not implemented */
35#define MIDI_OUTPUT 0x0800 35#define MIDI_OUTPUT 0x0800
36#define MIDI_INPUT 0x1000 36#define MIDI_INPUT 0x1000
37#define AC97_CD_INPUT 0x2000
37 38
38enum { 39enum {
39 CONTROL_SPDIF_PCM, 40 CONTROL_SPDIF_PCM,
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 7e93cf884437..e5ebe56fb0c5 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -308,25 +308,46 @@ static void oxygen_restore_eeprom(struct oxygen *chip,
308 } 308 }
309} 309}
310 310
311static void pci_bridge_magic(void) 311static void configure_pcie_bridge(struct pci_dev *pci)
312{ 312{
313 struct pci_dev *pci = NULL; 313 enum { PEX811X, PI7C9X110 };
314 static const struct pci_device_id bridge_ids[] = {
315 { PCI_VDEVICE(PLX, 0x8111), .driver_data = PEX811X },
316 { PCI_VDEVICE(PLX, 0x8112), .driver_data = PEX811X },
317 { PCI_DEVICE(0x12d8, 0xe110), .driver_data = PI7C9X110 },
318 { }
319 };
320 struct pci_dev *bridge;
321 const struct pci_device_id *id;
314 u32 tmp; 322 u32 tmp;
315 323
316 for (;;) { 324 if (!pci->bus || !pci->bus->self)
317 /* If there is any Pericom PI7C9X110 PCI-E/PCI bridge ... */ 325 return;
318 pci = pci_get_device(0x12d8, 0xe110, pci); 326 bridge = pci->bus->self;
319 if (!pci) 327
320 break; 328 id = pci_match_id(bridge_ids, bridge);
321 /* 329 if (!id)
322 * ... configure its secondary internal arbiter to park to 330 return;
323 * the secondary port, instead of to the last master. 331
324 */ 332 switch (id->driver_data) {
325 if (!pci_read_config_dword(pci, 0x40, &tmp)) { 333 case PEX811X: /* PLX PEX8111/PEX8112 PCIe/PCI bridge */
326 tmp |= 1; 334 pci_read_config_dword(bridge, 0x48, &tmp);
327 pci_write_config_dword(pci, 0x40, tmp); 335 tmp |= 1; /* enable blind prefetching */
328 } 336 tmp |= 1 << 11; /* enable beacon generation */
329 /* Why? Try asking C-Media. */ 337 pci_write_config_dword(bridge, 0x48, tmp);
338
339 pci_write_config_dword(bridge, 0x84, 0x0c);
340 pci_read_config_dword(bridge, 0x88, &tmp);
341 tmp &= ~(7 << 27);
342 tmp |= 2 << 27; /* set prefetch size to 128 bytes */
343 pci_write_config_dword(bridge, 0x88, tmp);
344 break;
345
346 case PI7C9X110: /* Pericom PI7C9X110 PCIe/PCI bridge */
347 pci_read_config_dword(bridge, 0x40, &tmp);
348 tmp |= 1; /* park the PCI arbiter to the sound chip */
349 pci_write_config_dword(bridge, 0x40, tmp);
350 break;
330 } 351 }
331} 352}
332 353
@@ -613,7 +634,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
613 snd_card_set_dev(card, &pci->dev); 634 snd_card_set_dev(card, &pci->dev);
614 card->private_free = oxygen_card_free; 635 card->private_free = oxygen_card_free;
615 636
616 pci_bridge_magic(); 637 configure_pcie_bridge(pci);
617 oxygen_init(chip); 638 oxygen_init(chip);
618 chip->model.init(chip); 639 chip->model.init(chip);
619 640
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index f375b8a27862..2849b36f5f7e 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -708,7 +708,7 @@ static int ac97_fp_rec_volume_put(struct snd_kcontrol *ctl,
708 .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \ 708 .private_value = ((codec) << 24) | ((stereo) << 16) | (index), \
709 } 709 }
710 710
711static DECLARE_TLV_DB_SCALE(monitor_db_scale, -1000, 1000, 0); 711static DECLARE_TLV_DB_SCALE(monitor_db_scale, -600, 600, 0);
712static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0); 712static DECLARE_TLV_DB_SCALE(ac97_db_scale, -3450, 150, 0);
713static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0); 713static DECLARE_TLV_DB_SCALE(ac97_rec_db_scale, 0, 150, 0);
714 714
@@ -972,6 +972,9 @@ static int add_controls(struct oxygen *chip,
972 if (!strcmp(template.name, "Stereo Upmixing") && 972 if (!strcmp(template.name, "Stereo Upmixing") &&
973 chip->model.dac_channels == 2) 973 chip->model.dac_channels == 2)
974 continue; 974 continue;
975 if (!strncmp(template.name, "CD Capture ", 11) &&
976 !(chip->model.device_config & AC97_CD_INPUT))
977 continue;
975 if (!strcmp(template.name, "Master Playback Volume") && 978 if (!strcmp(template.name, "Master Playback Volume") &&
976 chip->model.dac_tlv) { 979 chip->model.dac_tlv) {
977 template.tlv.p = chip->model.dac_tlv; 980 template.tlv.p = chip->model.dac_tlv;
diff --git a/sound/pci/oxygen/oxygen_pcm.c b/sound/pci/oxygen/oxygen_pcm.c
index 9dff6954c397..814667442eb0 100644
--- a/sound/pci/oxygen/oxygen_pcm.c
+++ b/sound/pci/oxygen/oxygen_pcm.c
@@ -56,8 +56,8 @@ static const struct snd_pcm_hardware oxygen_stereo_hardware = {
56 .channels_max = 2, 56 .channels_max = 2,
57 .buffer_bytes_max = BUFFER_BYTES_MAX, 57 .buffer_bytes_max = BUFFER_BYTES_MAX,
58 .period_bytes_min = PERIOD_BYTES_MIN, 58 .period_bytes_min = PERIOD_BYTES_MIN,
59 .period_bytes_max = BUFFER_BYTES_MAX / 2, 59 .period_bytes_max = BUFFER_BYTES_MAX,
60 .periods_min = 2, 60 .periods_min = 1,
61 .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, 61 .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
62}; 62};
63static const struct snd_pcm_hardware oxygen_multichannel_hardware = { 63static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
@@ -82,8 +82,8 @@ static const struct snd_pcm_hardware oxygen_multichannel_hardware = {
82 .channels_max = 8, 82 .channels_max = 8,
83 .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH, 83 .buffer_bytes_max = BUFFER_BYTES_MAX_MULTICH,
84 .period_bytes_min = PERIOD_BYTES_MIN, 84 .period_bytes_min = PERIOD_BYTES_MIN,
85 .period_bytes_max = BUFFER_BYTES_MAX_MULTICH / 2, 85 .period_bytes_max = BUFFER_BYTES_MAX_MULTICH,
86 .periods_min = 2, 86 .periods_min = 1,
87 .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN, 87 .periods_max = BUFFER_BYTES_MAX_MULTICH / PERIOD_BYTES_MIN,
88}; 88};
89static const struct snd_pcm_hardware oxygen_ac97_hardware = { 89static const struct snd_pcm_hardware oxygen_ac97_hardware = {
@@ -100,8 +100,8 @@ static const struct snd_pcm_hardware oxygen_ac97_hardware = {
100 .channels_max = 2, 100 .channels_max = 2,
101 .buffer_bytes_max = BUFFER_BYTES_MAX, 101 .buffer_bytes_max = BUFFER_BYTES_MAX,
102 .period_bytes_min = PERIOD_BYTES_MIN, 102 .period_bytes_min = PERIOD_BYTES_MIN,
103 .period_bytes_max = BUFFER_BYTES_MAX / 2, 103 .period_bytes_max = BUFFER_BYTES_MAX,
104 .periods_min = 2, 104 .periods_min = 1,
105 .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN, 105 .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
106}; 106};
107 107
diff --git a/sound/pci/oxygen/oxygen_regs.h b/sound/pci/oxygen/oxygen_regs.h
index 72de159d4567..4dcd41b78258 100644
--- a/sound/pci/oxygen/oxygen_regs.h
+++ b/sound/pci/oxygen/oxygen_regs.h
@@ -436,13 +436,15 @@
436/* OXYGEN_CHANNEL_* */ 436/* OXYGEN_CHANNEL_* */
437 437
438#define OXYGEN_CODEC_VERSION 0xe4 438#define OXYGEN_CODEC_VERSION 0xe4
439#define OXYGEN_XCID_MASK 0x07 439#define OXYGEN_CODEC_ID_MASK 0x07
440 440
441#define OXYGEN_REVISION 0xe6 441#define OXYGEN_REVISION 0xe6
442#define OXYGEN_REVISION_XPKGID_MASK 0x0007 442#define OXYGEN_PACKAGE_ID_MASK 0x0007
443#define OXYGEN_PACKAGE_ID_8786 0x0004
444#define OXYGEN_PACKAGE_ID_8787 0x0006
445#define OXYGEN_PACKAGE_ID_8788 0x0007
443#define OXYGEN_REVISION_MASK 0xfff8 446#define OXYGEN_REVISION_MASK 0xfff8
444#define OXYGEN_REVISION_2 0x0008 /* bit flag */ 447#define OXYGEN_REVISION_2 0x0008
445#define OXYGEN_REVISION_8787 0x0014 /* 8 bits */
446 448
447#define OXYGEN_OFFSIN_48K 0xe8 449#define OXYGEN_OFFSIN_48K 0xe8
448#define OXYGEN_OFFSBASE_48K 0xe9 450#define OXYGEN_OFFSBASE_48K 0xe9
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 06c863e86e3d..469010a8b849 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -25,9 +25,9 @@
25#include "xonar.h" 25#include "xonar.h"
26 26
27MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>"); 27MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
28MODULE_DESCRIPTION("Asus AVx00 driver"); 28MODULE_DESCRIPTION("Asus Virtuoso driver");
29MODULE_LICENSE("GPL v2"); 29MODULE_LICENSE("GPL v2");
30MODULE_SUPPORTED_DEVICE("{{Asus,AV100},{Asus,AV200}}"); 30MODULE_SUPPORTED_DEVICE("{{Asus,AV66},{Asus,AV100},{Asus,AV200}}");
31 31
32static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; 32static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
33static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; 33static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -49,6 +49,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
49 { OXYGEN_PCI_SUBID(0x1043, 0x834f) }, 49 { OXYGEN_PCI_SUBID(0x1043, 0x834f) },
50 { OXYGEN_PCI_SUBID(0x1043, 0x835c) }, 50 { OXYGEN_PCI_SUBID(0x1043, 0x835c) },
51 { OXYGEN_PCI_SUBID(0x1043, 0x835d) }, 51 { OXYGEN_PCI_SUBID(0x1043, 0x835d) },
52 { OXYGEN_PCI_SUBID(0x1043, 0x835e) },
52 { OXYGEN_PCI_SUBID(0x1043, 0x838e) }, 53 { OXYGEN_PCI_SUBID(0x1043, 0x838e) },
53 { OXYGEN_PCI_SUBID_BROKEN_EEPROM }, 54 { OXYGEN_PCI_SUBID_BROKEN_EEPROM },
54 { } 55 { }
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
index 7c4986b27f2b..aa27c31049af 100644
--- a/sound/pci/oxygen/xonar_cs43xx.c
+++ b/sound/pci/oxygen/xonar_cs43xx.c
@@ -367,13 +367,6 @@ static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip,
367 367
368static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0); 368static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -6000, 100, 0);
369 369
370static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
371{
372 if (!strncmp(template->name, "CD Capture ", 11))
373 return 1; /* no CD input */
374 return 0;
375}
376
377static int xonar_d1_mixer_init(struct oxygen *chip) 370static int xonar_d1_mixer_init(struct oxygen *chip)
378{ 371{
379 int err; 372 int err;
@@ -391,7 +384,6 @@ static const struct oxygen_model model_xonar_d1 = {
391 .longname = "Asus Virtuoso 100", 384 .longname = "Asus Virtuoso 100",
392 .chip = "AV200", 385 .chip = "AV200",
393 .init = xonar_d1_init, 386 .init = xonar_d1_init,
394 .control_filter = xonar_d1_control_filter,
395 .mixer_init = xonar_d1_mixer_init, 387 .mixer_init = xonar_d1_mixer_init,
396 .cleanup = xonar_d1_cleanup, 388 .cleanup = xonar_d1_cleanup,
397 .suspend = xonar_d1_suspend, 389 .suspend = xonar_d1_suspend,
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index ba18fb546b4f..d491fd6c0be2 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -132,6 +132,18 @@
132 * GPIO 5 <- 0 132 * GPIO 5 <- 0
133 */ 133 */
134 134
135/*
136 * Xonar HDAV1.3 Slim
137 * ------------------
138 *
139 * CMI8788:
140 *
141 * GPIO 1 -> enable output
142 *
143 * TXD -> HDMI controller
144 * RXD <- HDMI controller
145 */
146
135#include <linux/pci.h> 147#include <linux/pci.h>
136#include <linux/delay.h> 148#include <linux/delay.h>
137#include <linux/mutex.h> 149#include <linux/mutex.h>
@@ -362,7 +374,6 @@ static void xonar_st_init_common(struct oxygen *chip)
362{ 374{
363 struct xonar_pcm179x *data = chip->model_data; 375 struct xonar_pcm179x *data = chip->model_data;
364 376
365 data->generic.anti_pop_delay = 100;
366 data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; 377 data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE;
367 data->dacs = chip->model.private_data ? 4 : 1; 378 data->dacs = chip->model.private_data ? 4 : 1;
368 data->hp_gain_offset = 2*-18; 379 data->hp_gain_offset = 2*-18;
@@ -408,6 +419,7 @@ static void xonar_st_init(struct oxygen *chip)
408{ 419{
409 struct xonar_pcm179x *data = chip->model_data; 420 struct xonar_pcm179x *data = chip->model_data;
410 421
422 data->generic.anti_pop_delay = 100;
411 data->has_cs2000 = 1; 423 data->has_cs2000 = 1;
412 data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; 424 data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1;
413 425
@@ -428,6 +440,7 @@ static void xonar_stx_init(struct oxygen *chip)
428 struct xonar_pcm179x *data = chip->model_data; 440 struct xonar_pcm179x *data = chip->model_data;
429 441
430 xonar_st_init_i2c(chip); 442 xonar_st_init_i2c(chip);
443 data->generic.anti_pop_delay = 800;
431 data->generic.ext_power_reg = OXYGEN_GPI_DATA; 444 data->generic.ext_power_reg = OXYGEN_GPI_DATA;
432 data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; 445 data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK;
433 data->generic.ext_power_bit = GPI_EXT_POWER; 446 data->generic.ext_power_bit = GPI_EXT_POWER;
@@ -915,13 +928,6 @@ static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
915 return 0; 928 return 0;
916} 929}
917 930
918static int xonar_st_control_filter(struct snd_kcontrol_new *template)
919{
920 if (!strncmp(template->name, "CD Capture ", 11))
921 return 1; /* no CD input */
922 return 0;
923}
924
925static int add_pcm1796_controls(struct oxygen *chip) 931static int add_pcm1796_controls(struct oxygen *chip)
926{ 932{
927 int err; 933 int err;
@@ -991,7 +997,8 @@ static const struct oxygen_model model_xonar_d2 = {
991 CAPTURE_0_FROM_I2S_2 | 997 CAPTURE_0_FROM_I2S_2 |
992 CAPTURE_1_FROM_SPDIF | 998 CAPTURE_1_FROM_SPDIF |
993 MIDI_OUTPUT | 999 MIDI_OUTPUT |
994 MIDI_INPUT, 1000 MIDI_INPUT |
1001 AC97_CD_INPUT,
995 .dac_channels = 8, 1002 .dac_channels = 8,
996 .dac_volume_min = 255 - 2*60, 1003 .dac_volume_min = 255 - 2*60,
997 .dac_volume_max = 255, 1004 .dac_volume_max = 255,
@@ -1037,7 +1044,6 @@ static const struct oxygen_model model_xonar_st = {
1037 .longname = "Asus Virtuoso 100", 1044 .longname = "Asus Virtuoso 100",
1038 .chip = "AV200", 1045 .chip = "AV200",
1039 .init = xonar_st_init, 1046 .init = xonar_st_init,
1040 .control_filter = xonar_st_control_filter,
1041 .mixer_init = xonar_st_mixer_init, 1047 .mixer_init = xonar_st_mixer_init,
1042 .cleanup = xonar_st_cleanup, 1048 .cleanup = xonar_st_cleanup,
1043 .suspend = xonar_st_suspend, 1049 .suspend = xonar_st_suspend,
@@ -1108,6 +1114,9 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip,
1108 chip->model.resume = xonar_stx_resume; 1114 chip->model.resume = xonar_stx_resume;
1109 chip->model.set_dac_params = set_pcm1796_params; 1115 chip->model.set_dac_params = set_pcm1796_params;
1110 break; 1116 break;
1117 case 0x835e:
1118 snd_printk(KERN_ERR "the HDAV1.3 Slim is not supported\n");
1119 return -ENODEV;
1111 default: 1120 default:
1112 return -EINVAL; 1121 return -EINVAL;
1113 } 1122 }
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
index b82c1cfa96f5..200f7601276f 100644
--- a/sound/pci/oxygen/xonar_wm87x6.c
+++ b/sound/pci/oxygen/xonar_wm87x6.c
@@ -25,16 +25,24 @@
25 * SPI 0 -> WM8766 (surround, center/LFE, back) 25 * SPI 0 -> WM8766 (surround, center/LFE, back)
26 * SPI 1 -> WM8776 (front, input) 26 * SPI 1 -> WM8776 (front, input)
27 * 27 *
28 * GPIO 4 <- headphone detect 28 * GPIO 4 <- headphone detect, 0 = plugged
29 * GPIO 6 -> route input jack to input 1/2 (1/0) 29 * GPIO 6 -> route input jack to mic-in (0) or line-in (1)
30 * GPIO 7 -> enable output to speakers 30 * GPIO 7 -> enable output to front L/R speaker channels
31 * GPIO 8 -> enable output to speakers 31 * GPIO 8 -> enable output to other speaker channels and front panel headphone
32 *
33 * WM8766:
34 *
35 * input 1 <- line
36 * input 2 <- mic
37 * input 3 <- front mic
38 * input 4 <- aux
32 */ 39 */
33 40
34#include <linux/pci.h> 41#include <linux/pci.h>
35#include <linux/delay.h> 42#include <linux/delay.h>
36#include <sound/control.h> 43#include <sound/control.h>
37#include <sound/core.h> 44#include <sound/core.h>
45#include <sound/jack.h>
38#include <sound/pcm.h> 46#include <sound/pcm.h>
39#include <sound/pcm_params.h> 47#include <sound/pcm_params.h>
40#include <sound/tlv.h> 48#include <sound/tlv.h>
@@ -44,7 +52,8 @@
44 52
45#define GPIO_DS_HP_DETECT 0x0010 53#define GPIO_DS_HP_DETECT 0x0010
46#define GPIO_DS_INPUT_ROUTE 0x0040 54#define GPIO_DS_INPUT_ROUTE 0x0040
47#define GPIO_DS_OUTPUT_ENABLE 0x0180 55#define GPIO_DS_OUTPUT_FRONTLR 0x0080
56#define GPIO_DS_OUTPUT_ENABLE 0x0100
48 57
49#define LC_CONTROL_LIMITER 0x40000000 58#define LC_CONTROL_LIMITER 0x40000000
50#define LC_CONTROL_ALC 0x20000000 59#define LC_CONTROL_ALC 0x20000000
@@ -56,6 +65,7 @@ struct xonar_wm87x6 {
56 struct snd_kcontrol *line_adcmux_control; 65 struct snd_kcontrol *line_adcmux_control;
57 struct snd_kcontrol *mic_adcmux_control; 66 struct snd_kcontrol *mic_adcmux_control;
58 struct snd_kcontrol *lc_controls[13]; 67 struct snd_kcontrol *lc_controls[13];
68 struct snd_jack *hp_jack;
59}; 69};
60 70
61static void wm8776_write(struct oxygen *chip, 71static void wm8776_write(struct oxygen *chip,
@@ -97,8 +107,12 @@ static void wm8766_write(struct oxygen *chip,
97 (0 << OXYGEN_SPI_CODEC_SHIFT) | 107 (0 << OXYGEN_SPI_CODEC_SHIFT) |
98 OXYGEN_SPI_CEN_LATCH_CLOCK_LO, 108 OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
99 (reg << 9) | value); 109 (reg << 9) | value);
100 if (reg < ARRAY_SIZE(data->wm8766_regs)) 110 if (reg < ARRAY_SIZE(data->wm8766_regs)) {
111 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
112 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
113 value &= ~WM8766_UPDATE;
101 data->wm8766_regs[reg] = value; 114 data->wm8766_regs[reg] = value;
115 }
102} 116}
103 117
104static void wm8766_write_cached(struct oxygen *chip, 118static void wm8766_write_cached(struct oxygen *chip,
@@ -107,12 +121,8 @@ static void wm8766_write_cached(struct oxygen *chip,
107 struct xonar_wm87x6 *data = chip->model_data; 121 struct xonar_wm87x6 *data = chip->model_data;
108 122
109 if (reg >= ARRAY_SIZE(data->wm8766_regs) || 123 if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
110 value != data->wm8766_regs[reg]) { 124 value != data->wm8766_regs[reg])
111 if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
112 (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
113 value &= ~WM8766_UPDATE;
114 wm8766_write(chip, reg, value); 125 wm8766_write(chip, reg, value);
115 }
116} 126}
117 127
118static void wm8776_registers_init(struct oxygen *chip) 128static void wm8776_registers_init(struct oxygen *chip)
@@ -141,7 +151,10 @@ static void wm8776_registers_init(struct oxygen *chip)
141 151
142static void wm8766_registers_init(struct oxygen *chip) 152static void wm8766_registers_init(struct oxygen *chip)
143{ 153{
154 struct xonar_wm87x6 *data = chip->model_data;
155
144 wm8766_write(chip, WM8766_RESET, 0); 156 wm8766_write(chip, WM8766_RESET, 0);
157 wm8766_write(chip, WM8766_DAC_CTRL, data->wm8766_regs[WM8766_DAC_CTRL]);
145 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24); 158 wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
146 wm8766_write(chip, WM8766_DAC_CTRL2, 159 wm8766_write(chip, WM8766_DAC_CTRL2,
147 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); 160 WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
@@ -170,6 +183,40 @@ static void wm8776_init(struct oxygen *chip)
170 wm8776_registers_init(chip); 183 wm8776_registers_init(chip);
171} 184}
172 185
186static void wm8766_init(struct oxygen *chip)
187{
188 struct xonar_wm87x6 *data = chip->model_data;
189
190 data->wm8766_regs[WM8766_DAC_CTRL] =
191 WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
192 wm8766_registers_init(chip);
193}
194
195static void xonar_ds_handle_hp_jack(struct oxygen *chip)
196{
197 struct xonar_wm87x6 *data = chip->model_data;
198 bool hp_plugged;
199 unsigned int reg;
200
201 mutex_lock(&chip->mutex);
202
203 hp_plugged = !(oxygen_read16(chip, OXYGEN_GPIO_DATA) &
204 GPIO_DS_HP_DETECT);
205
206 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
207 hp_plugged ? 0 : GPIO_DS_OUTPUT_FRONTLR,
208 GPIO_DS_OUTPUT_FRONTLR);
209
210 reg = data->wm8766_regs[WM8766_DAC_CTRL] & ~WM8766_MUTEALL;
211 if (hp_plugged)
212 reg |= WM8766_MUTEALL;
213 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
214
215 snd_jack_report(data->hp_jack, hp_plugged ? SND_JACK_HEADPHONE : 0);
216
217 mutex_unlock(&chip->mutex);
218}
219
173static void xonar_ds_init(struct oxygen *chip) 220static void xonar_ds_init(struct oxygen *chip)
174{ 221{
175 struct xonar_wm87x6 *data = chip->model_data; 222 struct xonar_wm87x6 *data = chip->model_data;
@@ -178,16 +225,22 @@ static void xonar_ds_init(struct oxygen *chip)
178 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE; 225 data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
179 226
180 wm8776_init(chip); 227 wm8776_init(chip);
181 wm8766_registers_init(chip); 228 wm8766_init(chip);
182 229
183 oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE, 230 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
184 GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE); 231 GPIO_DS_INPUT_ROUTE | GPIO_DS_OUTPUT_FRONTLR);
232 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL,
233 GPIO_DS_HP_DETECT);
185 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE); 234 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
186 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT); 235 oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
187 chip->interrupt_mask |= OXYGEN_INT_GPIO; 236 chip->interrupt_mask |= OXYGEN_INT_GPIO;
188 237
189 xonar_enable_output(chip); 238 xonar_enable_output(chip);
190 239
240 snd_jack_new(chip->card, "Headphone",
241 SND_JACK_HEADPHONE, &data->hp_jack);
242 xonar_ds_handle_hp_jack(chip);
243
191 snd_component_add(chip->card, "WM8776"); 244 snd_component_add(chip->card, "WM8776");
192 snd_component_add(chip->card, "WM8766"); 245 snd_component_add(chip->card, "WM8766");
193} 246}
@@ -208,6 +261,7 @@ static void xonar_ds_resume(struct oxygen *chip)
208 wm8776_registers_init(chip); 261 wm8776_registers_init(chip);
209 wm8766_registers_init(chip); 262 wm8766_registers_init(chip);
210 xonar_enable_output(chip); 263 xonar_enable_output(chip);
264 xonar_ds_handle_hp_jack(chip);
211} 265}
212 266
213static void wm8776_adc_hardware_filter(unsigned int channel, 267static void wm8776_adc_hardware_filter(unsigned int channel,
@@ -323,12 +377,27 @@ static void update_wm87x6_mute(struct oxygen *chip)
323 (chip->dac_mute ? WM8766_DMUTE_MASK : 0)); 377 (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
324} 378}
325 379
326static void xonar_ds_gpio_changed(struct oxygen *chip) 380static void update_wm8766_center_lfe_mix(struct oxygen *chip, bool mixed)
327{ 381{
328 u16 bits; 382 struct xonar_wm87x6 *data = chip->model_data;
383 unsigned int reg;
329 384
330 bits = oxygen_read16(chip, OXYGEN_GPIO_DATA); 385 /*
331 snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT)); 386 * The WM8766 can mix left and right channels, but this setting
387 * applies to all three stereo pairs.
388 */
389 reg = data->wm8766_regs[WM8766_DAC_CTRL] &
390 ~(WM8766_PL_LEFT_MASK | WM8766_PL_RIGHT_MASK);
391 if (mixed)
392 reg |= WM8766_PL_LEFT_LRMIX | WM8766_PL_RIGHT_LRMIX;
393 else
394 reg |= WM8766_PL_LEFT_LEFT | WM8766_PL_RIGHT_RIGHT;
395 wm8766_write_cached(chip, WM8766_DAC_CTRL, reg);
396}
397
398static void xonar_ds_gpio_changed(struct oxygen *chip)
399{
400 xonar_ds_handle_hp_jack(chip);
332} 401}
333 402
334static int wm8776_bit_switch_get(struct snd_kcontrol *ctl, 403static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
@@ -896,7 +965,10 @@ static const struct snd_kcontrol_new ds_controls[] = {
896 .put = wm8776_input_mux_put, 965 .put = wm8776_input_mux_put,
897 .private_value = 1 << 1, 966 .private_value = 1 << 1,
898 }, 967 },
899 WM8776_BIT_SWITCH("Aux", WM8776_ADCMUX, 1 << 2, 0, 0), 968 WM8776_BIT_SWITCH("Front Mic Capture Switch",
969 WM8776_ADCMUX, 1 << 2, 0, 0),
970 WM8776_BIT_SWITCH("Aux Capture Switch",
971 WM8776_ADCMUX, 1 << 3, 0, 0),
900 { 972 {
901 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 973 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
902 .name = "ADC Filter Capture Enum", 974 .name = "ADC Filter Capture Enum",
@@ -956,13 +1028,6 @@ static const struct snd_kcontrol_new lc_controls[] = {
956 LC_CONTROL_ALC, wm8776_ngth_db_scale), 1028 LC_CONTROL_ALC, wm8776_ngth_db_scale),
957}; 1029};
958 1030
959static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
960{
961 if (!strncmp(template->name, "CD Capture ", 11))
962 return 1; /* no CD input */
963 return 0;
964}
965
966static int xonar_ds_mixer_init(struct oxygen *chip) 1031static int xonar_ds_mixer_init(struct oxygen *chip)
967{ 1032{
968 struct xonar_wm87x6 *data = chip->model_data; 1033 struct xonar_wm87x6 *data = chip->model_data;
@@ -999,10 +1064,9 @@ static int xonar_ds_mixer_init(struct oxygen *chip)
999 1064
1000static const struct oxygen_model model_xonar_ds = { 1065static const struct oxygen_model model_xonar_ds = {
1001 .shortname = "Xonar DS", 1066 .shortname = "Xonar DS",
1002 .longname = "Asus Virtuoso 200", 1067 .longname = "Asus Virtuoso 66",
1003 .chip = "AV200", 1068 .chip = "AV200",
1004 .init = xonar_ds_init, 1069 .init = xonar_ds_init,
1005 .control_filter = xonar_ds_control_filter,
1006 .mixer_init = xonar_ds_mixer_init, 1070 .mixer_init = xonar_ds_mixer_init,
1007 .cleanup = xonar_ds_cleanup, 1071 .cleanup = xonar_ds_cleanup,
1008 .suspend = xonar_ds_suspend, 1072 .suspend = xonar_ds_suspend,
@@ -1013,6 +1077,7 @@ static const struct oxygen_model model_xonar_ds = {
1013 .set_adc_params = set_wm8776_adc_params, 1077 .set_adc_params = set_wm8776_adc_params,
1014 .update_dac_volume = update_wm87x6_volume, 1078 .update_dac_volume = update_wm87x6_volume,
1015 .update_dac_mute = update_wm87x6_mute, 1079 .update_dac_mute = update_wm87x6_mute,
1080 .update_center_lfe_mix = update_wm8766_center_lfe_mix,
1016 .gpio_changed = xonar_ds_gpio_changed, 1081 .gpio_changed = xonar_ds_gpio_changed,
1017 .dac_tlv = wm87x6_dac_db_scale, 1082 .dac_tlv = wm87x6_dac_db_scale,
1018 .model_data_size = sizeof(struct xonar_wm87x6), 1083 .model_data_size = sizeof(struct xonar_wm87x6),
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index d19dc052c391..d5f5b440fc40 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1527,14 +1527,14 @@ snd_rme96_free(void *private_data)
1527static void 1527static void
1528snd_rme96_free_spdif_pcm(struct snd_pcm *pcm) 1528snd_rme96_free_spdif_pcm(struct snd_pcm *pcm)
1529{ 1529{
1530 struct rme96 *rme96 = (struct rme96 *) pcm->private_data; 1530 struct rme96 *rme96 = pcm->private_data;
1531 rme96->spdif_pcm = NULL; 1531 rme96->spdif_pcm = NULL;
1532} 1532}
1533 1533
1534static void 1534static void
1535snd_rme96_free_adat_pcm(struct snd_pcm *pcm) 1535snd_rme96_free_adat_pcm(struct snd_pcm *pcm)
1536{ 1536{
1537 struct rme96 *rme96 = (struct rme96 *) pcm->private_data; 1537 struct rme96 *rme96 = pcm->private_data;
1538 rme96->adat_pcm = NULL; 1538 rme96->adat_pcm = NULL;
1539} 1539}
1540 1540
@@ -1661,7 +1661,7 @@ static void
1661snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 1661snd_rme96_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
1662{ 1662{
1663 int n; 1663 int n;
1664 struct rme96 *rme96 = (struct rme96 *)entry->private_data; 1664 struct rme96 *rme96 = entry->private_data;
1665 1665
1666 rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER); 1666 rme96->rcreg = readl(rme96->iobase + RME96_IO_CONTROL_REGISTER);
1667 1667
@@ -2348,7 +2348,7 @@ snd_rme96_probe(struct pci_dev *pci,
2348 if (err < 0) 2348 if (err < 0)
2349 return err; 2349 return err;
2350 card->private_free = snd_rme96_card_free; 2350 card->private_free = snd_rme96_card_free;
2351 rme96 = (struct rme96 *)card->private_data; 2351 rme96 = card->private_data;
2352 rme96->card = card; 2352 rme96->card = card;
2353 rme96->pci = pci; 2353 rme96->pci = pci;
2354 snd_card_set_dev(card, &pci->dev); 2354 snd_card_set_dev(card, &pci->dev);
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index d6fa7bfd9aa1..0b720cf7783e 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3284,7 +3284,7 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
3284static void 3284static void
3285snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) 3285snd_hdsp_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
3286{ 3286{
3287 struct hdsp *hdsp = (struct hdsp *) entry->private_data; 3287 struct hdsp *hdsp = entry->private_data;
3288 unsigned int status; 3288 unsigned int status;
3289 unsigned int status2; 3289 unsigned int status2;
3290 char *pref_sync_ref; 3290 char *pref_sync_ref;
@@ -4566,7 +4566,7 @@ static int hdsp_get_peak(struct hdsp *hdsp, struct hdsp_peak_rms __user *peak_rm
4566 4566
4567static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg) 4567static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigned int cmd, unsigned long arg)
4568{ 4568{
4569 struct hdsp *hdsp = (struct hdsp *)hw->private_data; 4569 struct hdsp *hdsp = hw->private_data;
4570 void __user *argp = (void __user *)arg; 4570 void __user *argp = (void __user *)arg;
4571 int err; 4571 int err;
4572 4572
@@ -5156,7 +5156,7 @@ static int snd_hdsp_free(struct hdsp *hdsp)
5156 5156
5157static void snd_hdsp_card_free(struct snd_card *card) 5157static void snd_hdsp_card_free(struct snd_card *card)
5158{ 5158{
5159 struct hdsp *hdsp = (struct hdsp *) card->private_data; 5159 struct hdsp *hdsp = card->private_data;
5160 5160
5161 if (hdsp) 5161 if (hdsp)
5162 snd_hdsp_free(hdsp); 5162 snd_hdsp_free(hdsp);
@@ -5182,7 +5182,7 @@ static int __devinit snd_hdsp_probe(struct pci_dev *pci,
5182 if (err < 0) 5182 if (err < 0)
5183 return err; 5183 return err;
5184 5184
5185 hdsp = (struct hdsp *) card->private_data; 5185 hdsp = card->private_data;
5186 card->private_free = snd_hdsp_card_free; 5186 card->private_free = snd_hdsp_card_free;
5187 hdsp->dev = dev; 5187 hdsp->dev = dev;
5188 hdsp->pci = pci; 5188 hdsp->pci = pci;
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 20afdf9772ee..961d98297695 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -785,7 +785,7 @@ static int snapper_set_capture_source(struct pmac_tumbler *mix)
785 if (! mix->i2c.client) 785 if (! mix->i2c.client)
786 return -ENODEV; 786 return -ENODEV;
787 if (mix->capture_source) 787 if (mix->capture_source)
788 mix->acs = mix->acs |= 2; 788 mix->acs |= 2;
789 else 789 else
790 mix->acs &= ~2; 790 mix->acs &= ~2;
791 return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs); 791 return i2c_smbus_write_byte_data(mix->i2c.client, TAS_REG_ACS, mix->acs);
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index dc5249fba85c..d0e75323ec19 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -179,7 +179,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
179 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 179 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
180 runtime->dma_bytes = params_buffer_bytes(params); 180 runtime->dma_bytes = params_buffer_bytes(params);
181 181
182 prtd->params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 182 prtd->params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
183 prtd->params->dma_intr_handler = atmel_pcm_dma_irq; 183 prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
184 184
185 prtd->dma_buffer = runtime->dma_addr; 185 prtd->dma_buffer = runtime->dma_addr;
@@ -374,14 +374,14 @@ static int atmel_pcm_new(struct snd_card *card,
374 if (!card->dev->coherent_dma_mask) 374 if (!card->dev->coherent_dma_mask)
375 card->dev->coherent_dma_mask = 0xffffffff; 375 card->dev->coherent_dma_mask = 0xffffffff;
376 376
377 if (dai->playback.channels_min) { 377 if (dai->driver->playback.channels_min) {
378 ret = atmel_pcm_preallocate_dma_buffer(pcm, 378 ret = atmel_pcm_preallocate_dma_buffer(pcm,
379 SNDRV_PCM_STREAM_PLAYBACK); 379 SNDRV_PCM_STREAM_PLAYBACK);
380 if (ret) 380 if (ret)
381 goto out; 381 goto out;
382 } 382 }
383 383
384 if (dai->capture.channels_min) { 384 if (dai->driver->capture.channels_min) {
385 pr_debug("at32-pcm:" 385 pr_debug("at32-pcm:"
386 "Allocating PCM capture DMA buffer\n"); 386 "Allocating PCM capture DMA buffer\n");
387 ret = atmel_pcm_preallocate_dma_buffer(pcm, 387 ret = atmel_pcm_preallocate_dma_buffer(pcm,
@@ -414,12 +414,9 @@ static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
414} 414}
415 415
416#ifdef CONFIG_PM 416#ifdef CONFIG_PM
417static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link) 417static int atmel_pcm_suspend(struct snd_soc_dai *dai)
418{ 418{
419 struct snd_pcm *pcm = dai_link->pcm; 419 struct snd_pcm_runtime *runtime = dai->runtime;
420 struct snd_pcm_str *stream = &pcm->streams[0];
421 struct snd_pcm_substream *substream = stream->substream;
422 struct snd_pcm_runtime *runtime = substream->runtime;
423 struct atmel_runtime_data *prtd; 420 struct atmel_runtime_data *prtd;
424 struct atmel_pcm_dma_params *params; 421 struct atmel_pcm_dma_params *params;
425 422
@@ -441,12 +438,9 @@ static int atmel_pcm_suspend(struct snd_soc_dai_link *dai_link)
441 return 0; 438 return 0;
442} 439}
443 440
444static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link) 441static int atmel_pcm_resume(struct snd_soc_dai *dai)
445{ 442{
446 struct snd_pcm *pcm = dai_link->pcm; 443 struct snd_pcm_runtime *runtime = dai->runtime;
447 struct snd_pcm_str *stream = &pcm->streams[0];
448 struct snd_pcm_substream *substream = stream->substream;
449 struct snd_pcm_runtime *runtime = substream->runtime;
450 struct atmel_runtime_data *prtd; 444 struct atmel_runtime_data *prtd;
451 struct atmel_pcm_dma_params *params; 445 struct atmel_pcm_dma_params *params;
452 446
@@ -470,27 +464,46 @@ static int atmel_pcm_resume(struct snd_soc_dai_link *dai_link)
470#define atmel_pcm_resume NULL 464#define atmel_pcm_resume NULL
471#endif 465#endif
472 466
473struct snd_soc_platform atmel_soc_platform = { 467static struct snd_soc_platform_driver atmel_soc_platform = {
474 .name = "atmel-audio", 468 .ops = &atmel_pcm_ops,
475 .pcm_ops = &atmel_pcm_ops,
476 .pcm_new = atmel_pcm_new, 469 .pcm_new = atmel_pcm_new,
477 .pcm_free = atmel_pcm_free_dma_buffers, 470 .pcm_free = atmel_pcm_free_dma_buffers,
478 .suspend = atmel_pcm_suspend, 471 .suspend = atmel_pcm_suspend,
479 .resume = atmel_pcm_resume, 472 .resume = atmel_pcm_resume,
480}; 473};
481EXPORT_SYMBOL_GPL(atmel_soc_platform);
482 474
483static int __init atmel_pcm_modinit(void) 475static int __devinit atmel_soc_platform_probe(struct platform_device *pdev)
476{
477 return snd_soc_register_platform(&pdev->dev, &atmel_soc_platform);
478}
479
480static int __devexit atmel_soc_platform_remove(struct platform_device *pdev)
481{
482 snd_soc_unregister_platform(&pdev->dev);
483 return 0;
484}
485
486static struct platform_driver atmel_pcm_driver = {
487 .driver = {
488 .name = "atmel-pcm-audio",
489 .owner = THIS_MODULE,
490 },
491
492 .probe = atmel_soc_platform_probe,
493 .remove = __devexit_p(atmel_soc_platform_remove),
494};
495
496static int __init snd_atmel_pcm_init(void)
484{ 497{
485 return snd_soc_register_platform(&atmel_soc_platform); 498 return platform_driver_register(&atmel_pcm_driver);
486} 499}
487module_init(atmel_pcm_modinit); 500module_init(snd_atmel_pcm_init);
488 501
489static void __exit atmel_pcm_modexit(void) 502static void __exit snd_atmel_pcm_exit(void)
490{ 503{
491 snd_soc_unregister_platform(&atmel_soc_platform); 504 platform_driver_unregister(&atmel_pcm_driver);
492} 505}
493module_exit(atmel_pcm_modexit); 506module_exit(snd_atmel_pcm_exit);
494 507
495MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); 508MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
496MODULE_DESCRIPTION("Atmel PCM module"); 509MODULE_DESCRIPTION("Atmel PCM module");
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h
index ec9b2824b663..2597329302e7 100644
--- a/sound/soc/atmel/atmel-pcm.h
+++ b/sound/soc/atmel/atmel-pcm.h
@@ -74,9 +74,6 @@ struct atmel_pcm_dma_params {
74 void (*dma_intr_handler)(u32, struct snd_pcm_substream *); 74 void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
75}; 75};
76 76
77extern struct snd_soc_platform atmel_soc_platform;
78
79
80/* 77/*
81 * SSC register access (since ssc_writel() / ssc_readl() require literal name) 78 * SSC register access (since ssc_writel() / ssc_readl() require literal name)
82 */ 79 */
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index c85844d4845b..5d230cee3fa7 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -205,8 +205,7 @@ static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
205static int atmel_ssc_startup(struct snd_pcm_substream *substream, 205static int atmel_ssc_startup(struct snd_pcm_substream *substream,
206 struct snd_soc_dai *dai) 206 struct snd_soc_dai *dai)
207{ 207{
208 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 208 struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
209 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
210 int dir_mask; 209 int dir_mask;
211 210
212 pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", 211 pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
@@ -235,8 +234,7 @@ static int atmel_ssc_startup(struct snd_pcm_substream *substream,
235static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, 234static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
236 struct snd_soc_dai *dai) 235 struct snd_soc_dai *dai)
237{ 236{
238 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 237 struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
239 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
240 struct atmel_pcm_dma_params *dma_params; 238 struct atmel_pcm_dma_params *dma_params;
241 int dir, dir_mask; 239 int dir, dir_mask;
242 240
@@ -338,7 +336,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
338 struct snd_soc_dai *dai) 336 struct snd_soc_dai *dai)
339{ 337{
340 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 338 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
341 int id = rtd->dai->cpu_dai->id; 339 int id = dai->id;
342 struct atmel_ssc_info *ssc_p = &ssc_info[id]; 340 struct atmel_ssc_info *ssc_p = &ssc_info[id];
343 struct atmel_pcm_dma_params *dma_params; 341 struct atmel_pcm_dma_params *dma_params;
344 int dir, channels, bits; 342 int dir, channels, bits;
@@ -368,7 +366,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
368 * function. It should not be used for other purposes 366 * function. It should not be used for other purposes
369 * as it is common to all substreams. 367 * as it is common to all substreams.
370 */ 368 */
371 snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_params); 369 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_params);
372 370
373 channels = params_channels(params); 371 channels = params_channels(params);
374 372
@@ -605,8 +603,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
605static int atmel_ssc_prepare(struct snd_pcm_substream *substream, 603static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
606 struct snd_soc_dai *dai) 604 struct snd_soc_dai *dai)
607{ 605{
608 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 606 struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
609 struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
610 struct atmel_pcm_dma_params *dma_params; 607 struct atmel_pcm_dma_params *dma_params;
611 int dir; 608 int dir;
612 609
@@ -690,6 +687,32 @@ static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
690# define atmel_ssc_resume NULL 687# define atmel_ssc_resume NULL
691#endif /* CONFIG_PM */ 688#endif /* CONFIG_PM */
692 689
690static int atmel_ssc_probe(struct snd_soc_dai *dai)
691{
692 struct atmel_ssc_info *ssc_p = &ssc_info[dai->id];
693 int ret = 0;
694
695 snd_soc_dai_set_drvdata(dai, ssc_p);
696
697 /*
698 * Request SSC device
699 */
700 ssc_p->ssc = ssc_request(dai->id);
701 if (IS_ERR(ssc_p->ssc)) {
702 printk(KERN_ERR "ASoC: Failed to request SSC %d\n", dai->id);
703 ret = PTR_ERR(ssc_p->ssc);
704 }
705
706 return ret;
707}
708
709static int atmel_ssc_remove(struct snd_soc_dai *dai)
710{
711 struct atmel_ssc_info *ssc_p = snd_soc_dai_get_drvdata(dai);
712
713 ssc_free(ssc_p->ssc);
714 return 0;
715}
693 716
694#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000) 717#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
695 718
@@ -705,9 +728,11 @@ static struct snd_soc_dai_ops atmel_ssc_dai_ops = {
705 .set_clkdiv = atmel_ssc_set_dai_clkdiv, 728 .set_clkdiv = atmel_ssc_set_dai_clkdiv,
706}; 729};
707 730
708struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { 731static struct snd_soc_dai_driver atmel_ssc_dai[NUM_SSC_DEVICES] = {
709 { .name = "atmel-ssc0", 732 {
710 .id = 0, 733 .name = "atmel-ssc-dai.0",
734 .probe = atmel_ssc_probe,
735 .remove = atmel_ssc_remove,
711 .suspend = atmel_ssc_suspend, 736 .suspend = atmel_ssc_suspend,
712 .resume = atmel_ssc_resume, 737 .resume = atmel_ssc_resume,
713 .playback = { 738 .playback = {
@@ -721,11 +746,12 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
721 .rates = ATMEL_SSC_RATES, 746 .rates = ATMEL_SSC_RATES,
722 .formats = ATMEL_SSC_FORMATS,}, 747 .formats = ATMEL_SSC_FORMATS,},
723 .ops = &atmel_ssc_dai_ops, 748 .ops = &atmel_ssc_dai_ops,
724 .private_data = &ssc_info[0],
725 }, 749 },
726#if NUM_SSC_DEVICES == 3 750#if NUM_SSC_DEVICES == 3
727 { .name = "atmel-ssc1", 751 {
728 .id = 1, 752 .name = "atmel-ssc-dai.1",
753 .probe = atmel_ssc_probe,
754 .remove = atmel_ssc_remove,
729 .suspend = atmel_ssc_suspend, 755 .suspend = atmel_ssc_suspend,
730 .resume = atmel_ssc_resume, 756 .resume = atmel_ssc_resume,
731 .playback = { 757 .playback = {
@@ -739,10 +765,11 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
739 .rates = ATMEL_SSC_RATES, 765 .rates = ATMEL_SSC_RATES,
740 .formats = ATMEL_SSC_FORMATS,}, 766 .formats = ATMEL_SSC_FORMATS,},
741 .ops = &atmel_ssc_dai_ops, 767 .ops = &atmel_ssc_dai_ops,
742 .private_data = &ssc_info[1],
743 }, 768 },
744 { .name = "atmel-ssc2", 769 {
745 .id = 2, 770 .name = "atmel-ssc-dai.2",
771 .probe = atmel_ssc_probe,
772 .remove = atmel_ssc_remove,
746 .suspend = atmel_ssc_suspend, 773 .suspend = atmel_ssc_suspend,
747 .resume = atmel_ssc_resume, 774 .resume = atmel_ssc_resume,
748 .playback = { 775 .playback = {
@@ -756,23 +783,94 @@ struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
756 .rates = ATMEL_SSC_RATES, 783 .rates = ATMEL_SSC_RATES,
757 .formats = ATMEL_SSC_FORMATS,}, 784 .formats = ATMEL_SSC_FORMATS,},
758 .ops = &atmel_ssc_dai_ops, 785 .ops = &atmel_ssc_dai_ops,
759 .private_data = &ssc_info[2],
760 }, 786 },
761#endif 787#endif
762}; 788};
763EXPORT_SYMBOL_GPL(atmel_ssc_dai);
764 789
765static int __init atmel_ssc_modinit(void) 790static __devinit int asoc_ssc_probe(struct platform_device *pdev)
791{
792 BUG_ON(pdev->id < 0);
793 BUG_ON(pdev->id >= ARRAY_SIZE(atmel_ssc_dai));
794 return snd_soc_register_dai(&pdev->dev, &atmel_ssc_dai[pdev->id]);
795}
796
797static int __devexit asoc_ssc_remove(struct platform_device *pdev)
798{
799 snd_soc_unregister_dai(&pdev->dev);
800 return 0;
801}
802
803static struct platform_driver asoc_ssc_driver = {
804 .driver = {
805 .name = "atmel-ssc-dai",
806 .owner = THIS_MODULE,
807 },
808
809 .probe = asoc_ssc_probe,
810 .remove = __devexit_p(asoc_ssc_remove),
811};
812
813/**
814 * atmel_ssc_set_audio - Allocate the specified SSC for audio use.
815 */
816int atmel_ssc_set_audio(int ssc_id)
817{
818 struct ssc_device *ssc;
819 static struct platform_device *dma_pdev;
820 struct platform_device *ssc_pdev;
821 int ret;
822
823 if (ssc_id < 0 || ssc_id >= ARRAY_SIZE(atmel_ssc_dai))
824 return -EINVAL;
825
826 /* Allocate a dummy device for DMA if we don't have one already */
827 if (!dma_pdev) {
828 dma_pdev = platform_device_alloc("atmel-pcm-audio", -1);
829 if (!dma_pdev)
830 return -ENOMEM;
831
832 ret = platform_device_add(dma_pdev);
833 if (ret < 0) {
834 platform_device_put(dma_pdev);
835 dma_pdev = NULL;
836 return ret;
837 }
838 }
839
840 ssc_pdev = platform_device_alloc("atmel-ssc-dai", ssc_id);
841 if (!ssc_pdev) {
842 ssc_free(ssc);
843 return -ENOMEM;
844 }
845
846 /* If we can grab the SSC briefly to parent the DAI device off it */
847 ssc = ssc_request(ssc_id);
848 if (IS_ERR(ssc))
849 pr_warn("Unable to parent ASoC SSC DAI on SSC: %ld\n",
850 PTR_ERR(ssc));
851 else
852 ssc_pdev->dev.parent = &(ssc->pdev->dev);
853 ssc_free(ssc);
854
855 ret = platform_device_add(ssc_pdev);
856 if (ret < 0)
857 platform_device_put(ssc_pdev);
858
859 return ret;
860}
861EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
862
863static int __init snd_atmel_ssc_init(void)
766{ 864{
767 return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); 865 return platform_driver_register(&asoc_ssc_driver);
768} 866}
769module_init(atmel_ssc_modinit); 867module_init(snd_atmel_ssc_init);
770 868
771static void __exit atmel_ssc_modexit(void) 869static void __exit snd_atmel_ssc_exit(void)
772{ 870{
773 snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); 871 platform_driver_unregister(&asoc_ssc_driver);
774} 872}
775module_exit(atmel_ssc_modexit); 873module_exit(snd_atmel_ssc_exit);
776 874
777/* Module information */ 875/* Module information */
778MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); 876MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
index 391135f9c6c1..5d4f0f9b4d9a 100644
--- a/sound/soc/atmel/atmel_ssc_dai.h
+++ b/sound/soc/atmel/atmel_ssc_dai.h
@@ -116,6 +116,7 @@ struct atmel_ssc_info {
116 struct atmel_pcm_dma_params *dma_params[2]; 116 struct atmel_pcm_dma_params *dma_params[2];
117 struct atmel_ssc_state ssc_state; 117 struct atmel_ssc_state ssc_state;
118}; 118};
119extern struct snd_soc_dai atmel_ssc_dai[]; 119
120int atmel_ssc_set_audio(int ssc);
120 121
121#endif /* _AT91_SSC_DAI_H */ 122#endif /* _AT91_SSC_DAI_H */
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index 9df4c68ef000..5f4e59f4461c 100644
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -83,7 +83,7 @@ static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
83 struct snd_pcm_hw_params *params, 83 struct snd_pcm_hw_params *params,
84 struct snd_soc_dai *cpu_dai) 84 struct snd_soc_dai *cpu_dai)
85{ 85{
86 struct at32_ssc_info *ssc_p = cpu_dai->private_data; 86 struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
87 struct ssc_device *ssc = ssc_p->ssc; 87 struct ssc_device *ssc = ssc_p->ssc;
88 struct ssc_clock_data cd; 88 struct ssc_clock_data cd;
89 unsigned int rate, width_bits, channels; 89 unsigned int rate, width_bits, channels;
@@ -131,9 +131,9 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
131 struct snd_pcm_hw_params *params) 131 struct snd_pcm_hw_params *params)
132{ 132{
133 struct snd_soc_pcm_runtime *rtd = substream->private_data; 133 struct snd_soc_pcm_runtime *rtd = substream->private_data;
134 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 134 struct snd_soc_dai *codec_dai = rtd->codec_dai;
135 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 135 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
136 struct at32_ssc_info *ssc_p = cpu_dai->private_data; 136 struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
137 struct ssc_device *ssc = ssc_p->ssc; 137 struct ssc_device *ssc = ssc_p->ssc;
138 unsigned int pll_out = 0, bclk = 0, mclk_div = 0; 138 unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
139 int ret; 139 int ret;
@@ -315,8 +315,9 @@ static const struct snd_soc_dapm_route intercon[] = {
315 315
316 316
317 317
318static int playpaq_wm8510_init(struct snd_soc_codec *codec) 318static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
319{ 319{
320 struct snd_soc_codec *codec = rtd->codec;
320 int i; 321 int i;
321 322
322 /* 323 /*
@@ -342,7 +343,7 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)
342 343
343 344
344 /* Make CSB show PLL rate */ 345 /* Make CSB show PLL rate */
345 snd_soc_dai_set_clkdiv(codec->dai, WM8510_OPCLKDIV, 346 snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV,
346 WM8510_OPCLKDIV_1 | 4); 347 WM8510_OPCLKDIV_1 | 4);
347 348
348 return 0; 349 return 0;
@@ -353,8 +354,10 @@ static int playpaq_wm8510_init(struct snd_soc_codec *codec)
353static struct snd_soc_dai_link playpaq_wm8510_dai = { 354static struct snd_soc_dai_link playpaq_wm8510_dai = {
354 .name = "WM8510", 355 .name = "WM8510",
355 .stream_name = "WM8510 PCM", 356 .stream_name = "WM8510 PCM",
356 .cpu_dai = &at32_ssc_dai[0], 357 .cpu_dai_name= "atmel-ssc-dai.0",
357 .codec_dai = &wm8510_dai, 358 .platform_name = "atmel-pcm-audio",
359 .codec_name = "wm8510-codec.0-0x1a",
360 .codec_dai_name = "wm8510-hifi",
358 .init = playpaq_wm8510_init, 361 .init = playpaq_wm8510_init,
359 .ops = &playpaq_wm8510_ops, 362 .ops = &playpaq_wm8510_ops,
360}; 363};
@@ -363,46 +366,16 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = {
363 366
364static struct snd_soc_card snd_soc_playpaq = { 367static struct snd_soc_card snd_soc_playpaq = {
365 .name = "LRS_PlayPaq_WM8510", 368 .name = "LRS_PlayPaq_WM8510",
366 .platform = &at32_soc_platform,
367 .dai_link = &playpaq_wm8510_dai, 369 .dai_link = &playpaq_wm8510_dai,
368 .num_links = 1, 370 .num_links = 1,
369}; 371};
370 372
371
372
373static struct wm8510_setup_data playpaq_wm8510_setup = {
374 .i2c_bus = 0,
375 .i2c_address = 0x1a,
376};
377
378
379
380static struct snd_soc_device playpaq_wm8510_snd_devdata = {
381 .card = &snd_soc_playpaq,
382 .codec_dev = &soc_codec_dev_wm8510,
383 .codec_data = &playpaq_wm8510_setup,
384};
385
386static struct platform_device *playpaq_snd_device; 373static struct platform_device *playpaq_snd_device;
387 374
388 375
389static int __init playpaq_asoc_init(void) 376static int __init playpaq_asoc_init(void)
390{ 377{
391 int ret = 0; 378 int ret = 0;
392 struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
393 struct ssc_device *ssc = NULL;
394
395
396 /*
397 * Request SSC device
398 */
399 ssc = ssc_request(0);
400 if (IS_ERR(ssc)) {
401 ret = PTR_ERR(ssc);
402 goto err_ssc;
403 }
404 ssc_p->ssc = ssc;
405
406 379
407 /* 380 /*
408 * Configure MCLK for WM8510 381 * Configure MCLK for WM8510
@@ -439,8 +412,7 @@ static int __init playpaq_asoc_init(void)
439 goto err_device_alloc; 412 goto err_device_alloc;
440 } 413 }
441 414
442 platform_set_drvdata(playpaq_snd_device, &playpaq_wm8510_snd_devdata); 415 platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq);
443 playpaq_wm8510_snd_devdata.dev = &playpaq_snd_device->dev;
444 416
445 ret = platform_device_add(playpaq_snd_device); 417 ret = platform_device_add(playpaq_snd_device);
446 if (ret) { 418 if (ret) {
@@ -468,25 +440,12 @@ err_pll0:
468 clk_put(_gclk0); 440 clk_put(_gclk0);
469 _gclk0 = NULL; 441 _gclk0 = NULL;
470 } 442 }
471err_gclk0:
472 ssc_free(ssc);
473err_ssc:
474 return ret; 443 return ret;
475} 444}
476 445
477 446
478static void __exit playpaq_asoc_exit(void) 447static void __exit playpaq_asoc_exit(void)
479{ 448{
480 struct at32_ssc_info *ssc_p = playpaq_wm8510_dai.cpu_dai->private_data;
481 struct ssc_device *ssc;
482
483 if (ssc_p != NULL) {
484 ssc = ssc_p->ssc;
485 if (ssc != NULL)
486 ssc_free(ssc);
487 ssc_p->ssc = NULL;
488 }
489
490 if (_gclk0 != NULL) { 449 if (_gclk0 != NULL) {
491 clk_put(_gclk0); 450 clk_put(_gclk0);
492 _gclk0 = NULL; 451 _gclk0 = NULL;
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index e028744c32ce..293569dfd0ed 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -69,8 +69,8 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
69 struct snd_pcm_hw_params *params) 69 struct snd_pcm_hw_params *params)
70{ 70{
71 struct snd_soc_pcm_runtime *rtd = substream->private_data; 71 struct snd_soc_pcm_runtime *rtd = substream->private_data;
72 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 72 struct snd_soc_dai *codec_dai = rtd->codec_dai;
73 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 73 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
74 int ret; 74 int ret;
75 75
76 /* set codec DAI configuration */ 76 /* set codec DAI configuration */
@@ -136,16 +136,17 @@ static const struct snd_soc_dapm_route intercon[] = {
136/* 136/*
137 * Logic for a wm8731 as connected on a at91sam9g20ek board. 137 * Logic for a wm8731 as connected on a at91sam9g20ek board.
138 */ 138 */
139static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) 139static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
140{ 140{
141 struct snd_soc_dai *codec_dai = &codec->dai[0]; 141 struct snd_soc_codec *codec = rtd->codec;
142 struct snd_soc_dai *codec_dai = rtd->codec_dai;
142 int ret; 143 int ret;
143 144
144 printk(KERN_DEBUG 145 printk(KERN_DEBUG
145 "at91sam9g20ek_wm8731 " 146 "at91sam9g20ek_wm8731 "
146 ": at91sam9g20ek_wm8731_init() called\n"); 147 ": at91sam9g20ek_wm8731_init() called\n");
147 148
148 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, 149 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
149 MCLK_RATE, SND_SOC_CLOCK_IN); 150 MCLK_RATE, SND_SOC_CLOCK_IN);
150 if (ret < 0) { 151 if (ret < 0) {
151 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); 152 printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret);
@@ -179,37 +180,37 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
179static struct snd_soc_dai_link at91sam9g20ek_dai = { 180static struct snd_soc_dai_link at91sam9g20ek_dai = {
180 .name = "WM8731", 181 .name = "WM8731",
181 .stream_name = "WM8731 PCM", 182 .stream_name = "WM8731 PCM",
182 .cpu_dai = &atmel_ssc_dai[0], 183 .cpu_dai_name = "atmel-ssc-dai.0",
183 .codec_dai = &wm8731_dai, 184 .codec_dai_name = "wm8731-hifi",
184 .init = at91sam9g20ek_wm8731_init, 185 .init = at91sam9g20ek_wm8731_init,
186 .platform_name = "atmel-pcm-audio",
187 .codec_name = "wm8731-codec.0-001b",
185 .ops = &at91sam9g20ek_ops, 188 .ops = &at91sam9g20ek_ops,
186}; 189};
187 190
188static struct snd_soc_card snd_soc_at91sam9g20ek = { 191static struct snd_soc_card snd_soc_at91sam9g20ek = {
189 .name = "AT91SAMG20-EK", 192 .name = "AT91SAMG20-EK",
190 .platform = &atmel_soc_platform,
191 .dai_link = &at91sam9g20ek_dai, 193 .dai_link = &at91sam9g20ek_dai,
192 .num_links = 1, 194 .num_links = 1,
193 .set_bias_level = at91sam9g20ek_set_bias_level, 195 .set_bias_level = at91sam9g20ek_set_bias_level,
194}; 196};
195 197
196static struct snd_soc_device at91sam9g20ek_snd_devdata = {
197 .card = &snd_soc_at91sam9g20ek,
198 .codec_dev = &soc_codec_dev_wm8731,
199};
200
201static struct platform_device *at91sam9g20ek_snd_device; 198static struct platform_device *at91sam9g20ek_snd_device;
202 199
203static int __init at91sam9g20ek_init(void) 200static int __init at91sam9g20ek_init(void)
204{ 201{
205 struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
206 struct ssc_device *ssc = NULL;
207 struct clk *pllb; 202 struct clk *pllb;
208 int ret; 203 int ret;
209 204
210 if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc())) 205 if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
211 return -ENODEV; 206 return -ENODEV;
212 207
208 ret = atmel_ssc_set_audio(0);
209 if (ret != 0) {
210 pr_err("Failed to set SSC 0 for audio: %d\n", ret);
211 return ret;
212 }
213
213 /* 214 /*
214 * Codec MCLK is supplied by PCK0 - set it up. 215 * Codec MCLK is supplied by PCK0 - set it up.
215 */ 216 */
@@ -235,18 +236,6 @@ static int __init at91sam9g20ek_init(void)
235 236
236 clk_set_rate(mclk, MCLK_RATE); 237 clk_set_rate(mclk, MCLK_RATE);
237 238
238 /*
239 * Request SSC device
240 */
241 ssc = ssc_request(0);
242 if (IS_ERR(ssc)) {
243 printk(KERN_ERR "ASoC: Failed to request SSC 0\n");
244 ret = PTR_ERR(ssc);
245 ssc = NULL;
246 goto err_ssc;
247 }
248 ssc_p->ssc = ssc;
249
250 at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); 239 at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
251 if (!at91sam9g20ek_snd_device) { 240 if (!at91sam9g20ek_snd_device) {
252 printk(KERN_ERR "ASoC: Platform device allocation failed\n"); 241 printk(KERN_ERR "ASoC: Platform device allocation failed\n");
@@ -254,8 +243,7 @@ static int __init at91sam9g20ek_init(void)
254 } 243 }
255 244
256 platform_set_drvdata(at91sam9g20ek_snd_device, 245 platform_set_drvdata(at91sam9g20ek_snd_device,
257 &at91sam9g20ek_snd_devdata); 246 &snd_soc_at91sam9g20ek);
258 at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev;
259 247
260 ret = platform_device_add(at91sam9g20ek_snd_device); 248 ret = platform_device_add(at91sam9g20ek_snd_device);
261 if (ret) { 249 if (ret) {
@@ -265,9 +253,6 @@ static int __init at91sam9g20ek_init(void)
265 253
266 return ret; 254 return ret;
267 255
268err_ssc:
269 ssc_free(ssc);
270 ssc_p->ssc = NULL;
271err_mclk: 256err_mclk:
272 clk_put(mclk); 257 clk_put(mclk);
273 mclk = NULL; 258 mclk = NULL;
@@ -277,16 +262,6 @@ err:
277 262
278static void __exit at91sam9g20ek_exit(void) 263static void __exit at91sam9g20ek_exit(void)
279{ 264{
280 struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
281 struct ssc_device *ssc;
282
283 if (ssc_p != NULL) {
284 ssc = ssc_p->ssc;
285 if (ssc != NULL)
286 ssc_free(ssc);
287 ssc_p->ssc = NULL;
288 }
289
290 platform_device_unregister(at91sam9g20ek_snd_device); 265 platform_device_unregister(at91sam9g20ek_snd_device);
291 at91sam9g20ek_snd_device = NULL; 266 at91sam9g20ek_snd_device = NULL;
292 clk_put(mclk); 267 clk_put(mclk);
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c
index 23349de27313..e3d283561c19 100644
--- a/sound/soc/atmel/snd-soc-afeb9260.c
+++ b/sound/soc/atmel/snd-soc-afeb9260.c
@@ -46,8 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream,
46 struct snd_pcm_hw_params *params) 46 struct snd_pcm_hw_params *params)
47{ 47{
48 struct snd_soc_pcm_runtime *rtd = substream->private_data; 48 struct snd_soc_pcm_runtime *rtd = substream->private_data;
49 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 49 struct snd_soc_dai *codec_dai = rtd->codec_dai;
50 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 50 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
51 int err; 51 int err;
52 52
53 /* Set codec DAI configuration */ 53 /* Set codec DAI configuration */
@@ -102,8 +102,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
102 {"MICIN", NULL, "Mic Jack"}, 102 {"MICIN", NULL, "Mic Jack"},
103}; 103};
104 104
105static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec) 105static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
106{ 106{
107 struct snd_soc_codec *codec = rtd->codec;
107 108
108 /* Add afeb9260 specific widgets */ 109 /* Add afeb9260 specific widgets */
109 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, 110 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
@@ -125,8 +126,10 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_codec *codec)
125static struct snd_soc_dai_link afeb9260_dai = { 126static struct snd_soc_dai_link afeb9260_dai = {
126 .name = "TLV320AIC23", 127 .name = "TLV320AIC23",
127 .stream_name = "AIC23", 128 .stream_name = "AIC23",
128 .cpu_dai = &atmel_ssc_dai[0], 129 .cpu_dai_name = "atmel-ssc-dai.0",
129 .codec_dai = &tlv320aic23_dai, 130 .codec_dai_name = "tlv320aic23-hifi",
131 .platform_name = "atmel_pcm-audio",
132 .codec_name = "tlv320aic23-codec.0-0x1a",
130 .init = afeb9260_tlv320aic23_init, 133 .init = afeb9260_tlv320aic23_init,
131 .ops = &afeb9260_ops, 134 .ops = &afeb9260_ops,
132}; 135};
@@ -134,37 +137,20 @@ static struct snd_soc_dai_link afeb9260_dai = {
134/* Audio machine driver */ 137/* Audio machine driver */
135static struct snd_soc_card snd_soc_machine_afeb9260 = { 138static struct snd_soc_card snd_soc_machine_afeb9260 = {
136 .name = "AFEB9260", 139 .name = "AFEB9260",
137 .platform = &atmel_soc_platform,
138 .dai_link = &afeb9260_dai, 140 .dai_link = &afeb9260_dai,
139 .num_links = 1, 141 .num_links = 1,
140}; 142};
141 143
142/* Audio subsystem */
143static struct snd_soc_device afeb9260_snd_devdata = {
144 .card = &snd_soc_machine_afeb9260,
145 .codec_dev = &soc_codec_dev_tlv320aic23,
146};
147
148static struct platform_device *afeb9260_snd_device; 144static struct platform_device *afeb9260_snd_device;
149 145
150static int __init afeb9260_soc_init(void) 146static int __init afeb9260_soc_init(void)
151{ 147{
152 int err; 148 int err;
153 struct device *dev; 149 struct device *dev;
154 struct atmel_ssc_info *ssc_p = afeb9260_dai.cpu_dai->private_data;
155 struct ssc_device *ssc = NULL;
156 150
157 if (!(machine_is_afeb9260())) 151 if (!(machine_is_afeb9260()))
158 return -ENODEV; 152 return -ENODEV;
159 153
160 ssc = ssc_request(0);
161 if (IS_ERR(ssc)) {
162 printk(KERN_ERR "ASoC: Failed to request SSC 0\n");
163 err = PTR_ERR(ssc);
164 ssc = NULL;
165 goto err_ssc;
166 }
167 ssc_p->ssc = ssc;
168 154
169 afeb9260_snd_device = platform_device_alloc("soc-audio", -1); 155 afeb9260_snd_device = platform_device_alloc("soc-audio", -1);
170 if (!afeb9260_snd_device) { 156 if (!afeb9260_snd_device) {
@@ -172,8 +158,7 @@ static int __init afeb9260_soc_init(void)
172 return -ENOMEM; 158 return -ENOMEM;
173 } 159 }
174 160
175 platform_set_drvdata(afeb9260_snd_device, &afeb9260_snd_devdata); 161 platform_set_drvdata(afeb9260_snd_device, &snd_soc_machine_afeb9260);
176 afeb9260_snd_devdata.dev = &afeb9260_snd_device->dev;
177 err = platform_device_add(afeb9260_snd_device); 162 err = platform_device_add(afeb9260_snd_device);
178 if (err) 163 if (err)
179 goto err1; 164 goto err1;
@@ -184,9 +169,7 @@ static int __init afeb9260_soc_init(void)
184err1: 169err1:
185 platform_device_del(afeb9260_snd_device); 170 platform_device_del(afeb9260_snd_device);
186 platform_device_put(afeb9260_snd_device); 171 platform_device_put(afeb9260_snd_device);
187err_ssc:
188 return err; 172 return err;
189
190} 173}
191 174
192static void __exit afeb9260_soc_exit(void) 175static void __exit afeb9260_soc_exit(void)
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c
index cdf7be1b9b91..b62fcd33e586 100644
--- a/sound/soc/au1x/db1200.c
+++ b/sound/soc/au1x/db1200.c
@@ -19,7 +19,6 @@
19#include <asm/mach-au1x00/au1xxx_dbdma.h> 19#include <asm/mach-au1x00/au1xxx_dbdma.h>
20#include <asm/mach-db1x00/bcsr.h> 20#include <asm/mach-db1x00/bcsr.h>
21 21
22#include "../codecs/ac97.h"
23#include "../codecs/wm8731.h" 22#include "../codecs/wm8731.h"
24#include "psc.h" 23#include "psc.h"
25 24
@@ -28,20 +27,16 @@
28static struct snd_soc_dai_link db1200_ac97_dai = { 27static struct snd_soc_dai_link db1200_ac97_dai = {
29 .name = "AC97", 28 .name = "AC97",
30 .stream_name = "AC97 HiFi", 29 .stream_name = "AC97 HiFi",
31 .cpu_dai = &au1xpsc_ac97_dai, 30 .codec_dai_name = "ac97-hifi",
32 .codec_dai = &ac97_dai, 31 .cpu_dai_name = "au1xpsc_ac97.1",
32 .platform_name = "au1xpsc-pcm.1",
33 .codec_name = "ac97-codec.1",
33}; 34};
34 35
35static struct snd_soc_card db1200_ac97_machine = { 36static struct snd_soc_card db1200_ac97_machine = {
36 .name = "DB1200_AC97", 37 .name = "DB1200_AC97",
37 .dai_link = &db1200_ac97_dai, 38 .dai_link = &db1200_ac97_dai,
38 .num_links = 1, 39 .num_links = 1,
39 .platform = &au1xpsc_soc_platform,
40};
41
42static struct snd_soc_device db1200_ac97_devdata = {
43 .card = &db1200_ac97_machine,
44 .codec_dev = &soc_codec_dev_ac97,
45}; 40};
46 41
47/*------------------------- I2S PART ---------------------------*/ 42/*------------------------- I2S PART ---------------------------*/
@@ -49,12 +44,12 @@ static struct snd_soc_device db1200_ac97_devdata = {
49static int db1200_i2s_startup(struct snd_pcm_substream *substream) 44static int db1200_i2s_startup(struct snd_pcm_substream *substream)
50{ 45{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data; 46 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 47 struct snd_soc_dai *codec_dai = rtd->codec_dai;
53 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 48 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
54 int ret; 49 int ret;
55 50
56 /* WM8731 has its own 12MHz crystal */ 51 /* WM8731 has its own 12MHz crystal */
57 snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, 52 snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL,
58 12000000, SND_SOC_CLOCK_IN); 53 12000000, SND_SOC_CLOCK_IN);
59 54
60 /* codec is bitclock and lrclk master */ 55 /* codec is bitclock and lrclk master */
@@ -80,8 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = {
80static struct snd_soc_dai_link db1200_i2s_dai = { 75static struct snd_soc_dai_link db1200_i2s_dai = {
81 .name = "WM8731", 76 .name = "WM8731",
82 .stream_name = "WM8731 PCM", 77 .stream_name = "WM8731 PCM",
83 .cpu_dai = &au1xpsc_i2s_dai, 78 .codec_dai_name = "wm8731-hifi",
84 .codec_dai = &wm8731_dai, 79 .cpu_dai_name = "au1xpsc_i2s.1",
80 .platform_name = "au1xpsc-pcm.1",
81 .codec_name = "wm8731-codec.0-001b",
85 .ops = &db1200_i2s_wm8731_ops, 82 .ops = &db1200_i2s_wm8731_ops,
86}; 83};
87 84
@@ -89,12 +86,6 @@ static struct snd_soc_card db1200_i2s_machine = {
89 .name = "DB1200_I2S", 86 .name = "DB1200_I2S",
90 .dai_link = &db1200_i2s_dai, 87 .dai_link = &db1200_i2s_dai,
91 .num_links = 1, 88 .num_links = 1,
92 .platform = &au1xpsc_soc_platform,
93};
94
95static struct snd_soc_device db1200_i2s_devdata = {
96 .card = &db1200_i2s_machine,
97 .codec_dev = &soc_codec_dev_wm8731,
98}; 89};
99 90
100/*------------------------- COMMON PART ---------------------------*/ 91/*------------------------- COMMON PART ---------------------------*/
@@ -106,18 +97,16 @@ static int __init db1200_audio_load(void)
106 int ret; 97 int ret;
107 98
108 ret = -ENOMEM; 99 ret = -ENOMEM;
109 db1200_asoc_dev = platform_device_alloc("soc-audio", -1); 100 db1200_asoc_dev = platform_device_alloc("soc-audio", 1); /* PSC1 */
110 if (!db1200_asoc_dev) 101 if (!db1200_asoc_dev)
111 goto out; 102 goto out;
112 103
113 /* DB1200 board setup set PSC1MUX to preferred audio device */ 104 /* DB1200 board setup set PSC1MUX to preferred audio device */
114 if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX) 105 if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX)
115 platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_devdata); 106 platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine);
116 else 107 else
117 platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_devdata); 108 platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine);
118 109
119 db1200_ac97_devdata.dev = &db1200_asoc_dev->dev;
120 db1200_i2s_devdata.dev = &db1200_asoc_dev->dev;
121 ret = platform_device_add(db1200_asoc_dev); 110 ret = platform_device_add(db1200_asoc_dev);
122 111
123 if (ret) { 112 if (ret) {
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 6d9f4c624949..10fdd2854e58 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -10,9 +10,6 @@
10 * 10 *
11 * DMA glue for Au1x-PSC audio. 11 * DMA glue for Au1x-PSC audio.
12 * 12 *
13 * NOTE: all of these drivers can only work with a SINGLE instance
14 * of a PSC. Multiple independent audio devices are impossible
15 * with ASoC v1.
16 */ 13 */
17 14
18 15
@@ -61,9 +58,6 @@ struct au1xpsc_audio_dmadata {
61 int msbits; 58 int msbits;
62}; 59};
63 60
64/* instance data. There can be only one, MacLeod!!!! */
65static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2];
66
67/* 61/*
68 * These settings are somewhat okay, at least on my machine audio plays 62 * These settings are somewhat okay, at least on my machine audio plays
69 * almost skip-free. Especially the 64kB buffer seems to help a LOT. 63 * almost skip-free. Especially the 64kB buffer seems to help a LOT.
@@ -199,6 +193,14 @@ out:
199 return 0; 193 return 0;
200} 194}
201 195
196static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss)
197{
198 struct snd_soc_pcm_runtime *rtd = ss->private_data;
199 struct au1xpsc_audio_dmadata *pcd =
200 snd_soc_platform_get_drvdata(rtd->platform);
201 return &pcd[SUBSTREAM_TYPE(ss)];
202}
203
202static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, 204static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
203 struct snd_pcm_hw_params *params) 205 struct snd_pcm_hw_params *params)
204{ 206{
@@ -211,7 +213,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
211 goto out; 213 goto out;
212 214
213 stype = SUBSTREAM_TYPE(substream); 215 stype = SUBSTREAM_TYPE(substream);
214 pcd = au1xpsc_audio_pcmdma[stype]; 216 pcd = to_dmadata(substream);
215 217
216 DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " 218 DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
217 "runtime->min_align %d\n", 219 "runtime->min_align %d\n",
@@ -249,8 +251,7 @@ static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream)
249 251
250static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) 252static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
251{ 253{
252 struct au1xpsc_audio_dmadata *pcd = 254 struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream);
253 au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)];
254 255
255 au1xxx_dbdma_reset(pcd->ddma_chan); 256 au1xxx_dbdma_reset(pcd->ddma_chan);
256 257
@@ -267,7 +268,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
267 268
268static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 269static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
269{ 270{
270 u32 c = au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->ddma_chan; 271 u32 c = to_dmadata(substream)->ddma_chan;
271 272
272 switch (cmd) { 273 switch (cmd) {
273 case SNDRV_PCM_TRIGGER_START: 274 case SNDRV_PCM_TRIGGER_START:
@@ -287,8 +288,7 @@ static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
287static snd_pcm_uframes_t 288static snd_pcm_uframes_t
288au1xpsc_pcm_pointer(struct snd_pcm_substream *substream) 289au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
289{ 290{
290 return bytes_to_frames(substream->runtime, 291 return bytes_to_frames(substream->runtime, to_dmadata(substream)->pos);
291 au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->pos);
292} 292}
293 293
294static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) 294static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
@@ -299,7 +299,7 @@ static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
299 299
300static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) 300static int au1xpsc_pcm_close(struct snd_pcm_substream *substream)
301{ 301{
302 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]); 302 au1x_pcm_dbdma_free(to_dmadata(substream));
303 return 0; 303 return 0;
304} 304}
305 305
@@ -329,42 +329,21 @@ static int au1xpsc_pcm_new(struct snd_card *card,
329 return 0; 329 return 0;
330} 330}
331 331
332static int au1xpsc_pcm_probe(struct platform_device *pdev)
333{
334 if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
335 return -ENODEV;
336
337 return 0;
338}
339
340static int au1xpsc_pcm_remove(struct platform_device *pdev)
341{
342 return 0;
343}
344
345/* au1xpsc audio platform */ 332/* au1xpsc audio platform */
346struct snd_soc_platform au1xpsc_soc_platform = { 333struct snd_soc_platform_driver au1xpsc_soc_platform = {
347 .name = "au1xpsc-pcm-dbdma", 334 .ops = &au1xpsc_pcm_ops,
348 .probe = au1xpsc_pcm_probe,
349 .remove = au1xpsc_pcm_remove,
350 .pcm_ops = &au1xpsc_pcm_ops,
351 .pcm_new = au1xpsc_pcm_new, 335 .pcm_new = au1xpsc_pcm_new,
352 .pcm_free = au1xpsc_pcm_free_dma_buffers, 336 .pcm_free = au1xpsc_pcm_free_dma_buffers,
353}; 337};
354EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
355 338
356static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) 339static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
357{ 340{
341 struct au1xpsc_audio_dmadata *dmadata;
358 struct resource *r; 342 struct resource *r;
359 int ret; 343 int ret;
360 344
361 if (au1xpsc_audio_pcmdma[PCM_TX] || au1xpsc_audio_pcmdma[PCM_RX]) 345 dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
362 return -EBUSY; 346 if (!dmadata)
363
364 /* TX DMA */
365 au1xpsc_audio_pcmdma[PCM_TX]
366 = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
367 if (!au1xpsc_audio_pcmdma[PCM_TX])
368 return -ENOMEM; 347 return -ENOMEM;
369 348
370 r = platform_get_resource(pdev, IORESOURCE_DMA, 0); 349 r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -372,47 +351,33 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
372 ret = -ENODEV; 351 ret = -ENODEV;
373 goto out1; 352 goto out1;
374 } 353 }
375 (au1xpsc_audio_pcmdma[PCM_TX])->ddma_id = r->start; 354 dmadata[PCM_TX].ddma_id = r->start;
376 355
377 /* RX DMA */ 356 /* RX DMA */
378 au1xpsc_audio_pcmdma[PCM_RX]
379 = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
380 if (!au1xpsc_audio_pcmdma[PCM_RX])
381 return -ENOMEM;
382
383 r = platform_get_resource(pdev, IORESOURCE_DMA, 1); 357 r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
384 if (!r) { 358 if (!r) {
385 ret = -ENODEV; 359 ret = -ENODEV;
386 goto out2; 360 goto out1;
387 } 361 }
388 (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; 362 dmadata[PCM_RX].ddma_id = r->start;
363
364 platform_set_drvdata(pdev, dmadata);
389 365
390 ret = snd_soc_register_platform(&au1xpsc_soc_platform); 366 ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
391 if (!ret) 367 if (!ret)
392 return ret; 368 return ret;
393 369
394out2:
395 kfree(au1xpsc_audio_pcmdma[PCM_RX]);
396 au1xpsc_audio_pcmdma[PCM_RX] = NULL;
397out1: 370out1:
398 kfree(au1xpsc_audio_pcmdma[PCM_TX]); 371 kfree(dmadata);
399 au1xpsc_audio_pcmdma[PCM_TX] = NULL;
400 return ret; 372 return ret;
401} 373}
402 374
403static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) 375static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
404{ 376{
405 int i; 377 struct au1xpsc_audio_dmadata *dmadata = platform_get_drvdata(pdev);
406 378
407 snd_soc_unregister_platform(&au1xpsc_soc_platform); 379 snd_soc_unregister_platform(&pdev->dev);
408 380 kfree(dmadata);
409 for (i = 0; i < 2; i++) {
410 if (au1xpsc_audio_pcmdma[i]) {
411 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
412 kfree(au1xpsc_audio_pcmdma[i]);
413 au1xpsc_audio_pcmdma[i] = NULL;
414 }
415 }
416 381
417 return 0; 382 return 0;
418} 383}
@@ -428,8 +393,6 @@ static struct platform_driver au1xpsc_pcm_driver = {
428 393
429static int __init au1xpsc_audio_dbdma_load(void) 394static int __init au1xpsc_audio_dbdma_load(void)
430{ 395{
431 au1xpsc_audio_pcmdma[PCM_TX] = NULL;
432 au1xpsc_audio_pcmdma[PCM_RX] = NULL;
433 return platform_driver_register(&au1xpsc_pcm_driver); 396 return platform_driver_register(&au1xpsc_pcm_driver);
434} 397}
435 398
@@ -467,7 +430,7 @@ struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
467 res[1].start = res[1].end = id[1]; 430 res[1].start = res[1].end = id[1];
468 res[0].flags = res[1].flags = IORESOURCE_DMA; 431 res[0].flags = res[1].flags = IORESOURCE_DMA;
469 432
470 pd = platform_device_alloc("au1xpsc-pcm", -1); 433 pd = platform_device_alloc("au1xpsc-pcm", pdev->id);
471 if (!pd) 434 if (!pd)
472 goto out; 435 goto out;
473 436
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index d14a5a91a465..d0db66f24a00 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -10,9 +10,6 @@
10 * 10 *
11 * Au1xxx-PSC AC97 glue. 11 * Au1xxx-PSC AC97 glue.
12 * 12 *
13 * NOTE: all of these drivers can only work with a SINGLE instance
14 * of a PSC. Multiple independent audio devices are impossible
15 * with ASoC v1.
16 */ 13 */
17 14
18#include <linux/init.h> 15#include <linux/init.h>
@@ -56,12 +53,29 @@
56/* instance data. There can be only one, MacLeod!!!! */ 53/* instance data. There can be only one, MacLeod!!!! */
57static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; 54static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
58 55
56#if 0
57
58/* this could theoretically work, but ac97->bus->card->private_data can be NULL
59 * when snd_ac97_mixer() is called; I don't know if the rest further down the
60 * chain are always valid either.
61 */
62static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x)
63{
64 struct snd_soc_card *c = x->bus->card->private_data;
65 return snd_soc_dai_get_drvdata(c->rtd->cpu_dai);
66}
67
68#else
69
70#define ac97_to_pscdata(x) au1xpsc_ac97_workdata
71
72#endif
73
59/* AC97 controller reads codec register */ 74/* AC97 controller reads codec register */
60static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, 75static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
61 unsigned short reg) 76 unsigned short reg)
62{ 77{
63 /* FIXME */ 78 struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
64 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
65 unsigned short retry, tmo; 79 unsigned short retry, tmo;
66 unsigned long data; 80 unsigned long data;
67 81
@@ -102,8 +116,7 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
102static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, 116static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
103 unsigned short val) 117 unsigned short val)
104{ 118{
105 /* FIXME */ 119 struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
106 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
107 unsigned int tmo, retry; 120 unsigned int tmo, retry;
108 121
109 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 122 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
@@ -134,8 +147,7 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
134/* AC97 controller asserts a warm reset */ 147/* AC97 controller asserts a warm reset */
135static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) 148static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
136{ 149{
137 /* FIXME */ 150 struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
138 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
139 151
140 au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata)); 152 au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
141 au_sync(); 153 au_sync();
@@ -146,8 +158,7 @@ static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
146 158
147static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) 159static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
148{ 160{
149 /* FIXME */ 161 struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
150 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
151 int i; 162 int i;
152 163
153 /* disable PSC during cold reset */ 164 /* disable PSC during cold reset */
@@ -202,8 +213,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
202 struct snd_pcm_hw_params *params, 213 struct snd_pcm_hw_params *params,
203 struct snd_soc_dai *dai) 214 struct snd_soc_dai *dai)
204{ 215{
205 /* FIXME */ 216 struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
206 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
207 unsigned long r, ro, stat; 217 unsigned long r, ro, stat;
208 int chans, t, stype = SUBSTREAM_TYPE(substream); 218 int chans, t, stype = SUBSTREAM_TYPE(substream);
209 219
@@ -283,8 +293,7 @@ out:
283static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, 293static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
284 int cmd, struct snd_soc_dai *dai) 294 int cmd, struct snd_soc_dai *dai)
285{ 295{
286 /* FIXME */ 296 struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
287 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
288 int ret, stype = SUBSTREAM_TYPE(substream); 297 int ret, stype = SUBSTREAM_TYPE(substream);
289 298
290 ret = 0; 299 ret = 0;
@@ -315,27 +324,19 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
315 return ret; 324 return ret;
316} 325}
317 326
318static int au1xpsc_ac97_probe(struct platform_device *pdev, 327static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
319 struct snd_soc_dai *dai)
320{ 328{
321 return au1xpsc_ac97_workdata ? 0 : -ENODEV; 329 return au1xpsc_ac97_workdata ? 0 : -ENODEV;
322} 330}
323 331
324static void au1xpsc_ac97_remove(struct platform_device *pdev,
325 struct snd_soc_dai *dai)
326{
327}
328
329static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { 332static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
330 .trigger = au1xpsc_ac97_trigger, 333 .trigger = au1xpsc_ac97_trigger,
331 .hw_params = au1xpsc_ac97_hw_params, 334 .hw_params = au1xpsc_ac97_hw_params,
332}; 335};
333 336
334struct snd_soc_dai au1xpsc_ac97_dai = { 337static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
335 .name = "au1xpsc_ac97",
336 .ac97_control = 1, 338 .ac97_control = 1,
337 .probe = au1xpsc_ac97_probe, 339 .probe = au1xpsc_ac97_probe,
338 .remove = au1xpsc_ac97_remove,
339 .playback = { 340 .playback = {
340 .rates = AC97_RATES, 341 .rates = AC97_RATES,
341 .formats = AC97_FMTS, 342 .formats = AC97_FMTS,
@@ -350,7 +351,6 @@ struct snd_soc_dai au1xpsc_ac97_dai = {
350 }, 351 },
351 .ops = &au1xpsc_ac97_dai_ops, 352 .ops = &au1xpsc_ac97_dai_ops,
352}; 353};
353EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
354 354
355static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) 355static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
356{ 356{
@@ -359,9 +359,6 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
359 unsigned long sel; 359 unsigned long sel;
360 struct au1xpsc_audio_data *wd; 360 struct au1xpsc_audio_data *wd;
361 361
362 if (au1xpsc_ac97_workdata)
363 return -EBUSY;
364
365 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); 362 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
366 if (!wd) 363 if (!wd)
367 return -ENOMEM; 364 return -ENOMEM;
@@ -395,18 +392,24 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
395 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); 392 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
396 au_sync(); 393 au_sync();
397 394
398 ret = snd_soc_register_dai(&au1xpsc_ac97_dai); 395 /* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */
396 memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template,
397 sizeof(struct snd_soc_dai_driver));
398 wd->dai_drv.name = dev_name(&pdev->dev);
399
400 platform_set_drvdata(pdev, wd);
401
402 ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
399 if (ret) 403 if (ret)
400 goto out1; 404 goto out1;
401 405
402 wd->dmapd = au1xpsc_pcm_add(pdev); 406 wd->dmapd = au1xpsc_pcm_add(pdev);
403 if (wd->dmapd) { 407 if (wd->dmapd) {
404 platform_set_drvdata(pdev, wd); 408 au1xpsc_ac97_workdata = wd;
405 au1xpsc_ac97_workdata = wd; /* MDEV */
406 return 0; 409 return 0;
407 } 410 }
408 411
409 snd_soc_unregister_dai(&au1xpsc_ac97_dai); 412 snd_soc_unregister_dai(&pdev->dev);
410out1: 413out1:
411 release_mem_region(r->start, resource_size(r)); 414 release_mem_region(r->start, resource_size(r));
412out0: 415out0:
@@ -422,7 +425,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
422 if (wd->dmapd) 425 if (wd->dmapd)
423 au1xpsc_pcm_destroy(wd->dmapd); 426 au1xpsc_pcm_destroy(wd->dmapd);
424 427
425 snd_soc_unregister_dai(&au1xpsc_ac97_dai); 428 snd_soc_unregister_dai(&pdev->dev);
426 429
427 /* disable PSC completely */ 430 /* disable PSC completely */
428 au_writel(0, AC97_CFG(wd)); 431 au_writel(0, AC97_CFG(wd));
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index 6083fe7799fa..fca091276320 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -10,9 +10,6 @@
10 * 10 *
11 * Au1xxx-PSC I2S glue. 11 * Au1xxx-PSC I2S glue.
12 * 12 *
13 * NOTE: all of these drivers can only work with a SINGLE instance
14 * of a PSC. Multiple independent audio devices are impossible
15 * with ASoC v1.
16 * NOTE: so far only PSC slave mode (bit- and frameclock) is supported. 13 * NOTE: so far only PSC slave mode (bit- and frameclock) is supported.
17 */ 14 */
18 15
@@ -54,13 +51,10 @@
54 ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC) 51 ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
55 52
56 53
57/* instance data. There can be only one, MacLeod!!!! */
58static struct au1xpsc_audio_data *au1xpsc_i2s_workdata;
59
60static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, 54static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
61 unsigned int fmt) 55 unsigned int fmt)
62{ 56{
63 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; 57 struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(cpu_dai);
64 unsigned long ct; 58 unsigned long ct;
65 int ret; 59 int ret;
66 60
@@ -120,7 +114,7 @@ static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
120 struct snd_pcm_hw_params *params, 114 struct snd_pcm_hw_params *params,
121 struct snd_soc_dai *dai) 115 struct snd_soc_dai *dai)
122{ 116{
123 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; 117 struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
124 118
125 int cfgbits; 119 int cfgbits;
126 unsigned long stat; 120 unsigned long stat;
@@ -245,7 +239,7 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
245static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 239static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
246 struct snd_soc_dai *dai) 240 struct snd_soc_dai *dai)
247{ 241{
248 struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; 242 struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
249 int ret, stype = SUBSTREAM_TYPE(substream); 243 int ret, stype = SUBSTREAM_TYPE(substream);
250 244
251 switch (cmd) { 245 switch (cmd) {
@@ -263,27 +257,13 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
263 return ret; 257 return ret;
264} 258}
265 259
266static int au1xpsc_i2s_probe(struct platform_device *pdev,
267 struct snd_soc_dai *dai)
268{
269 return au1xpsc_i2s_workdata ? 0 : -ENODEV;
270}
271
272static void au1xpsc_i2s_remove(struct platform_device *pdev,
273 struct snd_soc_dai *dai)
274{
275}
276
277static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { 260static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
278 .trigger = au1xpsc_i2s_trigger, 261 .trigger = au1xpsc_i2s_trigger,
279 .hw_params = au1xpsc_i2s_hw_params, 262 .hw_params = au1xpsc_i2s_hw_params,
280 .set_fmt = au1xpsc_i2s_set_fmt, 263 .set_fmt = au1xpsc_i2s_set_fmt,
281}; 264};
282 265
283struct snd_soc_dai au1xpsc_i2s_dai = { 266static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
284 .name = "au1xpsc_i2s",
285 .probe = au1xpsc_i2s_probe,
286 .remove = au1xpsc_i2s_remove,
287 .playback = { 267 .playback = {
288 .rates = AU1XPSC_I2S_RATES, 268 .rates = AU1XPSC_I2S_RATES,
289 .formats = AU1XPSC_I2S_FMTS, 269 .formats = AU1XPSC_I2S_FMTS,
@@ -298,7 +278,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = {
298 }, 278 },
299 .ops = &au1xpsc_i2s_dai_ops, 279 .ops = &au1xpsc_i2s_dai_ops,
300}; 280};
301EXPORT_SYMBOL(au1xpsc_i2s_dai);
302 281
303static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) 282static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
304{ 283{
@@ -307,9 +286,6 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
307 int ret; 286 int ret;
308 struct au1xpsc_audio_data *wd; 287 struct au1xpsc_audio_data *wd;
309 288
310 if (au1xpsc_i2s_workdata)
311 return -EBUSY;
312
313 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); 289 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
314 if (!wd) 290 if (!wd)
315 return -ENOMEM; 291 return -ENOMEM;
@@ -346,19 +322,23 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
346 * time out. 322 * time out.
347 */ 323 */
348 324
349 ret = snd_soc_register_dai(&au1xpsc_i2s_dai); 325 /* name the DAI like this device instance ("au1xpsc-i2s.PSCINDEX") */
326 memcpy(&wd->dai_drv, &au1xpsc_i2s_dai_template,
327 sizeof(struct snd_soc_dai_driver));
328 wd->dai_drv.name = dev_name(&pdev->dev);
329
330 platform_set_drvdata(pdev, wd);
331
332 ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
350 if (ret) 333 if (ret)
351 goto out1; 334 goto out1;
352 335
353 /* finally add the DMA device for this PSC */ 336 /* finally add the DMA device for this PSC */
354 wd->dmapd = au1xpsc_pcm_add(pdev); 337 wd->dmapd = au1xpsc_pcm_add(pdev);
355 if (wd->dmapd) { 338 if (wd->dmapd)
356 platform_set_drvdata(pdev, wd);
357 au1xpsc_i2s_workdata = wd;
358 return 0; 339 return 0;
359 }
360 340
361 snd_soc_unregister_dai(&au1xpsc_i2s_dai); 341 snd_soc_unregister_dai(&pdev->dev);
362out1: 342out1:
363 release_mem_region(r->start, resource_size(r)); 343 release_mem_region(r->start, resource_size(r));
364out0: 344out0:
@@ -374,7 +354,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
374 if (wd->dmapd) 354 if (wd->dmapd)
375 au1xpsc_pcm_destroy(wd->dmapd); 355 au1xpsc_pcm_destroy(wd->dmapd);
376 356
377 snd_soc_unregister_dai(&au1xpsc_i2s_dai); 357 snd_soc_unregister_dai(&pdev->dev);
378 358
379 au_writel(0, I2S_CFG(wd)); 359 au_writel(0, I2S_CFG(wd));
380 au_sync(); 360 au_sync();
@@ -385,8 +365,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
385 release_mem_region(r->start, resource_size(r)); 365 release_mem_region(r->start, resource_size(r));
386 kfree(wd); 366 kfree(wd);
387 367
388 au1xpsc_i2s_workdata = NULL; /* MDEV */
389
390 return 0; 368 return 0;
391} 369}
392 370
@@ -446,7 +424,6 @@ static struct platform_driver au1xpsc_i2s_driver = {
446 424
447static int __init au1xpsc_i2s_load(void) 425static int __init au1xpsc_i2s_load(void)
448{ 426{
449 au1xpsc_i2s_workdata = NULL;
450 return platform_driver_register(&au1xpsc_i2s_driver); 427 return platform_driver_register(&au1xpsc_i2s_driver);
451} 428}
452 429
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
index 093775d4dc3e..b30eadd422a7 100644
--- a/sound/soc/au1x/psc.h
+++ b/sound/soc/au1x/psc.h
@@ -8,19 +8,11 @@
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 * 10 *
11 * NOTE: all of these drivers can only work with a SINGLE instance
12 * of a PSC. Multiple independent audio devices are impossible
13 * with ASoC v1.
14 */ 11 */
15 12
16#ifndef _AU1X_PCM_H 13#ifndef _AU1X_PCM_H
17#define _AU1X_PCM_H 14#define _AU1X_PCM_H
18 15
19extern struct snd_soc_dai au1xpsc_ac97_dai;
20extern struct snd_soc_dai au1xpsc_i2s_dai;
21extern struct snd_soc_platform au1xpsc_soc_platform;
22extern struct snd_ac97_bus_ops soc_ac97_ops;
23
24/* DBDMA helpers */ 16/* DBDMA helpers */
25extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev); 17extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev);
26extern void au1xpsc_pcm_destroy(struct platform_device *dmapd); 18extern void au1xpsc_pcm_destroy(struct platform_device *dmapd);
@@ -31,6 +23,8 @@ struct au1xpsc_audio_data {
31 unsigned long cfg; 23 unsigned long cfg;
32 unsigned long rate; 24 unsigned long rate;
33 25
26 struct snd_soc_dai_driver dai_drv;
27
34 unsigned long pm[2]; 28 unsigned long pm[2];
35 struct mutex lock; 29 struct mutex lock;
36 struct platform_device *dmapd; 30 struct platform_device *dmapd;
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 5e7aacf3bb5a..5a2fd8abaefa 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -422,14 +422,14 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
422 if (!card->dev->coherent_dma_mask) 422 if (!card->dev->coherent_dma_mask)
423 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 423 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
424 424
425 if (dai->playback.channels_min) { 425 if (dai->driver->playback.channels_min) {
426 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 426 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
427 SNDRV_PCM_STREAM_PLAYBACK); 427 SNDRV_PCM_STREAM_PLAYBACK);
428 if (ret) 428 if (ret)
429 goto out; 429 goto out;
430 } 430 }
431 431
432 if (dai->capture.channels_min) { 432 if (dai->driver->capture.channels_min) {
433 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 433 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
434 SNDRV_PCM_STREAM_CAPTURE); 434 SNDRV_PCM_STREAM_CAPTURE);
435 if (ret) 435 if (ret)
@@ -439,25 +439,44 @@ int bf5xx_pcm_ac97_new(struct snd_card *card, struct snd_soc_dai *dai,
439 return ret; 439 return ret;
440} 440}
441 441
442struct snd_soc_platform bf5xx_ac97_soc_platform = { 442static struct snd_soc_platform_driver bf5xx_ac97_soc_platform = {
443 .name = "bf5xx-audio", 443 .ops = &bf5xx_pcm_ac97_ops,
444 .pcm_ops = &bf5xx_pcm_ac97_ops,
445 .pcm_new = bf5xx_pcm_ac97_new, 444 .pcm_new = bf5xx_pcm_ac97_new,
446 .pcm_free = bf5xx_pcm_free_dma_buffers, 445 .pcm_free = bf5xx_pcm_free_dma_buffers,
447}; 446};
448EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform);
449 447
450static int __init bfin_ac97_init(void) 448static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
451{ 449{
452 return snd_soc_register_platform(&bf5xx_ac97_soc_platform); 450 return snd_soc_register_platform(&pdev->dev, &bf5xx_ac97_soc_platform);
453} 451}
454module_init(bfin_ac97_init);
455 452
456static void __exit bfin_ac97_exit(void) 453static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
457{ 454{
458 snd_soc_unregister_platform(&bf5xx_ac97_soc_platform); 455 snd_soc_unregister_platform(&pdev->dev);
456 return 0;
457}
458
459static struct platform_driver bf5xx_pcm_driver = {
460 .driver = {
461 .name = "bf5xx-pcm-audio",
462 .owner = THIS_MODULE,
463 },
464
465 .probe = bf5xx_soc_platform_probe,
466 .remove = __devexit_p(bf5xx_soc_platform_remove),
467};
468
469static int __init snd_bf5xx_pcm_init(void)
470{
471 return platform_driver_register(&bf5xx_pcm_driver);
472}
473module_init(snd_bf5xx_pcm_init);
474
475static void __exit snd_bf5xx_pcm_exit(void)
476{
477 platform_driver_unregister(&bf5xx_pcm_driver);
459} 478}
460module_exit(bfin_ac97_exit); 479module_exit(snd_bf5xx_pcm_exit);
461 480
462MODULE_AUTHOR("Cliff Cai"); 481MODULE_AUTHOR("Cliff Cai");
463MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); 482MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.h b/sound/soc/blackfin/bf5xx-ac97-pcm.h
index 350125a0ae21..d324d5826a9b 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.h
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.h
@@ -23,7 +23,4 @@ struct bf5xx_gpio {
23 u32 frm; 23 u32 frm;
24}; 24};
25 25
26/* platform data */
27extern struct snd_soc_platform bf5xx_ac97_soc_platform;
28
29#endif 26#endif
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index c0eba5109980..c5f856ec27ca 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops);
255#ifdef CONFIG_PM 255#ifdef CONFIG_PM
256static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) 256static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
257{ 257{
258 struct sport_device *sport = dai->private_data; 258 struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
259 259
260 pr_debug("%s : sport %d\n", __func__, dai->id); 260 pr_debug("%s : sport %d\n", __func__, dai->id);
261 if (!dai->active) 261 if (!dai->active)
@@ -270,7 +270,7 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
270static int bf5xx_ac97_resume(struct snd_soc_dai *dai) 270static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
271{ 271{
272 int ret; 272 int ret;
273 struct sport_device *sport = dai->private_data; 273 struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
274 274
275 pr_debug("%s : sport %d\n", __func__, dai->id); 275 pr_debug("%s : sport %d\n", __func__, dai->id);
276 if (!dai->active) 276 if (!dai->active)
@@ -306,8 +306,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
306#define bf5xx_ac97_resume NULL 306#define bf5xx_ac97_resume NULL
307#endif 307#endif
308 308
309static int bf5xx_ac97_probe(struct platform_device *pdev, 309static int bf5xx_ac97_probe(struct snd_soc_dai *dai)
310 struct snd_soc_dai *dai)
311{ 310{
312 int ret = 0; 311 int ret = 0;
313 cmd_count = (int *)get_zeroed_page(GFP_KERNEL); 312 cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
@@ -379,8 +378,7 @@ peripheral_err:
379 return ret; 378 return ret;
380} 379}
381 380
382static void bf5xx_ac97_remove(struct platform_device *pdev, 381static int bf5xx_ac97_remove(struct snd_soc_dai *dai)
383 struct snd_soc_dai *dai)
384{ 382{
385 free_page((unsigned long)cmd_count); 383 free_page((unsigned long)cmd_count);
386 cmd_count = NULL; 384 cmd_count = NULL;
@@ -388,11 +386,10 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
388#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET 386#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
389 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); 387 gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
390#endif 388#endif
389 return 0;
391} 390}
392 391
393struct snd_soc_dai bfin_ac97_dai = { 392struct snd_soc_dai_driver bfin_ac97_dai = {
394 .name = "bf5xx-ac97",
395 .id = 0,
396 .ac97_control = 1, 393 .ac97_control = 1,
397 .probe = bf5xx_ac97_probe, 394 .probe = bf5xx_ac97_probe,
398 .remove = bf5xx_ac97_remove, 395 .remove = bf5xx_ac97_remove,
@@ -417,18 +414,40 @@ struct snd_soc_dai bfin_ac97_dai = {
417}; 414};
418EXPORT_SYMBOL_GPL(bfin_ac97_dai); 415EXPORT_SYMBOL_GPL(bfin_ac97_dai);
419 416
417static __devinit int asoc_bfin_ac97_probe(struct platform_device *pdev)
418{
419 return snd_soc_register_dai(&pdev->dev, &bfin_ac97_dai);
420}
421
422static int __devexit asoc_bfin_ac97_remove(struct platform_device *pdev)
423{
424 snd_soc_unregister_dai(&pdev->dev);
425 return 0;
426}
427
428static struct platform_driver asoc_bfin_ac97_driver = {
429 .driver = {
430 .name = "bfin-ac97",
431 .owner = THIS_MODULE,
432 },
433
434 .probe = asoc_bfin_ac97_probe,
435 .remove = __devexit_p(asoc_bfin_ac97_remove),
436};
437
420static int __init bfin_ac97_init(void) 438static int __init bfin_ac97_init(void)
421{ 439{
422 return snd_soc_register_dai(&bfin_ac97_dai); 440 return platform_driver_register(&asoc_bfin_ac97_driver);
423} 441}
424module_init(bfin_ac97_init); 442module_init(bfin_ac97_init);
425 443
426static void __exit bfin_ac97_exit(void) 444static void __exit bfin_ac97_exit(void)
427{ 445{
428 snd_soc_unregister_dai(&bfin_ac97_dai); 446 platform_driver_unregister(&asoc_bfin_ac97_driver);
429} 447}
430module_exit(bfin_ac97_exit); 448module_exit(bfin_ac97_exit);
431 449
450
432MODULE_AUTHOR("Roy Huang"); 451MODULE_AUTHOR("Roy Huang");
433MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); 452MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
434MODULE_LICENSE("GPL"); 453MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h
index a1f97dd809d6..15c635e33f4d 100644
--- a/sound/soc/blackfin/bf5xx-ac97.h
+++ b/sound/soc/blackfin/bf5xx-ac97.h
@@ -50,8 +50,6 @@ struct ac97_frame {
50#define TAG_PCM_SR 0x0080 50#define TAG_PCM_SR 0x0080
51#define TAG_PCM_LFE 0x0040 51#define TAG_PCM_LFE 0x0040
52 52
53extern struct snd_soc_dai bfin_ac97_dai;
54
55void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \ 53void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \
56 size_t count, unsigned int chan_mask); 54 size_t count, unsigned int chan_mask);
57 55
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index 0f45a3f56be8..2394bff2b655 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -40,9 +40,9 @@ static struct snd_soc_card bf5xx_ad1836;
40static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream) 40static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream)
41{ 41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data; 42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 43 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
44 44
45 cpu_dai->private_data = sport_handle; 45 snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
46 return 0; 46 return 0;
47} 47}
48 48
@@ -50,8 +50,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
50 struct snd_pcm_hw_params *params) 50 struct snd_pcm_hw_params *params)
51{ 51{
52 struct snd_soc_pcm_runtime *rtd = substream->private_data; 52 struct snd_soc_pcm_runtime *rtd = substream->private_data;
53 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 53 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
54 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 54 struct snd_soc_dai *codec_dai = rtd->codec_dai;
55 unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7}; 55 unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
56 int ret = 0; 56 int ret = 0;
57 /* set cpu DAI configuration */ 57 /* set cpu DAI configuration */
@@ -83,23 +83,19 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {
83static struct snd_soc_dai_link bf5xx_ad1836_dai = { 83static struct snd_soc_dai_link bf5xx_ad1836_dai = {
84 .name = "ad1836", 84 .name = "ad1836",
85 .stream_name = "AD1836", 85 .stream_name = "AD1836",
86 .cpu_dai = &bf5xx_tdm_dai, 86 .cpu_dai_name = "bf5xx-tdm",
87 .codec_dai = &ad1836_dai, 87 .codec_dai_name = "ad1836-hifi",
88 .platform_name = "bf5xx-tdm-pcm-audio",
89 .codec_name = "ad1836-codec.0",
88 .ops = &bf5xx_ad1836_ops, 90 .ops = &bf5xx_ad1836_ops,
89}; 91};
90 92
91static struct snd_soc_card bf5xx_ad1836 = { 93static struct snd_soc_card bf5xx_ad1836 = {
92 .name = "bf5xx_ad1836", 94 .name = "bf5xx_ad1836",
93 .platform = &bf5xx_tdm_soc_platform,
94 .dai_link = &bf5xx_ad1836_dai, 95 .dai_link = &bf5xx_ad1836_dai,
95 .num_links = 1, 96 .num_links = 1,
96}; 97};
97 98
98static struct snd_soc_device bf5xx_ad1836_snd_devdata = {
99 .card = &bf5xx_ad1836,
100 .codec_dev = &soc_codec_dev_ad1836,
101};
102
103static struct platform_device *bfxx_ad1836_snd_device; 99static struct platform_device *bfxx_ad1836_snd_device;
104 100
105static int __init bf5xx_ad1836_init(void) 101static int __init bf5xx_ad1836_init(void)
@@ -110,8 +106,7 @@ static int __init bf5xx_ad1836_init(void)
110 if (!bfxx_ad1836_snd_device) 106 if (!bfxx_ad1836_snd_device)
111 return -ENOMEM; 107 return -ENOMEM;
112 108
113 platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata); 109 platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836);
114 bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev;
115 ret = platform_device_add(bfxx_ad1836_snd_device); 110 ret = platform_device_add(bfxx_ad1836_snd_device);
116 111
117 if (ret) 112 if (ret)
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c
index b8c9060cfd8e..e4a625317a1a 100644
--- a/sound/soc/blackfin/bf5xx-ad193x.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -49,9 +49,9 @@ static struct snd_soc_card bf5xx_ad193x;
49static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream) 49static int bf5xx_ad193x_startup(struct snd_pcm_substream *substream)
50{ 50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data; 51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 52 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
53 53
54 cpu_dai->private_data = sport_handle; 54 snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
55 return 0; 55 return 0;
56} 56}
57 57
@@ -59,8 +59,8 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
59 struct snd_pcm_hw_params *params) 59 struct snd_pcm_hw_params *params)
60{ 60{
61 struct snd_soc_pcm_runtime *rtd = substream->private_data; 61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 62 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 63 struct snd_soc_dai *codec_dai = rtd->codec_dai;
64 unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7}; 64 unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
65 int ret = 0; 65 int ret = 0;
66 /* set cpu DAI configuration */ 66 /* set cpu DAI configuration */
@@ -97,23 +97,19 @@ static struct snd_soc_ops bf5xx_ad193x_ops = {
97static struct snd_soc_dai_link bf5xx_ad193x_dai = { 97static struct snd_soc_dai_link bf5xx_ad193x_dai = {
98 .name = "ad193x", 98 .name = "ad193x",
99 .stream_name = "AD193X", 99 .stream_name = "AD193X",
100 .cpu_dai = &bf5xx_tdm_dai, 100 .cpu_dai_name = "bf5xx-tdm",
101 .codec_dai = &ad193x_dai, 101 .codec_dai_name ="ad193x-hifi",
102 .platform_name = "bf5xx-tdm-pcm-audio",
103 .codec_name = "ad193x-codec.5",
102 .ops = &bf5xx_ad193x_ops, 104 .ops = &bf5xx_ad193x_ops,
103}; 105};
104 106
105static struct snd_soc_card bf5xx_ad193x = { 107static struct snd_soc_card bf5xx_ad193x = {
106 .name = "bf5xx_ad193x", 108 .name = "bf5xx_ad193x",
107 .platform = &bf5xx_tdm_soc_platform,
108 .dai_link = &bf5xx_ad193x_dai, 109 .dai_link = &bf5xx_ad193x_dai,
109 .num_links = 1, 110 .num_links = 1,
110}; 111};
111 112
112static struct snd_soc_device bf5xx_ad193x_snd_devdata = {
113 .card = &bf5xx_ad193x,
114 .codec_dev = &soc_codec_dev_ad193x,
115};
116
117static struct platform_device *bfxx_ad193x_snd_device; 113static struct platform_device *bfxx_ad193x_snd_device;
118 114
119static int __init bf5xx_ad193x_init(void) 115static int __init bf5xx_ad193x_init(void)
@@ -124,8 +120,7 @@ static int __init bf5xx_ad193x_init(void)
124 if (!bfxx_ad193x_snd_device) 120 if (!bfxx_ad193x_snd_device)
125 return -ENOMEM; 121 return -ENOMEM;
126 122
127 platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x_snd_devdata); 123 platform_set_drvdata(bfxx_ad193x_snd_device, &bf5xx_ad193x);
128 bf5xx_ad193x_snd_devdata.dev = &bfxx_ad193x_snd_device->dev;
129 ret = platform_device_add(bfxx_ad193x_snd_device); 124 ret = platform_device_add(bfxx_ad193x_snd_device);
130 125
131 if (ret) 126 if (ret)
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c
index 92f7c327bb7a..d57c9c9c9883 100644
--- a/sound/soc/blackfin/bf5xx-ad1980.c
+++ b/sound/soc/blackfin/bf5xx-ad1980.c
@@ -56,10 +56,10 @@ static struct snd_soc_card bf5xx_board;
56static int bf5xx_board_startup(struct snd_pcm_substream *substream) 56static int bf5xx_board_startup(struct snd_pcm_substream *substream)
57{ 57{
58 struct snd_soc_pcm_runtime *rtd = substream->private_data; 58 struct snd_soc_pcm_runtime *rtd = substream->private_data;
59 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 59 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
60 60
61 pr_debug("%s enter\n", __func__); 61 pr_debug("%s enter\n", __func__);
62 cpu_dai->private_data = sport_handle; 62 snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
63 return 0; 63 return 0;
64} 64}
65 65
@@ -70,23 +70,19 @@ static struct snd_soc_ops bf5xx_board_ops = {
70static struct snd_soc_dai_link bf5xx_board_dai = { 70static struct snd_soc_dai_link bf5xx_board_dai = {
71 .name = "AC97", 71 .name = "AC97",
72 .stream_name = "AC97 HiFi", 72 .stream_name = "AC97 HiFi",
73 .cpu_dai = &bfin_ac97_dai, 73 .cpu_dai_name = "bfin-ac97",
74 .codec_dai = &ad1980_dai, 74 .codec_dai_name = "ad1980-hifi",
75 .platform_name = "bfin-pcm-audio",
76 .codec_name = "ad1980-codec",
75 .ops = &bf5xx_board_ops, 77 .ops = &bf5xx_board_ops,
76}; 78};
77 79
78static struct snd_soc_card bf5xx_board = { 80static struct snd_soc_card bf5xx_board = {
79 .name = "bf5xx-board", 81 .name = "bf5xx-board",
80 .platform = &bf5xx_ac97_soc_platform,
81 .dai_link = &bf5xx_board_dai, 82 .dai_link = &bf5xx_board_dai,
82 .num_links = 1, 83 .num_links = 1,
83}; 84};
84 85
85static struct snd_soc_device bf5xx_board_snd_devdata = {
86 .card = &bf5xx_board,
87 .codec_dev = &soc_codec_dev_ad1980,
88};
89
90static struct platform_device *bf5xx_board_snd_device; 86static struct platform_device *bf5xx_board_snd_device;
91 87
92static int __init bf5xx_board_init(void) 88static int __init bf5xx_board_init(void)
@@ -97,8 +93,7 @@ static int __init bf5xx_board_init(void)
97 if (!bf5xx_board_snd_device) 93 if (!bf5xx_board_snd_device)
98 return -ENOMEM; 94 return -ENOMEM;
99 95
100 platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board_snd_devdata); 96 platform_set_drvdata(bf5xx_board_snd_device, &bf5xx_board);
101 bf5xx_board_snd_devdata.dev = &bf5xx_board_snd_device->dev;
102 ret = platform_device_add(bf5xx_board_snd_device); 97 ret = platform_device_add(bf5xx_board_snd_device);
103 98
104 if (ret) 99 if (ret)
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 9825b71d0e28..900ced54ac79 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -47,7 +47,6 @@
47#include "../codecs/ad73311.h" 47#include "../codecs/ad73311.h"
48#include "bf5xx-sport.h" 48#include "bf5xx-sport.h"
49#include "bf5xx-i2s-pcm.h" 49#include "bf5xx-i2s-pcm.h"
50#include "bf5xx-i2s.h"
51 50
52#if CONFIG_SND_BF5XX_SPORT_NUM == 0 51#if CONFIG_SND_BF5XX_SPORT_NUM == 0
53#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1 52#define bfin_write_SPORT_TCR1 bfin_write_SPORT0_TCR1
@@ -150,10 +149,10 @@ static int bf5xx_probe(struct platform_device *pdev)
150static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream) 149static int bf5xx_ad73311_startup(struct snd_pcm_substream *substream)
151{ 150{
152 struct snd_soc_pcm_runtime *rtd = substream->private_data; 151 struct snd_soc_pcm_runtime *rtd = substream->private_data;
153 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 152 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
154 153
155 pr_debug("%s enter\n", __func__); 154 pr_debug("%s enter\n", __func__);
156 cpu_dai->private_data = sport_handle; 155 snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
157 return 0; 156 return 0;
158} 157}
159 158
@@ -161,7 +160,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params) 160 struct snd_pcm_hw_params *params)
162{ 161{
163 struct snd_soc_pcm_runtime *rtd = substream->private_data; 162 struct snd_soc_pcm_runtime *rtd = substream->private_data;
164 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 163 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
165 int ret = 0; 164 int ret = 0;
166 165
167 pr_debug("%s rate %d format %x\n", __func__, params_rate(params), 166 pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
@@ -185,24 +184,20 @@ static struct snd_soc_ops bf5xx_ad73311_ops = {
185static struct snd_soc_dai_link bf5xx_ad73311_dai = { 184static struct snd_soc_dai_link bf5xx_ad73311_dai = {
186 .name = "ad73311", 185 .name = "ad73311",
187 .stream_name = "AD73311", 186 .stream_name = "AD73311",
188 .cpu_dai = &bf5xx_i2s_dai, 187 .cpu_dai_name = "bf5xx-i2s",
189 .codec_dai = &ad73311_dai, 188 .codec_dai_name = "ad73311-hifi",
189 .platform_name = "bfin-pcm-audio",
190 .codec_name = "ad73311-codec",
190 .ops = &bf5xx_ad73311_ops, 191 .ops = &bf5xx_ad73311_ops,
191}; 192};
192 193
193static struct snd_soc_card bf5xx_ad73311 = { 194static struct snd_soc_card bf5xx_ad73311 = {
194 .name = "bf5xx_ad73311", 195 .name = "bf5xx_ad73311",
195 .platform = &bf5xx_i2s_soc_platform,
196 .probe = bf5xx_probe, 196 .probe = bf5xx_probe,
197 .dai_link = &bf5xx_ad73311_dai, 197 .dai_link = &bf5xx_ad73311_dai,
198 .num_links = 1, 198 .num_links = 1,
199}; 199};
200 200
201static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
202 .card = &bf5xx_ad73311,
203 .codec_dev = &soc_codec_dev_ad73311,
204};
205
206static struct platform_device *bf5xx_ad73311_snd_device; 201static struct platform_device *bf5xx_ad73311_snd_device;
207 202
208static int __init bf5xx_ad73311_init(void) 203static int __init bf5xx_ad73311_init(void)
@@ -214,8 +209,7 @@ static int __init bf5xx_ad73311_init(void)
214 if (!bf5xx_ad73311_snd_device) 209 if (!bf5xx_ad73311_snd_device)
215 return -ENOMEM; 210 return -ENOMEM;
216 211
217 platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); 212 platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311);
218 bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev;
219 ret = platform_device_add(bf5xx_ad73311_snd_device); 213 ret = platform_device_add(bf5xx_ad73311_snd_device);
220 214
221 if (ret) 215 if (ret)
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 1d2a1adf2575..890a0dccf902 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -40,7 +40,6 @@
40#include <asm/dma.h> 40#include <asm/dma.h>
41 41
42#include "bf5xx-i2s-pcm.h" 42#include "bf5xx-i2s-pcm.h"
43#include "bf5xx-i2s.h"
44#include "bf5xx-sport.h" 43#include "bf5xx-sport.h"
45 44
46static void bf5xx_dma_irq(void *data) 45static void bf5xx_dma_irq(void *data)
@@ -257,14 +256,14 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
257 if (!card->dev->coherent_dma_mask) 256 if (!card->dev->coherent_dma_mask)
258 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 257 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
259 258
260 if (dai->playback.channels_min) { 259 if (dai->driver->playback.channels_min) {
261 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 260 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
262 SNDRV_PCM_STREAM_PLAYBACK); 261 SNDRV_PCM_STREAM_PLAYBACK);
263 if (ret) 262 if (ret)
264 goto out; 263 goto out;
265 } 264 }
266 265
267 if (dai->capture.channels_min) { 266 if (dai->driver->capture.channels_min) {
268 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 267 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
269 SNDRV_PCM_STREAM_CAPTURE); 268 SNDRV_PCM_STREAM_CAPTURE);
270 if (ret) 269 if (ret)
@@ -274,25 +273,44 @@ int bf5xx_pcm_i2s_new(struct snd_card *card, struct snd_soc_dai *dai,
274 return ret; 273 return ret;
275} 274}
276 275
277struct snd_soc_platform bf5xx_i2s_soc_platform = { 276static struct snd_soc_platform_driver bf5xx_i2s_soc_platform = {
278 .name = "bf5xx-audio", 277 .ops = &bf5xx_pcm_i2s_ops,
279 .pcm_ops = &bf5xx_pcm_i2s_ops,
280 .pcm_new = bf5xx_pcm_i2s_new, 278 .pcm_new = bf5xx_pcm_i2s_new,
281 .pcm_free = bf5xx_pcm_free_dma_buffers, 279 .pcm_free = bf5xx_pcm_free_dma_buffers,
282}; 280};
283EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
284 281
285static int __init bfin_i2s_init(void) 282static int __devinit bfin_i2s_soc_platform_probe(struct platform_device *pdev)
286{ 283{
287 return snd_soc_register_platform(&bf5xx_i2s_soc_platform); 284 return snd_soc_register_platform(&pdev->dev, &bf5xx_i2s_soc_platform);
288} 285}
289module_init(bfin_i2s_init);
290 286
291static void __exit bfin_i2s_exit(void) 287static int __devexit bfin_i2s_soc_platform_remove(struct platform_device *pdev)
292{ 288{
293 snd_soc_unregister_platform(&bf5xx_i2s_soc_platform); 289 snd_soc_unregister_platform(&pdev->dev);
290 return 0;
291}
292
293static struct platform_driver bfin_i2s_pcm_driver = {
294 .driver = {
295 .name = "bfin-pcm-audio",
296 .owner = THIS_MODULE,
297 },
298
299 .probe = bfin_i2s_soc_platform_probe,
300 .remove = __devexit_p(bfin_i2s_soc_platform_remove),
301};
302
303static int __init snd_bfin_i2s_pcm_init(void)
304{
305 return platform_driver_register(&bfin_i2s_pcm_driver);
306}
307module_init(snd_bfin_i2s_pcm_init);
308
309static void __exit snd_bfin_i2s_pcm_exit(void)
310{
311 platform_driver_unregister(&bfin_i2s_pcm_driver);
294} 312}
295module_exit(bfin_i2s_exit); 313module_exit(snd_bfin_i2s_pcm_exit);
296 314
297MODULE_AUTHOR("Cliff Cai"); 315MODULE_AUTHOR("Cliff Cai");
298MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); 316MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.h b/sound/soc/blackfin/bf5xx-i2s-pcm.h
index 4d4609a97c59..0c2c5a68d4ff 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.h
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.h
@@ -23,7 +23,4 @@ struct bf5xx_gpio {
23 u32 frm; 23 u32 frm;
24}; 24};
25 25
26/* platform data */
27extern struct snd_soc_platform bf5xx_i2s_soc_platform;
28
29#endif 26#endif
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 3e6ada0dd1c4..d453b1e9d607 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -42,7 +42,6 @@
42#include <linux/gpio.h> 42#include <linux/gpio.h>
43 43
44#include "bf5xx-sport.h" 44#include "bf5xx-sport.h"
45#include "bf5xx-i2s.h"
46 45
47struct bf5xx_i2s_port { 46struct bf5xx_i2s_port {
48 u16 tcr1; 47 u16 tcr1;
@@ -195,8 +194,7 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
195 bf5xx_i2s.configured = 0; 194 bf5xx_i2s.configured = 0;
196} 195}
197 196
198static int bf5xx_i2s_probe(struct platform_device *pdev, 197static int bf5xx_i2s_probe(struct snd_soc_dai *dai)
199 struct snd_soc_dai *dai)
200{ 198{
201 pr_debug("%s enter\n", __func__); 199 pr_debug("%s enter\n", __func__);
202 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { 200 if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
@@ -215,11 +213,11 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
215 return 0; 213 return 0;
216} 214}
217 215
218static void bf5xx_i2s_remove(struct platform_device *pdev, 216static int bf5xx_i2s_remove(struct snd_soc_dai *dai)
219 struct snd_soc_dai *dai)
220{ 217{
221 pr_debug("%s enter\n", __func__); 218 pr_debug("%s enter\n", __func__);
222 peripheral_free_list(&sport_req[sport_num][0]); 219 peripheral_free_list(&sport_req[sport_num][0]);
220 return 0;
223} 221}
224 222
225#ifdef CONFIG_PM 223#ifdef CONFIG_PM
@@ -228,9 +226,9 @@ static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
228 226
229 pr_debug("%s : sport %d\n", __func__, dai->id); 227 pr_debug("%s : sport %d\n", __func__, dai->id);
230 228
231 if (dai->capture.active) 229 if (dai->capture_active)
232 sport_rx_stop(sport_handle); 230 sport_rx_stop(sport_handle);
233 if (dai->playback.active) 231 if (dai->playback_active)
234 sport_tx_stop(sport_handle); 232 sport_tx_stop(sport_handle);
235 return 0; 233 return 0;
236} 234}
@@ -277,9 +275,7 @@ static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
277 .set_fmt = bf5xx_i2s_set_dai_fmt, 275 .set_fmt = bf5xx_i2s_set_dai_fmt,
278}; 276};
279 277
280struct snd_soc_dai bf5xx_i2s_dai = { 278static struct snd_soc_dai_driver bf5xx_i2s_dai = {
281 .name = "bf5xx-i2s",
282 .id = 0,
283 .probe = bf5xx_i2s_probe, 279 .probe = bf5xx_i2s_probe,
284 .remove = bf5xx_i2s_remove, 280 .remove = bf5xx_i2s_remove,
285 .suspend = bf5xx_i2s_suspend, 281 .suspend = bf5xx_i2s_suspend,
@@ -296,18 +292,39 @@ struct snd_soc_dai bf5xx_i2s_dai = {
296 .formats = BF5XX_I2S_FORMATS,}, 292 .formats = BF5XX_I2S_FORMATS,},
297 .ops = &bf5xx_i2s_dai_ops, 293 .ops = &bf5xx_i2s_dai_ops,
298}; 294};
299EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); 295
296static int bfin_i2s_drv_probe(struct platform_device *pdev)
297{
298 return snd_soc_register_dai(&pdev->dev, &bf5xx_i2s_dai);
299}
300
301static int __devexit bfin_i2s_drv_remove(struct platform_device *pdev)
302{
303 snd_soc_unregister_dai(&pdev->dev);
304 return 0;
305}
306
307static struct platform_driver bfin_i2s_driver = {
308 .probe = bfin_i2s_drv_probe,
309 .remove = __devexit_p(bfin_i2s_drv_remove),
310
311 .driver = {
312 .name = "bf5xx-i2s",
313 .owner = THIS_MODULE,
314 },
315};
300 316
301static int __init bfin_i2s_init(void) 317static int __init bfin_i2s_init(void)
302{ 318{
303 return snd_soc_register_dai(&bf5xx_i2s_dai); 319 return platform_driver_register(&bfin_i2s_driver);
304} 320}
305module_init(bfin_i2s_init);
306 321
307static void __exit bfin_i2s_exit(void) 322static void __exit bfin_i2s_exit(void)
308{ 323{
309 snd_soc_unregister_dai(&bf5xx_i2s_dai); 324 platform_driver_unregister(&bfin_i2s_driver);
310} 325}
326
327module_init(bfin_i2s_init);
311module_exit(bfin_i2s_exit); 328module_exit(bfin_i2s_exit);
312 329
313/* Module information */ 330/* Module information */
diff --git a/sound/soc/blackfin/bf5xx-i2s.h b/sound/soc/blackfin/bf5xx-i2s.h
deleted file mode 100644
index 264ecdcba35a..000000000000
--- a/sound/soc/blackfin/bf5xx-i2s.h
+++ /dev/null
@@ -1,14 +0,0 @@
1/*
2 * sound/soc/blackfin/bf5xx-i2s.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _BF5XX_I2S_H
10#define _BF5XX_I2S_H
11
12extern struct snd_soc_dai bf5xx_i2s_dai;
13
14#endif
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index 3a00fa4dbe6d..36f2769eb912 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -42,17 +42,16 @@
42#include "../codecs/ssm2602.h" 42#include "../codecs/ssm2602.h"
43#include "bf5xx-sport.h" 43#include "bf5xx-sport.h"
44#include "bf5xx-i2s-pcm.h" 44#include "bf5xx-i2s-pcm.h"
45#include "bf5xx-i2s.h"
46 45
47static struct snd_soc_card bf5xx_ssm2602; 46static struct snd_soc_card bf5xx_ssm2602;
48 47
49static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) 48static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)
50{ 49{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data; 50 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 51 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
53 52
54 pr_debug("%s enter\n", __func__); 53 pr_debug("%s enter\n", __func__);
55 cpu_dai->private_data = sport_handle; 54 snd_soc_dai_set_drvdata(cpu_dai, sport_handle);
56 return 0; 55 return 0;
57} 56}
58 57
@@ -60,8 +59,8 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
60 struct snd_pcm_hw_params *params) 59 struct snd_pcm_hw_params *params)
61{ 60{
62 struct snd_soc_pcm_runtime *rtd = substream->private_data; 61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 62 struct snd_soc_dai *codec_dai = rtd->codec_dai;
64 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 63 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
65 unsigned int clk = 0; 64 unsigned int clk = 0;
66 int ret = 0; 65 int ret = 0;
67 66
@@ -118,36 +117,19 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {
118static struct snd_soc_dai_link bf5xx_ssm2602_dai = { 117static struct snd_soc_dai_link bf5xx_ssm2602_dai = {
119 .name = "ssm2602", 118 .name = "ssm2602",
120 .stream_name = "SSM2602", 119 .stream_name = "SSM2602",
121 .cpu_dai = &bf5xx_i2s_dai, 120 .cpu_dai_name = "bf5xx-i2s",
122 .codec_dai = &ssm2602_dai, 121 .codec_dai_name = "ssm2602-hifi",
122 .platform_name = "bf5xx-pcm-audio",
123 .codec_name = "ssm2602-codec.0-0x1b",
123 .ops = &bf5xx_ssm2602_ops, 124 .ops = &bf5xx_ssm2602_ops,
124}; 125};
125 126
126/*
127 * SSM2602 2 wire address is determined by CSB
128 * state during powerup.
129 * low = 0x1a
130 * high = 0x1b
131 */
132
133static struct ssm2602_setup_data bf5xx_ssm2602_setup = {
134 .i2c_bus = 0,
135 .i2c_address = 0x1b,
136};
137
138static struct snd_soc_card bf5xx_ssm2602 = { 127static struct snd_soc_card bf5xx_ssm2602 = {
139 .name = "bf5xx_ssm2602", 128 .name = "bf5xx_ssm2602",
140 .platform = &bf5xx_i2s_soc_platform,
141 .dai_link = &bf5xx_ssm2602_dai, 129 .dai_link = &bf5xx_ssm2602_dai,
142 .num_links = 1, 130 .num_links = 1,
143}; 131};
144 132
145static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
146 .card = &bf5xx_ssm2602,
147 .codec_dev = &soc_codec_dev_ssm2602,
148 .codec_data = &bf5xx_ssm2602_setup,
149};
150
151static struct platform_device *bf5xx_ssm2602_snd_device; 133static struct platform_device *bf5xx_ssm2602_snd_device;
152 134
153static int __init bf5xx_ssm2602_init(void) 135static int __init bf5xx_ssm2602_init(void)
@@ -159,9 +141,7 @@ static int __init bf5xx_ssm2602_init(void)
159 if (!bf5xx_ssm2602_snd_device) 141 if (!bf5xx_ssm2602_snd_device)
160 return -ENOMEM; 142 return -ENOMEM;
161 143
162 platform_set_drvdata(bf5xx_ssm2602_snd_device, 144 platform_set_drvdata(bf5xx_ssm2602_snd_device, &bf5xx_ssm2602);
163 &bf5xx_ssm2602_snd_devdata);
164 bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev;
165 ret = platform_device_add(bf5xx_ssm2602_snd_device); 145 ret = platform_device_add(bf5xx_ssm2602_snd_device);
166 146
167 if (ret) 147 if (ret)
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index 6bac1ac1a315..74cf759b78a6 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -290,14 +290,14 @@ static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai,
290 if (!card->dev->coherent_dma_mask) 290 if (!card->dev->coherent_dma_mask)
291 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 291 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
292 292
293 if (dai->playback.channels_min) { 293 if (dai->driver->playback.channels_min) {
294 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 294 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
295 SNDRV_PCM_STREAM_PLAYBACK); 295 SNDRV_PCM_STREAM_PLAYBACK);
296 if (ret) 296 if (ret)
297 goto out; 297 goto out;
298 } 298 }
299 299
300 if (dai->capture.channels_min) { 300 if (dai->driver->capture.channels_min) {
301 ret = bf5xx_pcm_preallocate_dma_buffer(pcm, 301 ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
302 SNDRV_PCM_STREAM_CAPTURE); 302 SNDRV_PCM_STREAM_CAPTURE);
303 if (ret) 303 if (ret)
@@ -307,25 +307,44 @@ out:
307 return ret; 307 return ret;
308} 308}
309 309
310struct snd_soc_platform bf5xx_tdm_soc_platform = { 310static struct snd_soc_platform_driver bf5xx_tdm_soc_platform = {
311 .name = "bf5xx-audio", 311 .ops = &bf5xx_pcm_tdm_ops,
312 .pcm_ops = &bf5xx_pcm_tdm_ops,
313 .pcm_new = bf5xx_pcm_tdm_new, 312 .pcm_new = bf5xx_pcm_tdm_new,
314 .pcm_free = bf5xx_pcm_free_dma_buffers, 313 .pcm_free = bf5xx_pcm_free_dma_buffers,
315}; 314};
316EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform);
317 315
318static int __init bfin_pcm_tdm_init(void) 316static int __devinit bf5xx_soc_platform_probe(struct platform_device *pdev)
319{ 317{
320 return snd_soc_register_platform(&bf5xx_tdm_soc_platform); 318 return snd_soc_register_platform(&pdev->dev, &bf5xx_tdm_soc_platform);
321} 319}
322module_init(bfin_pcm_tdm_init);
323 320
324static void __exit bfin_pcm_tdm_exit(void) 321static int __devexit bf5xx_soc_platform_remove(struct platform_device *pdev)
325{ 322{
326 snd_soc_unregister_platform(&bf5xx_tdm_soc_platform); 323 snd_soc_unregister_platform(&pdev->dev);
324 return 0;
325}
326
327static struct platform_driver bfin_tdm_driver = {
328 .driver = {
329 .name = "bf5xx-tdm-pcm-audio",
330 .owner = THIS_MODULE,
331 },
332
333 .probe = bf5xx_soc_platform_probe,
334 .remove = __devexit_p(bf5xx_soc_platform_remove),
335};
336
337static int __init snd_bfin_tdm_init(void)
338{
339 return platform_driver_register(&bfin_tdm_driver);
340}
341module_init(snd_bfin_tdm_init);
342
343static void __exit snd_bfin_tdm_exit(void)
344{
345 platform_driver_unregister(&bfin_tdm_driver);
327} 346}
328module_exit(bfin_pcm_tdm_exit); 347module_exit(snd_bfin_tdm_exit);
329 348
330MODULE_AUTHOR("Barry Song"); 349MODULE_AUTHOR("Barry Song");
331MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); 350MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.h b/sound/soc/blackfin/bf5xx-tdm-pcm.h
index ddc5047df88c..7f8cc01c4477 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.h
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.h
@@ -15,7 +15,4 @@ struct bf5xx_pcm_dma_params {
15 char *name; /* stream identifier */ 15 char *name; /* stream identifier */
16}; 16};
17 17
18/* platform data */
19extern struct snd_soc_platform bf5xx_tdm_soc_platform;
20
21#endif 18#endif
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index 24c14269f4bc..125123929f16 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -214,9 +214,9 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
214 214
215 if (!dai->active) 215 if (!dai->active)
216 return 0; 216 return 0;
217 if (dai->capture.active) 217 if (dai->capture_active)
218 sport_rx_stop(sport); 218 sport_rx_stop(sport);
219 if (dai->playback.active) 219 if (dai->playback_active)
220 sport_tx_stop(sport); 220 sport_tx_stop(sport);
221 return 0; 221 return 0;
222} 222}
@@ -224,7 +224,7 @@ static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
224static int bf5xx_tdm_resume(struct snd_soc_dai *dai) 224static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
225{ 225{
226 int ret; 226 int ret;
227 struct sport_device *sport = dai->private_data; 227 struct sport_device *sport = snd_soc_dai_get_drvdata(dai);
228 228
229 if (!dai->active) 229 if (!dai->active)
230 return 0; 230 return 0;
@@ -262,9 +262,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
262 .set_channel_map = bf5xx_tdm_set_channel_map, 262 .set_channel_map = bf5xx_tdm_set_channel_map,
263}; 263};
264 264
265struct snd_soc_dai bf5xx_tdm_dai = { 265static struct snd_soc_dai_driver bf5xx_tdm_dai = {
266 .name = "bf5xx-tdm",
267 .id = 0,
268 .suspend = bf5xx_tdm_suspend, 266 .suspend = bf5xx_tdm_suspend,
269 .resume = bf5xx_tdm_resume, 267 .resume = bf5xx_tdm_resume,
270 .playback = { 268 .playback = {
@@ -279,7 +277,6 @@ struct snd_soc_dai bf5xx_tdm_dai = {
279 .formats = SNDRV_PCM_FMTBIT_S32_LE,}, 277 .formats = SNDRV_PCM_FMTBIT_S32_LE,},
280 .ops = &bf5xx_tdm_dai_ops, 278 .ops = &bf5xx_tdm_dai_ops,
281}; 279};
282EXPORT_SYMBOL_GPL(bf5xx_tdm_dai);
283 280
284static int __devinit bfin_tdm_probe(struct platform_device *pdev) 281static int __devinit bfin_tdm_probe(struct platform_device *pdev)
285{ 282{
@@ -320,7 +317,7 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev)
320 goto sport_config_err; 317 goto sport_config_err;
321 } 318 }
322 319
323 ret = snd_soc_register_dai(&bf5xx_tdm_dai); 320 ret = snd_soc_register_dai(&pdev->dev, &bf5xx_tdm_dai);
324 if (ret) { 321 if (ret) {
325 pr_err("Failed to register DAI: %d\n", ret); 322 pr_err("Failed to register DAI: %d\n", ret);
326 goto sport_config_err; 323 goto sport_config_err;
@@ -337,7 +334,7 @@ sport_config_err:
337static int __devexit bfin_tdm_remove(struct platform_device *pdev) 334static int __devexit bfin_tdm_remove(struct platform_device *pdev)
338{ 335{
339 peripheral_free_list(&sport_req[sport_num][0]); 336 peripheral_free_list(&sport_req[sport_num][0]);
340 snd_soc_unregister_dai(&bf5xx_tdm_dai); 337 snd_soc_unregister_dai(&pdev->dev);
341 338
342 return 0; 339 return 0;
343} 340}
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h
index 04189a18c1ba..e986a3ea3315 100644
--- a/sound/soc/blackfin/bf5xx-tdm.h
+++ b/sound/soc/blackfin/bf5xx-tdm.h
@@ -20,6 +20,4 @@ struct bf5xx_tdm_port {
20 int configured; 20 int configured;
21}; 21};
22 22
23extern struct snd_soc_dai bf5xx_tdm_dai;
24
25#endif 23#endif
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
new file mode 100644
index 000000000000..01d19e9f53f9
--- /dev/null
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -0,0 +1,1486 @@
1/*
2 * 88pm860x-codec.c -- 88PM860x ALSA SoC Audio Driver
3 *
4 * Copyright 2010 Marvell International Ltd.
5 * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/i2c.h>
15#include <linux/platform_device.h>
16#include <linux/mfd/88pm860x.h>
17#include <linux/slab.h>
18#include <sound/core.h>
19#include <sound/pcm.h>
20#include <sound/pcm_params.h>
21#include <sound/soc.h>
22#include <sound/soc-dapm.h>
23#include <sound/tlv.h>
24#include <sound/initval.h>
25#include <sound/jack.h>
26
27#include "88pm860x-codec.h"
28
29#define MAX_NAME_LEN 20
30#define REG_CACHE_SIZE 0x40
31#define REG_CACHE_BASE 0xb0
32
33/* Status Register 1 (0x01) */
34#define REG_STATUS_1 0x01
35#define MIC_STATUS (1 << 7)
36#define HOOK_STATUS (1 << 6)
37#define HEADSET_STATUS (1 << 5)
38
39/* Mic Detection Register (0x37) */
40#define REG_MIC_DET 0x37
41#define CONTINUOUS_POLLING (3 << 1)
42#define EN_MIC_DET (1 << 0)
43#define MICDET_MASK 0x07
44
45/* Headset Detection Register (0x38) */
46#define REG_HS_DET 0x38
47#define EN_HS_DET (1 << 0)
48
49/* Misc2 Register (0x42) */
50#define REG_MISC2 0x42
51#define AUDIO_PLL (1 << 5)
52#define AUDIO_SECTION_RESET (1 << 4)
53#define AUDIO_SECTION_ON (1 << 3)
54
55/* PCM Interface Register 2 (0xb1) */
56#define PCM_INF2_BCLK (1 << 6) /* Bit clock polarity */
57#define PCM_INF2_FS (1 << 5) /* Frame Sync polarity */
58#define PCM_INF2_MASTER (1 << 4) /* Master / Slave */
59#define PCM_INF2_18WL (1 << 3) /* 18 / 16 bits */
60#define PCM_GENERAL_I2S 0
61#define PCM_EXACT_I2S 1
62#define PCM_LEFT_I2S 2
63#define PCM_RIGHT_I2S 3
64#define PCM_SHORT_FS 4
65#define PCM_LONG_FS 5
66#define PCM_MODE_MASK 7
67
68/* I2S Interface Register 4 (0xbe) */
69#define I2S_EQU_BYP (1 << 6)
70
71/* DAC Offset Register (0xcb) */
72#define DAC_MUTE (1 << 7)
73#define MUTE_LEFT (1 << 6)
74#define MUTE_RIGHT (1 << 2)
75
76/* ADC Analog Register 1 (0xd0) */
77#define REG_ADC_ANA_1 0xd0
78#define MIC1BIAS_MASK 0x60
79
80/* Earpiece/Speaker Control Register 2 (0xda) */
81#define REG_EAR2 0xda
82#define RSYNC_CHANGE (1 << 2)
83
84/* Audio Supplies Register 2 (0xdc) */
85#define REG_SUPPLIES2 0xdc
86#define LDO15_READY (1 << 4)
87#define LDO15_EN (1 << 3)
88#define CPUMP_READY (1 << 2)
89#define CPUMP_EN (1 << 1)
90#define AUDIO_EN (1 << 0)
91#define SUPPLY_MASK (LDO15_EN | CPUMP_EN | AUDIO_EN)
92
93/* Audio Enable Register 1 (0xdd) */
94#define ADC_MOD_RIGHT (1 << 1)
95#define ADC_MOD_LEFT (1 << 0)
96
97/* Audio Enable Register 2 (0xde) */
98#define ADC_LEFT (1 << 5)
99#define ADC_RIGHT (1 << 4)
100
101/* DAC Enable Register 2 (0xe1) */
102#define DAC_LEFT (1 << 5)
103#define DAC_RIGHT (1 << 4)
104#define MODULATOR (1 << 3)
105
106/* Shorts Register (0xeb) */
107#define REG_SHORTS 0xeb
108#define CLR_SHORT_LO2 (1 << 7)
109#define SHORT_LO2 (1 << 6)
110#define CLR_SHORT_LO1 (1 << 5)
111#define SHORT_LO1 (1 << 4)
112#define CLR_SHORT_HS2 (1 << 3)
113#define SHORT_HS2 (1 << 2)
114#define CLR_SHORT_HS1 (1 << 1)
115#define SHORT_HS1 (1 << 0)
116
117/*
118 * This widget should be just after DAC & PGA in DAPM power-on sequence and
119 * before DAC & PGA in DAPM power-off sequence.
120 */
121#define PM860X_DAPM_OUTPUT(wname, wevent) \
122{ .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
123 .shift = 0, .invert = 0, .kcontrols = NULL, \
124 .num_kcontrols = 0, .event = wevent, \
125 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, }
126
127struct pm860x_det {
128 struct snd_soc_jack *hp_jack;
129 struct snd_soc_jack *mic_jack;
130 int hp_det;
131 int mic_det;
132 int hook_det;
133 int hs_shrt;
134 int lo_shrt;
135};
136
137struct pm860x_priv {
138 unsigned int sysclk;
139 unsigned int pcmclk;
140 unsigned int dir;
141 unsigned int filter;
142 struct snd_soc_codec *codec;
143 struct i2c_client *i2c;
144 struct pm860x_chip *chip;
145 struct pm860x_det det;
146
147 int irq[4];
148 unsigned char name[4][MAX_NAME_LEN];
149 unsigned char reg_cache[REG_CACHE_SIZE];
150};
151
152/* -9450dB to 0dB in 150dB steps ( mute instead of -9450dB) */
153static const DECLARE_TLV_DB_SCALE(dpga_tlv, -9450, 150, 1);
154
155/* -9dB to 0db in 3dB steps */
156static const DECLARE_TLV_DB_SCALE(adc_tlv, -900, 300, 0);
157
158/* {-23, -17, -13.5, -11, -9, -6, -3, 0}dB */
159static const unsigned int mic_tlv[] = {
160 TLV_DB_RANGE_HEAD(5),
161 0, 0, TLV_DB_SCALE_ITEM(-2300, 0, 0),
162 1, 1, TLV_DB_SCALE_ITEM(-1700, 0, 0),
163 2, 2, TLV_DB_SCALE_ITEM(-1350, 0, 0),
164 3, 3, TLV_DB_SCALE_ITEM(-1100, 0, 0),
165 4, 7, TLV_DB_SCALE_ITEM(-900, 300, 0),
166};
167
168/* {0, 0, 0, -6, 0, 6, 12, 18}dB */
169static const unsigned int aux_tlv[] = {
170 TLV_DB_RANGE_HEAD(2),
171 0, 2, TLV_DB_SCALE_ITEM(0, 0, 0),
172 3, 7, TLV_DB_SCALE_ITEM(-600, 600, 0),
173};
174
175/* {-16, -13, -10, -7, -5.2, -3,3, -2.2, 0}dB, mute instead of -16dB */
176static const unsigned int out_tlv[] = {
177 TLV_DB_RANGE_HEAD(4),
178 0, 3, TLV_DB_SCALE_ITEM(-1600, 300, 1),
179 4, 4, TLV_DB_SCALE_ITEM(-520, 0, 0),
180 5, 5, TLV_DB_SCALE_ITEM(-330, 0, 0),
181 6, 7, TLV_DB_SCALE_ITEM(-220, 220, 0),
182};
183
184static const unsigned int st_tlv[] = {
185 TLV_DB_RANGE_HEAD(8),
186 0, 1, TLV_DB_SCALE_ITEM(-12041, 602, 0),
187 2, 3, TLV_DB_SCALE_ITEM(-11087, 250, 0),
188 4, 5, TLV_DB_SCALE_ITEM(-10643, 158, 0),
189 6, 7, TLV_DB_SCALE_ITEM(-10351, 116, 0),
190 8, 9, TLV_DB_SCALE_ITEM(-10133, 92, 0),
191 10, 13, TLV_DB_SCALE_ITEM(-9958, 70, 0),
192 14, 17, TLV_DB_SCALE_ITEM(-9689, 53, 0),
193 18, 271, TLV_DB_SCALE_ITEM(-9484, 37, 0),
194};
195
196/* Sidetone Gain = M * 2^(-5-N) */
197struct st_gain {
198 unsigned int db;
199 unsigned int m;
200 unsigned int n;
201};
202
203static struct st_gain st_table[] = {
204 {-12041, 1, 15}, {-11439, 1, 14}, {-11087, 3, 15}, {-10837, 1, 13},
205 {-10643, 5, 15}, {-10485, 3, 14}, {-10351, 7, 15}, {-10235, 1, 12},
206 {-10133, 9, 15}, {-10041, 5, 14}, { -9958, 11, 15}, { -9883, 3, 13},
207 { -9813, 13, 15}, { -9749, 7, 14}, { -9689, 15, 15}, { -9633, 1, 11},
208 { -9580, 17, 15}, { -9531, 9, 14}, { -9484, 19, 15}, { -9439, 5, 13},
209 { -9397, 21, 15}, { -9356, 11, 14}, { -9318, 23, 15}, { -9281, 3, 12},
210 { -9245, 25, 15}, { -9211, 13, 14}, { -9178, 27, 15}, { -9147, 7, 13},
211 { -9116, 29, 15}, { -9087, 15, 14}, { -9058, 31, 15}, { -9031, 1, 10},
212 { -8978, 17, 14}, { -8929, 9, 13}, { -8882, 19, 14}, { -8837, 5, 12},
213 { -8795, 21, 14}, { -8754, 11, 13}, { -8716, 23, 14}, { -8679, 3, 11},
214 { -8643, 25, 14}, { -8609, 13, 13}, { -8576, 27, 14}, { -8545, 7, 12},
215 { -8514, 29, 14}, { -8485, 15, 13}, { -8456, 31, 14}, { -8429, 1, 9},
216 { -8376, 17, 13}, { -8327, 9, 12}, { -8280, 19, 13}, { -8235, 5, 11},
217 { -8193, 21, 13}, { -8152, 11, 12}, { -8114, 23, 13}, { -8077, 3, 10},
218 { -8041, 25, 13}, { -8007, 13, 12}, { -7974, 27, 13}, { -7943, 7, 11},
219 { -7912, 29, 13}, { -7883, 15, 12}, { -7854, 31, 13}, { -7827, 1, 8},
220 { -7774, 17, 12}, { -7724, 9, 11}, { -7678, 19, 12}, { -7633, 5, 10},
221 { -7591, 21, 12}, { -7550, 11, 11}, { -7512, 23, 12}, { -7475, 3, 9},
222 { -7439, 25, 12}, { -7405, 13, 11}, { -7372, 27, 12}, { -7341, 7, 10},
223 { -7310, 29, 12}, { -7281, 15, 11}, { -7252, 31, 12}, { -7225, 1, 7},
224 { -7172, 17, 11}, { -7122, 9, 10}, { -7075, 19, 11}, { -7031, 5, 9},
225 { -6989, 21, 11}, { -6948, 11, 10}, { -6910, 23, 11}, { -6873, 3, 8},
226 { -6837, 25, 11}, { -6803, 13, 10}, { -6770, 27, 11}, { -6739, 7, 9},
227 { -6708, 29, 11}, { -6679, 15, 10}, { -6650, 31, 11}, { -6623, 1, 6},
228 { -6570, 17, 10}, { -6520, 9, 9}, { -6473, 19, 10}, { -6429, 5, 8},
229 { -6386, 21, 10}, { -6346, 11, 9}, { -6307, 23, 10}, { -6270, 3, 7},
230 { -6235, 25, 10}, { -6201, 13, 9}, { -6168, 27, 10}, { -6137, 7, 8},
231 { -6106, 29, 10}, { -6077, 15, 9}, { -6048, 31, 10}, { -6021, 1, 5},
232 { -5968, 17, 9}, { -5918, 9, 8}, { -5871, 19, 9}, { -5827, 5, 7},
233 { -5784, 21, 9}, { -5744, 11, 8}, { -5705, 23, 9}, { -5668, 3, 6},
234 { -5633, 25, 9}, { -5599, 13, 8}, { -5566, 27, 9}, { -5535, 7, 7},
235 { -5504, 29, 9}, { -5475, 15, 8}, { -5446, 31, 9}, { -5419, 1, 4},
236 { -5366, 17, 8}, { -5316, 9, 7}, { -5269, 19, 8}, { -5225, 5, 6},
237 { -5182, 21, 8}, { -5142, 11, 7}, { -5103, 23, 8}, { -5066, 3, 5},
238 { -5031, 25, 8}, { -4997, 13, 7}, { -4964, 27, 8}, { -4932, 7, 6},
239 { -4902, 29, 8}, { -4873, 15, 7}, { -4844, 31, 8}, { -4816, 1, 3},
240 { -4764, 17, 7}, { -4714, 9, 6}, { -4667, 19, 7}, { -4623, 5, 5},
241 { -4580, 21, 7}, { -4540, 11, 6}, { -4501, 23, 7}, { -4464, 3, 4},
242 { -4429, 25, 7}, { -4395, 13, 6}, { -4362, 27, 7}, { -4330, 7, 5},
243 { -4300, 29, 7}, { -4270, 15, 6}, { -4242, 31, 7}, { -4214, 1, 2},
244 { -4162, 17, 6}, { -4112, 9, 5}, { -4065, 19, 6}, { -4021, 5, 4},
245 { -3978, 21, 6}, { -3938, 11, 5}, { -3899, 23, 6}, { -3862, 3, 3},
246 { -3827, 25, 6}, { -3793, 13, 5}, { -3760, 27, 6}, { -3728, 7, 4},
247 { -3698, 29, 6}, { -3668, 15, 5}, { -3640, 31, 6}, { -3612, 1, 1},
248 { -3560, 17, 5}, { -3510, 9, 4}, { -3463, 19, 5}, { -3419, 5, 3},
249 { -3376, 21, 5}, { -3336, 11, 4}, { -3297, 23, 5}, { -3260, 3, 2},
250 { -3225, 25, 5}, { -3191, 13, 4}, { -3158, 27, 5}, { -3126, 7, 3},
251 { -3096, 29, 5}, { -3066, 15, 4}, { -3038, 31, 5}, { -3010, 1, 0},
252 { -2958, 17, 4}, { -2908, 9, 3}, { -2861, 19, 4}, { -2816, 5, 2},
253 { -2774, 21, 4}, { -2734, 11, 3}, { -2695, 23, 4}, { -2658, 3, 1},
254 { -2623, 25, 4}, { -2589, 13, 3}, { -2556, 27, 4}, { -2524, 7, 2},
255 { -2494, 29, 4}, { -2464, 15, 3}, { -2436, 31, 4}, { -2408, 2, 0},
256 { -2356, 17, 3}, { -2306, 9, 2}, { -2259, 19, 3}, { -2214, 5, 1},
257 { -2172, 21, 3}, { -2132, 11, 2}, { -2093, 23, 3}, { -2056, 3, 0},
258 { -2021, 25, 3}, { -1987, 13, 2}, { -1954, 27, 3}, { -1922, 7, 1},
259 { -1892, 29, 3}, { -1862, 15, 2}, { -1834, 31, 3}, { -1806, 4, 0},
260 { -1754, 17, 2}, { -1704, 9, 1}, { -1657, 19, 2}, { -1612, 5, 0},
261 { -1570, 21, 2}, { -1530, 11, 1}, { -1491, 23, 2}, { -1454, 6, 0},
262 { -1419, 25, 2}, { -1384, 13, 1}, { -1352, 27, 2}, { -1320, 7, 0},
263 { -1290, 29, 2}, { -1260, 15, 1}, { -1232, 31, 2}, { -1204, 8, 0},
264 { -1151, 17, 1}, { -1102, 9, 0}, { -1055, 19, 1}, { -1010, 10, 0},
265 { -968, 21, 1}, { -928, 11, 0}, { -889, 23, 1}, { -852, 12, 0},
266 { -816, 25, 1}, { -782, 13, 0}, { -750, 27, 1}, { -718, 14, 0},
267 { -688, 29, 1}, { -658, 15, 0}, { -630, 31, 1}, { -602, 16, 0},
268 { -549, 17, 0}, { -500, 18, 0}, { -453, 19, 0}, { -408, 20, 0},
269 { -366, 21, 0}, { -325, 22, 0}, { -287, 23, 0}, { -250, 24, 0},
270 { -214, 25, 0}, { -180, 26, 0}, { -148, 27, 0}, { -116, 28, 0},
271 { -86, 29, 0}, { -56, 30, 0}, { -28, 31, 0}, { 0, 0, 0},
272};
273
274static int pm860x_volatile(unsigned int reg)
275{
276 BUG_ON(reg >= REG_CACHE_SIZE);
277
278 switch (reg) {
279 case PM860X_AUDIO_SUPPLIES_2:
280 return 1;
281 }
282
283 return 0;
284}
285
286static unsigned int pm860x_read_reg_cache(struct snd_soc_codec *codec,
287 unsigned int reg)
288{
289 unsigned char *cache = codec->reg_cache;
290
291 BUG_ON(reg >= REG_CACHE_SIZE);
292
293 if (pm860x_volatile(reg))
294 return cache[reg];
295
296 reg += REG_CACHE_BASE;
297
298 return pm860x_reg_read(codec->control_data, reg);
299}
300
301static int pm860x_write_reg_cache(struct snd_soc_codec *codec,
302 unsigned int reg, unsigned int value)
303{
304 unsigned char *cache = codec->reg_cache;
305
306 BUG_ON(reg >= REG_CACHE_SIZE);
307
308 if (!pm860x_volatile(reg))
309 cache[reg] = (unsigned char)value;
310
311 reg += REG_CACHE_BASE;
312
313 return pm860x_reg_write(codec->control_data, reg, value);
314}
315
316static int snd_soc_get_volsw_2r_st(struct snd_kcontrol *kcontrol,
317 struct snd_ctl_elem_value *ucontrol)
318{
319 struct soc_mixer_control *mc =
320 (struct soc_mixer_control *)kcontrol->private_value;
321 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
322 unsigned int reg = mc->reg;
323 unsigned int reg2 = mc->rreg;
324 int val[2], val2[2], i;
325
326 val[0] = snd_soc_read(codec, reg) & 0x3f;
327 val[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT) >> 4) & 0xf;
328 val2[0] = snd_soc_read(codec, reg2) & 0x3f;
329 val2[1] = (snd_soc_read(codec, PM860X_SIDETONE_SHIFT)) & 0xf;
330
331 for (i = 0; i < ARRAY_SIZE(st_table); i++) {
332 if ((st_table[i].m == val[0]) && (st_table[i].n == val[1]))
333 ucontrol->value.integer.value[0] = i;
334 if ((st_table[i].m == val2[0]) && (st_table[i].n == val2[1]))
335 ucontrol->value.integer.value[1] = i;
336 }
337 return 0;
338}
339
340static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol,
341 struct snd_ctl_elem_value *ucontrol)
342{
343 struct soc_mixer_control *mc =
344 (struct soc_mixer_control *)kcontrol->private_value;
345 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
346 unsigned int reg = mc->reg;
347 unsigned int reg2 = mc->rreg;
348 int err;
349 unsigned int val, val2;
350
351 val = ucontrol->value.integer.value[0];
352 val2 = ucontrol->value.integer.value[1];
353
354 err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m);
355 if (err < 0)
356 return err;
357 err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0xf0,
358 st_table[val].n << 4);
359 if (err < 0)
360 return err;
361
362 err = snd_soc_update_bits(codec, reg2, 0x3f, st_table[val2].m);
363 if (err < 0)
364 return err;
365 err = snd_soc_update_bits(codec, PM860X_SIDETONE_SHIFT, 0x0f,
366 st_table[val2].n);
367 return err;
368}
369
370static int snd_soc_get_volsw_2r_out(struct snd_kcontrol *kcontrol,
371 struct snd_ctl_elem_value *ucontrol)
372{
373 struct soc_mixer_control *mc =
374 (struct soc_mixer_control *)kcontrol->private_value;
375 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
376 unsigned int reg = mc->reg;
377 unsigned int reg2 = mc->rreg;
378 unsigned int shift = mc->shift;
379 int max = mc->max, val, val2;
380 unsigned int mask = (1 << fls(max)) - 1;
381
382 val = snd_soc_read(codec, reg) >> shift;
383 val2 = snd_soc_read(codec, reg2) >> shift;
384 ucontrol->value.integer.value[0] = (max - val) & mask;
385 ucontrol->value.integer.value[1] = (max - val2) & mask;
386
387 return 0;
388}
389
390static int snd_soc_put_volsw_2r_out(struct snd_kcontrol *kcontrol,
391 struct snd_ctl_elem_value *ucontrol)
392{
393 struct soc_mixer_control *mc =
394 (struct soc_mixer_control *)kcontrol->private_value;
395 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
396 unsigned int reg = mc->reg;
397 unsigned int reg2 = mc->rreg;
398 unsigned int shift = mc->shift;
399 int max = mc->max;
400 unsigned int mask = (1 << fls(max)) - 1;
401 int err;
402 unsigned int val, val2, val_mask;
403
404 val_mask = mask << shift;
405 val = ((max - ucontrol->value.integer.value[0]) & mask);
406 val2 = ((max - ucontrol->value.integer.value[1]) & mask);
407
408 val = val << shift;
409 val2 = val2 << shift;
410
411 err = snd_soc_update_bits(codec, reg, val_mask, val);
412 if (err < 0)
413 return err;
414
415 err = snd_soc_update_bits(codec, reg2, val_mask, val2);
416 return err;
417}
418
419/* DAPM Widget Events */
420/*
421 * A lot registers are belong to RSYNC domain. It requires enabling RSYNC bit
422 * after updating these registers. Otherwise, these updated registers won't
423 * be effective.
424 */
425static int pm860x_rsync_event(struct snd_soc_dapm_widget *w,
426 struct snd_kcontrol *kcontrol, int event)
427{
428 struct snd_soc_codec *codec = w->codec;
429
430 /*
431 * In order to avoid current on the load, mute power-on and power-off
432 * should be transients.
433 * Unmute by DAC_MUTE. It should be unmuted when DAPM sequence is
434 * finished.
435 */
436 snd_soc_update_bits(codec, PM860X_DAC_OFFSET, DAC_MUTE, 0);
437 snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
438 RSYNC_CHANGE, RSYNC_CHANGE);
439 return 0;
440}
441
442static int pm860x_dac_event(struct snd_soc_dapm_widget *w,
443 struct snd_kcontrol *kcontrol, int event)
444{
445 struct snd_soc_codec *codec = w->codec;
446 unsigned int dac = 0;
447 int data;
448
449 if (!strcmp(w->name, "Left DAC"))
450 dac = DAC_LEFT;
451 if (!strcmp(w->name, "Right DAC"))
452 dac = DAC_RIGHT;
453 switch (event) {
454 case SND_SOC_DAPM_PRE_PMU:
455 if (dac) {
456 /* Auto mute in power-on sequence. */
457 dac |= MODULATOR;
458 snd_soc_update_bits(codec, PM860X_DAC_OFFSET,
459 DAC_MUTE, DAC_MUTE);
460 snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
461 RSYNC_CHANGE, RSYNC_CHANGE);
462 /* update dac */
463 snd_soc_update_bits(codec, PM860X_DAC_EN_2,
464 dac, dac);
465 }
466 break;
467 case SND_SOC_DAPM_PRE_PMD:
468 if (dac) {
469 /* Auto mute in power-off sequence. */
470 snd_soc_update_bits(codec, PM860X_DAC_OFFSET,
471 DAC_MUTE, DAC_MUTE);
472 snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
473 RSYNC_CHANGE, RSYNC_CHANGE);
474 /* update dac */
475 data = snd_soc_read(codec, PM860X_DAC_EN_2);
476 data &= ~dac;
477 if (!(data & (DAC_LEFT | DAC_RIGHT)))
478 data &= ~MODULATOR;
479 snd_soc_write(codec, PM860X_DAC_EN_2, data);
480 }
481 break;
482 }
483 return 0;
484}
485
486static const char *pm860x_opamp_texts[] = {"-50%", "-25%", "0%", "75%"};
487
488static const char *pm860x_pa_texts[] = {"-33%", "0%", "33%", "66%"};
489
490static const struct soc_enum pm860x_hs1_opamp_enum =
491 SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 5, 4, pm860x_opamp_texts);
492
493static const struct soc_enum pm860x_hs2_opamp_enum =
494 SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 5, 4, pm860x_opamp_texts);
495
496static const struct soc_enum pm860x_hs1_pa_enum =
497 SOC_ENUM_SINGLE(PM860X_HS1_CTRL, 3, 4, pm860x_pa_texts);
498
499static const struct soc_enum pm860x_hs2_pa_enum =
500 SOC_ENUM_SINGLE(PM860X_HS2_CTRL, 3, 4, pm860x_pa_texts);
501
502static const struct soc_enum pm860x_lo1_opamp_enum =
503 SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 5, 4, pm860x_opamp_texts);
504
505static const struct soc_enum pm860x_lo2_opamp_enum =
506 SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 5, 4, pm860x_opamp_texts);
507
508static const struct soc_enum pm860x_lo1_pa_enum =
509 SOC_ENUM_SINGLE(PM860X_LO1_CTRL, 3, 4, pm860x_pa_texts);
510
511static const struct soc_enum pm860x_lo2_pa_enum =
512 SOC_ENUM_SINGLE(PM860X_LO2_CTRL, 3, 4, pm860x_pa_texts);
513
514static const struct soc_enum pm860x_spk_pa_enum =
515 SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 5, 4, pm860x_pa_texts);
516
517static const struct soc_enum pm860x_ear_pa_enum =
518 SOC_ENUM_SINGLE(PM860X_EAR_CTRL_2, 0, 4, pm860x_pa_texts);
519
520static const struct soc_enum pm860x_spk_ear_opamp_enum =
521 SOC_ENUM_SINGLE(PM860X_EAR_CTRL_1, 3, 4, pm860x_opamp_texts);
522
523static const struct snd_kcontrol_new pm860x_snd_controls[] = {
524 SOC_DOUBLE_R_TLV("ADC Capture Volume", PM860X_ADC_ANA_2,
525 PM860X_ADC_ANA_3, 6, 3, 0, adc_tlv),
526 SOC_DOUBLE_TLV("AUX Capture Volume", PM860X_ADC_ANA_3, 0, 3, 7, 0,
527 aux_tlv),
528 SOC_SINGLE_TLV("MIC1 Capture Volume", PM860X_ADC_ANA_2, 0, 7, 0,
529 mic_tlv),
530 SOC_SINGLE_TLV("MIC3 Capture Volume", PM860X_ADC_ANA_2, 3, 7, 0,
531 mic_tlv),
532 SOC_DOUBLE_R_EXT_TLV("Sidetone Volume", PM860X_SIDETONE_L_GAIN,
533 PM860X_SIDETONE_R_GAIN, 0, ARRAY_SIZE(st_table)-1,
534 0, snd_soc_get_volsw_2r_st,
535 snd_soc_put_volsw_2r_st, st_tlv),
536 SOC_SINGLE_TLV("Speaker Playback Volume", PM860X_EAR_CTRL_1,
537 0, 7, 0, out_tlv),
538 SOC_DOUBLE_R_TLV("Line Playback Volume", PM860X_LO1_CTRL,
539 PM860X_LO2_CTRL, 0, 7, 0, out_tlv),
540 SOC_DOUBLE_R_TLV("Headset Playback Volume", PM860X_HS1_CTRL,
541 PM860X_HS2_CTRL, 0, 7, 0, out_tlv),
542 SOC_DOUBLE_R_EXT_TLV("Hifi Left Playback Volume",
543 PM860X_HIFIL_GAIN_LEFT,
544 PM860X_HIFIL_GAIN_RIGHT, 0, 63, 0,
545 snd_soc_get_volsw_2r_out,
546 snd_soc_put_volsw_2r_out, dpga_tlv),
547 SOC_DOUBLE_R_EXT_TLV("Hifi Right Playback Volume",
548 PM860X_HIFIR_GAIN_LEFT,
549 PM860X_HIFIR_GAIN_RIGHT, 0, 63, 0,
550 snd_soc_get_volsw_2r_out,
551 snd_soc_put_volsw_2r_out, dpga_tlv),
552 SOC_DOUBLE_R_EXT_TLV("Lofi Playback Volume", PM860X_LOFI_GAIN_LEFT,
553 PM860X_LOFI_GAIN_RIGHT, 0, 63, 0,
554 snd_soc_get_volsw_2r_out,
555 snd_soc_put_volsw_2r_out, dpga_tlv),
556 SOC_ENUM("Headset1 Operational Amplifier Current",
557 pm860x_hs1_opamp_enum),
558 SOC_ENUM("Headset2 Operational Amplifier Current",
559 pm860x_hs2_opamp_enum),
560 SOC_ENUM("Headset1 Amplifier Current", pm860x_hs1_pa_enum),
561 SOC_ENUM("Headset2 Amplifier Current", pm860x_hs2_pa_enum),
562 SOC_ENUM("Lineout1 Operational Amplifier Current",
563 pm860x_lo1_opamp_enum),
564 SOC_ENUM("Lineout2 Operational Amplifier Current",
565 pm860x_lo2_opamp_enum),
566 SOC_ENUM("Lineout1 Amplifier Current", pm860x_lo1_pa_enum),
567 SOC_ENUM("Lineout2 Amplifier Current", pm860x_lo2_pa_enum),
568 SOC_ENUM("Speaker Operational Amplifier Current",
569 pm860x_spk_ear_opamp_enum),
570 SOC_ENUM("Speaker Amplifier Current", pm860x_spk_pa_enum),
571 SOC_ENUM("Earpiece Amplifier Current", pm860x_ear_pa_enum),
572};
573
574/*
575 * DAPM Controls
576 */
577
578/* PCM Switch / PCM Interface */
579static const struct snd_kcontrol_new pcm_switch_controls =
580 SOC_DAPM_SINGLE("Switch", PM860X_ADC_EN_2, 0, 1, 0);
581
582/* AUX1 Switch */
583static const struct snd_kcontrol_new aux1_switch_controls =
584 SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 4, 1, 0);
585
586/* AUX2 Switch */
587static const struct snd_kcontrol_new aux2_switch_controls =
588 SOC_DAPM_SINGLE("Switch", PM860X_ANA_TO_ANA, 5, 1, 0);
589
590/* Left Ex. PA Switch */
591static const struct snd_kcontrol_new lepa_switch_controls =
592 SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 2, 1, 0);
593
594/* Right Ex. PA Switch */
595static const struct snd_kcontrol_new repa_switch_controls =
596 SOC_DAPM_SINGLE("Switch", PM860X_DAC_EN_2, 1, 1, 0);
597
598/* PCM Mux / Mux7 */
599static const char *aif1_text[] = {
600 "PCM L", "PCM R",
601};
602
603static const struct soc_enum aif1_enum =
604 SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 6, 2, aif1_text);
605
606static const struct snd_kcontrol_new aif1_mux =
607 SOC_DAPM_ENUM("PCM Mux", aif1_enum);
608
609/* I2S Mux / Mux9 */
610static const char *i2s_din_text[] = {
611 "DIN", "DIN1",
612};
613
614static const struct soc_enum i2s_din_enum =
615 SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 1, 2, i2s_din_text);
616
617static const struct snd_kcontrol_new i2s_din_mux =
618 SOC_DAPM_ENUM("I2S DIN Mux", i2s_din_enum);
619
620/* I2S Mic Mux / Mux8 */
621static const char *i2s_mic_text[] = {
622 "Ex PA", "ADC",
623};
624
625static const struct soc_enum i2s_mic_enum =
626 SOC_ENUM_SINGLE(PM860X_I2S_IFACE_3, 4, 2, i2s_mic_text);
627
628static const struct snd_kcontrol_new i2s_mic_mux =
629 SOC_DAPM_ENUM("I2S Mic Mux", i2s_mic_enum);
630
631/* ADCL Mux / Mux2 */
632static const char *adcl_text[] = {
633 "ADCR", "ADCL",
634};
635
636static const struct soc_enum adcl_enum =
637 SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 4, 2, adcl_text);
638
639static const struct snd_kcontrol_new adcl_mux =
640 SOC_DAPM_ENUM("ADC Left Mux", adcl_enum);
641
642/* ADCR Mux / Mux3 */
643static const char *adcr_text[] = {
644 "ADCL", "ADCR",
645};
646
647static const struct soc_enum adcr_enum =
648 SOC_ENUM_SINGLE(PM860X_PCM_IFACE_3, 2, 2, adcr_text);
649
650static const struct snd_kcontrol_new adcr_mux =
651 SOC_DAPM_ENUM("ADC Right Mux", adcr_enum);
652
653/* ADCR EC Mux / Mux6 */
654static const char *adcr_ec_text[] = {
655 "ADCR", "EC",
656};
657
658static const struct soc_enum adcr_ec_enum =
659 SOC_ENUM_SINGLE(PM860X_ADC_EN_2, 3, 2, adcr_ec_text);
660
661static const struct snd_kcontrol_new adcr_ec_mux =
662 SOC_DAPM_ENUM("ADCR EC Mux", adcr_ec_enum);
663
664/* EC Mux / Mux4 */
665static const char *ec_text[] = {
666 "Left", "Right", "Left + Right",
667};
668
669static const struct soc_enum ec_enum =
670 SOC_ENUM_SINGLE(PM860X_EC_PATH, 1, 3, ec_text);
671
672static const struct snd_kcontrol_new ec_mux =
673 SOC_DAPM_ENUM("EC Mux", ec_enum);
674
675static const char *dac_text[] = {
676 "No input", "Right", "Left", "No input",
677};
678
679/* DAC Headset 1 Mux / Mux10 */
680static const struct soc_enum dac_hs1_enum =
681 SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 0, 4, dac_text);
682
683static const struct snd_kcontrol_new dac_hs1_mux =
684 SOC_DAPM_ENUM("DAC HS1 Mux", dac_hs1_enum);
685
686/* DAC Headset 2 Mux / Mux11 */
687static const struct soc_enum dac_hs2_enum =
688 SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 2, 4, dac_text);
689
690static const struct snd_kcontrol_new dac_hs2_mux =
691 SOC_DAPM_ENUM("DAC HS2 Mux", dac_hs2_enum);
692
693/* DAC Lineout 1 Mux / Mux12 */
694static const struct soc_enum dac_lo1_enum =
695 SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 4, 4, dac_text);
696
697static const struct snd_kcontrol_new dac_lo1_mux =
698 SOC_DAPM_ENUM("DAC LO1 Mux", dac_lo1_enum);
699
700/* DAC Lineout 2 Mux / Mux13 */
701static const struct soc_enum dac_lo2_enum =
702 SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_1, 6, 4, dac_text);
703
704static const struct snd_kcontrol_new dac_lo2_mux =
705 SOC_DAPM_ENUM("DAC LO2 Mux", dac_lo2_enum);
706
707/* DAC Spearker Earphone Mux / Mux14 */
708static const struct soc_enum dac_spk_ear_enum =
709 SOC_ENUM_SINGLE(PM860X_ANA_INPUT_SEL_2, 0, 4, dac_text);
710
711static const struct snd_kcontrol_new dac_spk_ear_mux =
712 SOC_DAPM_ENUM("DAC SP Mux", dac_spk_ear_enum);
713
714/* Headset 1 Mux / Mux15 */
715static const char *in_text[] = {
716 "Digital", "Analog",
717};
718
719static const struct soc_enum hs1_enum =
720 SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 0, 2, in_text);
721
722static const struct snd_kcontrol_new hs1_mux =
723 SOC_DAPM_ENUM("Headset1 Mux", hs1_enum);
724
725/* Headset 2 Mux / Mux16 */
726static const struct soc_enum hs2_enum =
727 SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 1, 2, in_text);
728
729static const struct snd_kcontrol_new hs2_mux =
730 SOC_DAPM_ENUM("Headset2 Mux", hs2_enum);
731
732/* Lineout 1 Mux / Mux17 */
733static const struct soc_enum lo1_enum =
734 SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 2, 2, in_text);
735
736static const struct snd_kcontrol_new lo1_mux =
737 SOC_DAPM_ENUM("Lineout1 Mux", lo1_enum);
738
739/* Lineout 2 Mux / Mux18 */
740static const struct soc_enum lo2_enum =
741 SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 3, 2, in_text);
742
743static const struct snd_kcontrol_new lo2_mux =
744 SOC_DAPM_ENUM("Lineout2 Mux", lo2_enum);
745
746/* Speaker Earpiece Demux */
747static const char *spk_text[] = {
748 "Earpiece", "Speaker",
749};
750
751static const struct soc_enum spk_enum =
752 SOC_ENUM_SINGLE(PM860X_ANA_TO_ANA, 6, 2, spk_text);
753
754static const struct snd_kcontrol_new spk_demux =
755 SOC_DAPM_ENUM("Speaker Earpiece Demux", spk_enum);
756
757/* MIC Mux / Mux1 */
758static const char *mic_text[] = {
759 "Mic 1", "Mic 2",
760};
761
762static const struct soc_enum mic_enum =
763 SOC_ENUM_SINGLE(PM860X_ADC_ANA_4, 4, 2, mic_text);
764
765static const struct snd_kcontrol_new mic_mux =
766 SOC_DAPM_ENUM("MIC Mux", mic_enum);
767
768static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
769 SND_SOC_DAPM_AIF_IN("PCM SDI", "PCM Playback", 0,
770 PM860X_ADC_EN_2, 0, 0),
771 SND_SOC_DAPM_AIF_OUT("PCM SDO", "PCM Capture", 0,
772 PM860X_PCM_IFACE_3, 1, 1),
773
774
775 SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
776 PM860X_DAC_EN_2, 0, 0),
777 SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
778 PM860X_DAC_EN_2, 0, 0),
779 SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
780 PM860X_I2S_IFACE_3, 5, 1),
781 SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
782 SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
783 SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
784 SND_SOC_DAPM_MUX("EC Mux", SND_SOC_NOPM, 0, 0, &ec_mux),
785 SND_SOC_DAPM_MUX("ADCR EC Mux", SND_SOC_NOPM, 0, 0, &adcr_ec_mux),
786 SND_SOC_DAPM_SWITCH("Left EPA", SND_SOC_NOPM, 0, 0,
787 &lepa_switch_controls),
788 SND_SOC_DAPM_SWITCH("Right EPA", SND_SOC_NOPM, 0, 0,
789 &repa_switch_controls),
790
791 SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Left ADC MOD", PM860X_ADC_EN_1,
792 0, 1, 1, 0),
793 SND_SOC_DAPM_REG(snd_soc_dapm_supply, "Right ADC MOD", PM860X_ADC_EN_1,
794 1, 1, 1, 0),
795 SND_SOC_DAPM_ADC("Left ADC", NULL, PM860X_ADC_EN_2, 5, 0),
796 SND_SOC_DAPM_ADC("Right ADC", NULL, PM860X_ADC_EN_2, 4, 0),
797
798 SND_SOC_DAPM_SWITCH("AUX1 Switch", SND_SOC_NOPM, 0, 0,
799 &aux1_switch_controls),
800 SND_SOC_DAPM_SWITCH("AUX2 Switch", SND_SOC_NOPM, 0, 0,
801 &aux2_switch_controls),
802
803 SND_SOC_DAPM_MUX("MIC Mux", SND_SOC_NOPM, 0, 0, &mic_mux),
804 SND_SOC_DAPM_MICBIAS("Mic1 Bias", PM860X_ADC_ANA_1, 2, 0),
805 SND_SOC_DAPM_MICBIAS("Mic3 Bias", PM860X_ADC_ANA_1, 7, 0),
806 SND_SOC_DAPM_PGA("MIC1 Volume", PM860X_ADC_EN_1, 2, 0, NULL, 0),
807 SND_SOC_DAPM_PGA("MIC3 Volume", PM860X_ADC_EN_1, 3, 0, NULL, 0),
808 SND_SOC_DAPM_PGA("AUX1 Volume", PM860X_ADC_EN_1, 4, 0, NULL, 0),
809 SND_SOC_DAPM_PGA("AUX2 Volume", PM860X_ADC_EN_1, 5, 0, NULL, 0),
810 SND_SOC_DAPM_PGA("Sidetone PGA", PM860X_ADC_EN_2, 1, 0, NULL, 0),
811 SND_SOC_DAPM_PGA("Lofi PGA", PM860X_ADC_EN_2, 2, 0, NULL, 0),
812
813 SND_SOC_DAPM_INPUT("AUX1"),
814 SND_SOC_DAPM_INPUT("AUX2"),
815 SND_SOC_DAPM_INPUT("MIC1P"),
816 SND_SOC_DAPM_INPUT("MIC1N"),
817 SND_SOC_DAPM_INPUT("MIC2P"),
818 SND_SOC_DAPM_INPUT("MIC2N"),
819 SND_SOC_DAPM_INPUT("MIC3P"),
820 SND_SOC_DAPM_INPUT("MIC3N"),
821
822 SND_SOC_DAPM_DAC_E("Left DAC", NULL, SND_SOC_NOPM, 0, 0,
823 pm860x_dac_event,
824 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
825 SND_SOC_DAPM_DAC_E("Right DAC", NULL, SND_SOC_NOPM, 0, 0,
826 pm860x_dac_event,
827 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
828
829 SND_SOC_DAPM_MUX("I2S DIN Mux", SND_SOC_NOPM, 0, 0, &i2s_din_mux),
830 SND_SOC_DAPM_MUX("DAC HS1 Mux", SND_SOC_NOPM, 0, 0, &dac_hs1_mux),
831 SND_SOC_DAPM_MUX("DAC HS2 Mux", SND_SOC_NOPM, 0, 0, &dac_hs2_mux),
832 SND_SOC_DAPM_MUX("DAC LO1 Mux", SND_SOC_NOPM, 0, 0, &dac_lo1_mux),
833 SND_SOC_DAPM_MUX("DAC LO2 Mux", SND_SOC_NOPM, 0, 0, &dac_lo2_mux),
834 SND_SOC_DAPM_MUX("DAC SP Mux", SND_SOC_NOPM, 0, 0, &dac_spk_ear_mux),
835 SND_SOC_DAPM_MUX("Headset1 Mux", SND_SOC_NOPM, 0, 0, &hs1_mux),
836 SND_SOC_DAPM_MUX("Headset2 Mux", SND_SOC_NOPM, 0, 0, &hs2_mux),
837 SND_SOC_DAPM_MUX("Lineout1 Mux", SND_SOC_NOPM, 0, 0, &lo1_mux),
838 SND_SOC_DAPM_MUX("Lineout2 Mux", SND_SOC_NOPM, 0, 0, &lo2_mux),
839 SND_SOC_DAPM_MUX("Speaker Earpiece Demux", SND_SOC_NOPM, 0, 0,
840 &spk_demux),
841
842
843 SND_SOC_DAPM_PGA("Headset1 PGA", PM860X_DAC_EN_1, 0, 0, NULL, 0),
844 SND_SOC_DAPM_PGA("Headset2 PGA", PM860X_DAC_EN_1, 1, 0, NULL, 0),
845 SND_SOC_DAPM_OUTPUT("HS1"),
846 SND_SOC_DAPM_OUTPUT("HS2"),
847 SND_SOC_DAPM_PGA("Lineout1 PGA", PM860X_DAC_EN_1, 2, 0, NULL, 0),
848 SND_SOC_DAPM_PGA("Lineout2 PGA", PM860X_DAC_EN_1, 3, 0, NULL, 0),
849 SND_SOC_DAPM_OUTPUT("LINEOUT1"),
850 SND_SOC_DAPM_OUTPUT("LINEOUT2"),
851 SND_SOC_DAPM_PGA("Earpiece PGA", PM860X_DAC_EN_1, 4, 0, NULL, 0),
852 SND_SOC_DAPM_OUTPUT("EARP"),
853 SND_SOC_DAPM_OUTPUT("EARN"),
854 SND_SOC_DAPM_PGA("Speaker PGA", PM860X_DAC_EN_1, 5, 0, NULL, 0),
855 SND_SOC_DAPM_OUTPUT("LSP"),
856 SND_SOC_DAPM_OUTPUT("LSN"),
857 SND_SOC_DAPM_REG(snd_soc_dapm_supply, "VCODEC", PM860X_AUDIO_SUPPLIES_2,
858 0, SUPPLY_MASK, SUPPLY_MASK, 0),
859
860 PM860X_DAPM_OUTPUT("RSYNC", pm860x_rsync_event),
861};
862
863static const struct snd_soc_dapm_route audio_map[] = {
864 /* supply */
865 {"Left DAC", NULL, "VCODEC"},
866 {"Right DAC", NULL, "VCODEC"},
867 {"Left ADC", NULL, "VCODEC"},
868 {"Right ADC", NULL, "VCODEC"},
869 {"Left ADC", NULL, "Left ADC MOD"},
870 {"Right ADC", NULL, "Right ADC MOD"},
871
872 /* PCM/AIF1 Inputs */
873 {"PCM SDO", NULL, "ADC Left Mux"},
874 {"PCM SDO", NULL, "ADCR EC Mux"},
875
876 /* PCM/AFI2 Outputs */
877 {"Lofi PGA", NULL, "PCM SDI"},
878 {"Lofi PGA", NULL, "Sidetone PGA"},
879 {"Left DAC", NULL, "Lofi PGA"},
880 {"Right DAC", NULL, "Lofi PGA"},
881
882 /* I2S/AIF2 Inputs */
883 {"MIC Mux", "Mic 1", "MIC1P"},
884 {"MIC Mux", "Mic 1", "MIC1N"},
885 {"MIC Mux", "Mic 2", "MIC2P"},
886 {"MIC Mux", "Mic 2", "MIC2N"},
887 {"MIC1 Volume", NULL, "MIC Mux"},
888 {"MIC3 Volume", NULL, "MIC3P"},
889 {"MIC3 Volume", NULL, "MIC3N"},
890 {"Left ADC", NULL, "MIC1 Volume"},
891 {"Right ADC", NULL, "MIC3 Volume"},
892 {"ADC Left Mux", "ADCR", "Right ADC"},
893 {"ADC Left Mux", "ADCL", "Left ADC"},
894 {"ADC Right Mux", "ADCL", "Left ADC"},
895 {"ADC Right Mux", "ADCR", "Right ADC"},
896 {"Left EPA", "Switch", "Left DAC"},
897 {"Right EPA", "Switch", "Right DAC"},
898 {"EC Mux", "Left", "Left DAC"},
899 {"EC Mux", "Right", "Right DAC"},
900 {"EC Mux", "Left + Right", "Left DAC"},
901 {"EC Mux", "Left + Right", "Right DAC"},
902 {"ADCR EC Mux", "ADCR", "ADC Right Mux"},
903 {"ADCR EC Mux", "EC", "EC Mux"},
904 {"I2S Mic Mux", "Ex PA", "Left EPA"},
905 {"I2S Mic Mux", "Ex PA", "Right EPA"},
906 {"I2S Mic Mux", "ADC", "ADC Left Mux"},
907 {"I2S Mic Mux", "ADC", "ADCR EC Mux"},
908 {"I2S DOUT", NULL, "I2S Mic Mux"},
909
910 /* I2S/AIF2 Outputs */
911 {"I2S DIN Mux", "DIN", "I2S DIN"},
912 {"I2S DIN Mux", "DIN1", "I2S DIN1"},
913 {"Left DAC", NULL, "I2S DIN Mux"},
914 {"Right DAC", NULL, "I2S DIN Mux"},
915 {"DAC HS1 Mux", "Left", "Left DAC"},
916 {"DAC HS1 Mux", "Right", "Right DAC"},
917 {"DAC HS2 Mux", "Left", "Left DAC"},
918 {"DAC HS2 Mux", "Right", "Right DAC"},
919 {"DAC LO1 Mux", "Left", "Left DAC"},
920 {"DAC LO1 Mux", "Right", "Right DAC"},
921 {"DAC LO2 Mux", "Left", "Left DAC"},
922 {"DAC LO2 Mux", "Right", "Right DAC"},
923 {"Headset1 Mux", "Digital", "DAC HS1 Mux"},
924 {"Headset2 Mux", "Digital", "DAC HS2 Mux"},
925 {"Lineout1 Mux", "Digital", "DAC LO1 Mux"},
926 {"Lineout2 Mux", "Digital", "DAC LO2 Mux"},
927 {"Headset1 PGA", NULL, "Headset1 Mux"},
928 {"Headset2 PGA", NULL, "Headset2 Mux"},
929 {"Lineout1 PGA", NULL, "Lineout1 Mux"},
930 {"Lineout2 PGA", NULL, "Lineout2 Mux"},
931 {"DAC SP Mux", "Left", "Left DAC"},
932 {"DAC SP Mux", "Right", "Right DAC"},
933 {"Speaker Earpiece Demux", "Speaker", "DAC SP Mux"},
934 {"Speaker PGA", NULL, "Speaker Earpiece Demux"},
935 {"Earpiece PGA", NULL, "Speaker Earpiece Demux"},
936
937 {"RSYNC", NULL, "Headset1 PGA"},
938 {"RSYNC", NULL, "Headset2 PGA"},
939 {"RSYNC", NULL, "Lineout1 PGA"},
940 {"RSYNC", NULL, "Lineout2 PGA"},
941 {"RSYNC", NULL, "Speaker PGA"},
942 {"RSYNC", NULL, "Speaker PGA"},
943 {"RSYNC", NULL, "Earpiece PGA"},
944 {"RSYNC", NULL, "Earpiece PGA"},
945
946 {"HS1", NULL, "RSYNC"},
947 {"HS2", NULL, "RSYNC"},
948 {"LINEOUT1", NULL, "RSYNC"},
949 {"LINEOUT2", NULL, "RSYNC"},
950 {"LSP", NULL, "RSYNC"},
951 {"LSN", NULL, "RSYNC"},
952 {"EARP", NULL, "RSYNC"},
953 {"EARN", NULL, "RSYNC"},
954};
955
956/*
957 * Use MUTE_LEFT & MUTE_RIGHT to implement digital mute.
958 * These bits can also be used to mute.
959 */
960static int pm860x_digital_mute(struct snd_soc_dai *codec_dai, int mute)
961{
962 struct snd_soc_codec *codec = codec_dai->codec;
963 int data = 0, mask = MUTE_LEFT | MUTE_RIGHT;
964
965 if (mute)
966 data = mask;
967 snd_soc_update_bits(codec, PM860X_DAC_OFFSET, mask, data);
968 snd_soc_update_bits(codec, PM860X_EAR_CTRL_2,
969 RSYNC_CHANGE, RSYNC_CHANGE);
970 return 0;
971}
972
973static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream,
974 struct snd_pcm_hw_params *params,
975 struct snd_soc_dai *dai)
976{
977 struct snd_soc_codec *codec = dai->codec;
978 unsigned char inf = 0, mask = 0;
979
980 /* bit size */
981 switch (params_format(params)) {
982 case SNDRV_PCM_FORMAT_S16_LE:
983 inf &= ~PCM_INF2_18WL;
984 break;
985 case SNDRV_PCM_FORMAT_S18_3LE:
986 inf |= PCM_INF2_18WL;
987 break;
988 default:
989 return -EINVAL;
990 }
991 mask |= PCM_INF2_18WL;
992 snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf);
993
994 /* sample rate */
995 switch (params_rate(params)) {
996 case 8000:
997 inf = 0;
998 break;
999 case 16000:
1000 inf = 3;
1001 break;
1002 case 32000:
1003 inf = 6;
1004 break;
1005 case 48000:
1006 inf = 8;
1007 break;
1008 default:
1009 return -EINVAL;
1010 }
1011 snd_soc_update_bits(codec, PM860X_PCM_RATE, 0x0f, inf);
1012
1013 return 0;
1014}
1015
1016static int pm860x_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
1017 unsigned int fmt)
1018{
1019 struct snd_soc_codec *codec = codec_dai->codec;
1020 struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
1021 unsigned char inf = 0, mask = 0;
1022 int ret = -EINVAL;
1023
1024 mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER;
1025
1026 /* set master/slave audio interface */
1027 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1028 case SND_SOC_DAIFMT_CBM_CFM:
1029 case SND_SOC_DAIFMT_CBM_CFS:
1030 if (pm860x->dir == PM860X_CLK_DIR_OUT) {
1031 inf |= PCM_INF2_MASTER;
1032 ret = 0;
1033 }
1034 break;
1035 case SND_SOC_DAIFMT_CBS_CFS:
1036 if (pm860x->dir == PM860X_CLK_DIR_IN) {
1037 inf &= ~PCM_INF2_MASTER;
1038 ret = 0;
1039 }
1040 break;
1041 }
1042
1043 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1044 case SND_SOC_DAIFMT_I2S:
1045 inf |= PCM_EXACT_I2S;
1046 ret = 0;
1047 break;
1048 }
1049 mask |= PCM_MODE_MASK;
1050 if (ret)
1051 return ret;
1052 snd_soc_update_bits(codec, PM860X_PCM_IFACE_2, mask, inf);
1053 return 0;
1054}
1055
1056static int pm860x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1057 int clk_id, unsigned int freq, int dir)
1058{
1059 struct snd_soc_codec *codec = codec_dai->codec;
1060 struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
1061
1062 if (dir == PM860X_CLK_DIR_OUT)
1063 pm860x->dir = PM860X_CLK_DIR_OUT;
1064 else {
1065 pm860x->dir = PM860X_CLK_DIR_IN;
1066 return -EINVAL;
1067 }
1068
1069 return 0;
1070}
1071
1072static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream,
1073 struct snd_pcm_hw_params *params,
1074 struct snd_soc_dai *dai)
1075{
1076 struct snd_soc_codec *codec = dai->codec;
1077 unsigned char inf;
1078
1079 /* bit size */
1080 switch (params_format(params)) {
1081 case SNDRV_PCM_FORMAT_S16_LE:
1082 inf = 0;
1083 break;
1084 case SNDRV_PCM_FORMAT_S18_3LE:
1085 inf = PCM_INF2_18WL;
1086 break;
1087 default:
1088 return -EINVAL;
1089 }
1090 snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, PCM_INF2_18WL, inf);
1091
1092 /* sample rate */
1093 switch (params_rate(params)) {
1094 case 8000:
1095 inf = 0;
1096 break;
1097 case 11025:
1098 inf = 1;
1099 break;
1100 case 16000:
1101 inf = 3;
1102 break;
1103 case 22050:
1104 inf = 4;
1105 break;
1106 case 32000:
1107 inf = 6;
1108 break;
1109 case 44100:
1110 inf = 7;
1111 break;
1112 case 48000:
1113 inf = 8;
1114 break;
1115 default:
1116 return -EINVAL;
1117 }
1118 snd_soc_update_bits(codec, PM860X_I2S_IFACE_4, 0xf, inf);
1119
1120 return 0;
1121}
1122
1123static int pm860x_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
1124 unsigned int fmt)
1125{
1126 struct snd_soc_codec *codec = codec_dai->codec;
1127 struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
1128 unsigned char inf = 0, mask = 0;
1129
1130 mask |= PCM_INF2_BCLK | PCM_INF2_FS | PCM_INF2_MASTER;
1131
1132 /* set master/slave audio interface */
1133 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1134 case SND_SOC_DAIFMT_CBM_CFM:
1135 if (pm860x->dir == PM860X_CLK_DIR_OUT)
1136 inf |= PCM_INF2_MASTER;
1137 else
1138 return -EINVAL;
1139 break;
1140 case SND_SOC_DAIFMT_CBS_CFS:
1141 if (pm860x->dir == PM860X_CLK_DIR_IN)
1142 inf &= ~PCM_INF2_MASTER;
1143 else
1144 return -EINVAL;
1145 break;
1146 default:
1147 return -EINVAL;
1148 }
1149
1150 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1151 case SND_SOC_DAIFMT_I2S:
1152 inf |= PCM_EXACT_I2S;
1153 break;
1154 default:
1155 return -EINVAL;
1156 }
1157 mask |= PCM_MODE_MASK;
1158 snd_soc_update_bits(codec, PM860X_I2S_IFACE_2, mask, inf);
1159 return 0;
1160}
1161
1162static int pm860x_set_bias_level(struct snd_soc_codec *codec,
1163 enum snd_soc_bias_level level)
1164{
1165 int data;
1166
1167 switch (level) {
1168 case SND_SOC_BIAS_ON:
1169 break;
1170
1171 case SND_SOC_BIAS_PREPARE:
1172 break;
1173
1174 case SND_SOC_BIAS_STANDBY:
1175 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1176 /* Enable Audio PLL & Audio section */
1177 data = AUDIO_PLL | AUDIO_SECTION_RESET
1178 | AUDIO_SECTION_ON;
1179 pm860x_reg_write(codec->control_data, REG_MISC2, data);
1180 }
1181 break;
1182
1183 case SND_SOC_BIAS_OFF:
1184 data = AUDIO_PLL | AUDIO_SECTION_RESET | AUDIO_SECTION_ON;
1185 pm860x_set_bits(codec->control_data, REG_MISC2, data, 0);
1186 break;
1187 }
1188 codec->bias_level = level;
1189 return 0;
1190}
1191
1192static struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
1193 .digital_mute = pm860x_digital_mute,
1194 .hw_params = pm860x_pcm_hw_params,
1195 .set_fmt = pm860x_pcm_set_dai_fmt,
1196 .set_sysclk = pm860x_set_dai_sysclk,
1197};
1198
1199static struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
1200 .digital_mute = pm860x_digital_mute,
1201 .hw_params = pm860x_i2s_hw_params,
1202 .set_fmt = pm860x_i2s_set_dai_fmt,
1203 .set_sysclk = pm860x_set_dai_sysclk,
1204};
1205
1206#define PM860X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
1207 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
1208
1209static struct snd_soc_dai_driver pm860x_dai[] = {
1210 {
1211 /* DAI PCM */
1212 .name = "88pm860x-pcm",
1213 .id = 1,
1214 .playback = {
1215 .stream_name = "PCM Playback",
1216 .channels_min = 2,
1217 .channels_max = 2,
1218 .rates = PM860X_RATES,
1219 .formats = SNDRV_PCM_FORMAT_S16_LE | \
1220 SNDRV_PCM_FORMAT_S18_3LE,
1221 },
1222 .capture = {
1223 .stream_name = "PCM Capture",
1224 .channels_min = 2,
1225 .channels_max = 2,
1226 .rates = PM860X_RATES,
1227 .formats = SNDRV_PCM_FORMAT_S16_LE | \
1228 SNDRV_PCM_FORMAT_S18_3LE,
1229 },
1230 .ops = &pm860x_pcm_dai_ops,
1231 }, {
1232 /* DAI I2S */
1233 .name = "88pm860x-i2s",
1234 .id = 2,
1235 .playback = {
1236 .stream_name = "I2S Playback",
1237 .channels_min = 2,
1238 .channels_max = 2,
1239 .rates = SNDRV_PCM_RATE_8000_48000,
1240 .formats = SNDRV_PCM_FORMAT_S16_LE | \
1241 SNDRV_PCM_FORMAT_S18_3LE,
1242 },
1243 .capture = {
1244 .stream_name = "I2S Capture",
1245 .channels_min = 2,
1246 .channels_max = 2,
1247 .rates = SNDRV_PCM_RATE_8000_48000,
1248 .formats = SNDRV_PCM_FORMAT_S16_LE | \
1249 SNDRV_PCM_FORMAT_S18_3LE,
1250 },
1251 .ops = &pm860x_i2s_dai_ops,
1252 },
1253};
1254
1255static irqreturn_t pm860x_codec_handler(int irq, void *data)
1256{
1257 struct pm860x_priv *pm860x = data;
1258 int status, shrt, report = 0, mic_report = 0;
1259 int mask;
1260
1261 status = pm860x_reg_read(pm860x->i2c, REG_STATUS_1);
1262 shrt = pm860x_reg_read(pm860x->i2c, REG_SHORTS);
1263 mask = pm860x->det.hs_shrt | pm860x->det.hook_det | pm860x->det.lo_shrt
1264 | pm860x->det.hp_det;
1265
1266 if ((pm860x->det.hp_det & SND_JACK_HEADPHONE)
1267 && (status & HEADSET_STATUS))
1268 report |= SND_JACK_HEADPHONE;
1269
1270 if ((pm860x->det.mic_det & SND_JACK_MICROPHONE)
1271 && (status & MIC_STATUS))
1272 mic_report |= SND_JACK_MICROPHONE;
1273
1274 if (pm860x->det.hs_shrt && (shrt & (SHORT_HS1 | SHORT_HS2)))
1275 report |= pm860x->det.hs_shrt;
1276
1277 if (pm860x->det.hook_det && (status & HOOK_STATUS))
1278 report |= pm860x->det.hook_det;
1279
1280 if (pm860x->det.lo_shrt && (shrt & (SHORT_LO1 | SHORT_LO2)))
1281 report |= pm860x->det.lo_shrt;
1282
1283 if (report)
1284 snd_soc_jack_report(pm860x->det.hp_jack, report, mask);
1285 if (mic_report)
1286 snd_soc_jack_report(pm860x->det.mic_jack, SND_JACK_MICROPHONE,
1287 SND_JACK_MICROPHONE);
1288
1289 dev_dbg(pm860x->codec->dev, "headphone report:0x%x, mask:%x\n",
1290 report, mask);
1291 dev_dbg(pm860x->codec->dev, "microphone report:0x%x\n", mic_report);
1292 return IRQ_HANDLED;
1293}
1294
1295int pm860x_hs_jack_detect(struct snd_soc_codec *codec,
1296 struct snd_soc_jack *jack,
1297 int det, int hook, int hs_shrt, int lo_shrt)
1298{
1299 struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
1300 int data;
1301
1302 pm860x->det.hp_jack = jack;
1303 pm860x->det.hp_det = det;
1304 pm860x->det.hook_det = hook;
1305 pm860x->det.hs_shrt = hs_shrt;
1306 pm860x->det.lo_shrt = lo_shrt;
1307
1308 if (det & SND_JACK_HEADPHONE)
1309 pm860x_set_bits(codec->control_data, REG_HS_DET,
1310 EN_HS_DET, EN_HS_DET);
1311 /* headset short detect */
1312 if (hs_shrt) {
1313 data = CLR_SHORT_HS2 | CLR_SHORT_HS1;
1314 pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
1315 }
1316 /* Lineout short detect */
1317 if (lo_shrt) {
1318 data = CLR_SHORT_LO2 | CLR_SHORT_LO1;
1319 pm860x_set_bits(codec->control_data, REG_SHORTS, data, data);
1320 }
1321
1322 /* sync status */
1323 pm860x_codec_handler(0, pm860x);
1324 return 0;
1325}
1326EXPORT_SYMBOL_GPL(pm860x_hs_jack_detect);
1327
1328int pm860x_mic_jack_detect(struct snd_soc_codec *codec,
1329 struct snd_soc_jack *jack, int det)
1330{
1331 struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
1332
1333 pm860x->det.mic_jack = jack;
1334 pm860x->det.mic_det = det;
1335
1336 if (det & SND_JACK_MICROPHONE)
1337 pm860x_set_bits(codec->control_data, REG_MIC_DET,
1338 MICDET_MASK, MICDET_MASK);
1339
1340 /* sync status */
1341 pm860x_codec_handler(0, pm860x);
1342 return 0;
1343}
1344EXPORT_SYMBOL_GPL(pm860x_mic_jack_detect);
1345
1346static int pm860x_probe(struct snd_soc_codec *codec)
1347{
1348 struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
1349 int i, ret;
1350
1351 pm860x->codec = codec;
1352
1353 codec->control_data = pm860x->i2c;
1354
1355 for (i = 0; i < 4; i++) {
1356 ret = request_threaded_irq(pm860x->irq[i], NULL,
1357 pm860x_codec_handler, IRQF_ONESHOT,
1358 pm860x->name[i], pm860x);
1359 if (ret < 0) {
1360 dev_err(codec->dev, "Failed to request IRQ!\n");
1361 goto out_irq;
1362 }
1363 }
1364
1365 pm860x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1366
1367 ret = pm860x_bulk_read(codec->control_data, REG_CACHE_BASE,
1368 REG_CACHE_SIZE, codec->reg_cache);
1369 if (ret < 0) {
1370 dev_err(codec->dev, "Failed to fill register cache: %d\n",
1371 ret);
1372 goto out_codec;
1373 }
1374
1375 snd_soc_add_controls(codec, pm860x_snd_controls,
1376 ARRAY_SIZE(pm860x_snd_controls));
1377 snd_soc_dapm_new_controls(codec, pm860x_dapm_widgets,
1378 ARRAY_SIZE(pm860x_dapm_widgets));
1379 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
1380 return 0;
1381
1382out_codec:
1383 i = 3;
1384out_irq:
1385 for (; i >= 0; i--)
1386 free_irq(pm860x->irq[i], pm860x);
1387 return -EINVAL;
1388}
1389
1390static int pm860x_remove(struct snd_soc_codec *codec)
1391{
1392 struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
1393 int i;
1394
1395 for (i = 3; i >= 0; i--)
1396 free_irq(pm860x->irq[i], pm860x);
1397 pm860x_set_bias_level(codec, SND_SOC_BIAS_OFF);
1398 return 0;
1399}
1400
1401static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
1402 .probe = pm860x_probe,
1403 .remove = pm860x_remove,
1404 .read = pm860x_read_reg_cache,
1405 .write = pm860x_write_reg_cache,
1406 .reg_cache_size = REG_CACHE_SIZE,
1407 .reg_word_size = sizeof(u8),
1408 .set_bias_level = pm860x_set_bias_level,
1409};
1410
1411static int __devinit pm860x_codec_probe(struct platform_device *pdev)
1412{
1413 struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
1414 struct pm860x_priv *pm860x;
1415 struct resource *res;
1416 int i, ret;
1417
1418 pm860x = kzalloc(sizeof(struct pm860x_priv), GFP_KERNEL);
1419 if (pm860x == NULL)
1420 return -ENOMEM;
1421
1422 pm860x->chip = chip;
1423 pm860x->i2c = (chip->id == CHIP_PM8607) ? chip->client
1424 : chip->companion;
1425 platform_set_drvdata(pdev, pm860x);
1426
1427 for (i = 0; i < 4; i++) {
1428 res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
1429 if (!res) {
1430 dev_err(&pdev->dev, "Failed to get IRQ resources\n");
1431 goto out;
1432 }
1433 pm860x->irq[i] = res->start + chip->irq_base;
1434 strncpy(pm860x->name[i], res->name, MAX_NAME_LEN);
1435 }
1436
1437 ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_pm860x,
1438 pm860x_dai, ARRAY_SIZE(pm860x_dai));
1439 if (ret) {
1440 dev_err(&pdev->dev, "Failed to register codec\n");
1441 goto out;
1442 }
1443 return ret;
1444
1445out:
1446 platform_set_drvdata(pdev, NULL);
1447 kfree(pm860x);
1448 return -EINVAL;
1449}
1450
1451static int __devexit pm860x_codec_remove(struct platform_device *pdev)
1452{
1453 struct pm860x_priv *pm860x = platform_get_drvdata(pdev);
1454
1455 snd_soc_unregister_codec(&pdev->dev);
1456 platform_set_drvdata(pdev, NULL);
1457 kfree(pm860x);
1458 return 0;
1459}
1460
1461static struct platform_driver pm860x_codec_driver = {
1462 .driver = {
1463 .name = "88pm860x-codec",
1464 .owner = THIS_MODULE,
1465 },
1466 .probe = pm860x_codec_probe,
1467 .remove = __devexit_p(pm860x_codec_remove),
1468};
1469
1470static __init int pm860x_init(void)
1471{
1472 return platform_driver_register(&pm860x_codec_driver);
1473}
1474module_init(pm860x_init);
1475
1476static __exit void pm860x_exit(void)
1477{
1478 platform_driver_unregister(&pm860x_codec_driver);
1479}
1480module_exit(pm860x_exit);
1481
1482MODULE_DESCRIPTION("ASoC 88PM860x driver");
1483MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
1484MODULE_LICENSE("GPL");
1485MODULE_ALIAS("platform:88pm860x-codec");
1486
diff --git a/sound/soc/codecs/88pm860x-codec.h b/sound/soc/codecs/88pm860x-codec.h
new file mode 100644
index 000000000000..3364ba4a3607
--- /dev/null
+++ b/sound/soc/codecs/88pm860x-codec.h
@@ -0,0 +1,97 @@
1/*
2 * 88pm860x-codec.h -- 88PM860x ALSA SoC Audio Driver
3 *
4 * Copyright 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef __88PM860X_H
13#define __88PM860X_H
14
15/* The offset of these registers are 0xb0 */
16#define PM860X_PCM_IFACE_1 0x00
17#define PM860X_PCM_IFACE_2 0x01
18#define PM860X_PCM_IFACE_3 0x02
19#define PM860X_PCM_RATE 0x03
20#define PM860X_EC_PATH 0x04
21#define PM860X_SIDETONE_L_GAIN 0x05
22#define PM860X_SIDETONE_R_GAIN 0x06
23#define PM860X_SIDETONE_SHIFT 0x07
24#define PM860X_ADC_OFFSET_1 0x08
25#define PM860X_ADC_OFFSET_2 0x09
26#define PM860X_DMIC_DELAY 0x0a
27
28#define PM860X_I2S_IFACE_1 0x0b
29#define PM860X_I2S_IFACE_2 0x0c
30#define PM860X_I2S_IFACE_3 0x0d
31#define PM860X_I2S_IFACE_4 0x0e
32#define PM860X_EQUALIZER_N0_1 0x0f
33#define PM860X_EQUALIZER_N0_2 0x10
34#define PM860X_EQUALIZER_N1_1 0x11
35#define PM860X_EQUALIZER_N1_2 0x12
36#define PM860X_EQUALIZER_D1_1 0x13
37#define PM860X_EQUALIZER_D1_2 0x14
38#define PM860X_LOFI_GAIN_LEFT 0x15
39#define PM860X_LOFI_GAIN_RIGHT 0x16
40#define PM860X_HIFIL_GAIN_LEFT 0x17
41#define PM860X_HIFIL_GAIN_RIGHT 0x18
42#define PM860X_HIFIR_GAIN_LEFT 0x19
43#define PM860X_HIFIR_GAIN_RIGHT 0x1a
44#define PM860X_DAC_OFFSET 0x1b
45#define PM860X_OFFSET_LEFT_1 0x1c
46#define PM860X_OFFSET_LEFT_2 0x1d
47#define PM860X_OFFSET_RIGHT_1 0x1e
48#define PM860X_OFFSET_RIGHT_2 0x1f
49#define PM860X_ADC_ANA_1 0x20
50#define PM860X_ADC_ANA_2 0x21
51#define PM860X_ADC_ANA_3 0x22
52#define PM860X_ADC_ANA_4 0x23
53#define PM860X_ANA_TO_ANA 0x24
54#define PM860X_HS1_CTRL 0x25
55#define PM860X_HS2_CTRL 0x26
56#define PM860X_LO1_CTRL 0x27
57#define PM860X_LO2_CTRL 0x28
58#define PM860X_EAR_CTRL_1 0x29
59#define PM860X_EAR_CTRL_2 0x2a
60#define PM860X_AUDIO_SUPPLIES_1 0x2b
61#define PM860X_AUDIO_SUPPLIES_2 0x2c
62#define PM860X_ADC_EN_1 0x2d
63#define PM860X_ADC_EN_2 0x2e
64#define PM860X_DAC_EN_1 0x2f
65#define PM860X_DAC_EN_2 0x31
66#define PM860X_AUDIO_CAL_1 0x32
67#define PM860X_AUDIO_CAL_2 0x33
68#define PM860X_AUDIO_CAL_3 0x34
69#define PM860X_AUDIO_CAL_4 0x35
70#define PM860X_AUDIO_CAL_5 0x36
71#define PM860X_ANA_INPUT_SEL_1 0x37
72#define PM860X_ANA_INPUT_SEL_2 0x38
73
74#define PM860X_PCM_IFACE_4 0x39
75#define PM860X_I2S_IFACE_5 0x3a
76
77#define PM860X_SHORTS 0x3b
78#define PM860X_PLL_ADJ_1 0x3c
79#define PM860X_PLL_ADJ_2 0x3d
80
81/* bits definition */
82#define PM860X_CLK_DIR_IN 0
83#define PM860X_CLK_DIR_OUT 1
84
85#define PM860X_DET_HEADSET (1 << 0)
86#define PM860X_DET_MIC (1 << 1)
87#define PM860X_DET_HOOK (1 << 2)
88#define PM860X_SHORT_HEADSET (1 << 3)
89#define PM860X_SHORT_LINEOUT (1 << 4)
90#define PM860X_DET_MASK 0x1F
91
92extern int pm860x_hs_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *,
93 int, int, int, int);
94extern int pm860x_mic_jack_detect(struct snd_soc_codec *, struct snd_soc_jack *,
95 int);
96
97#endif /* __88PM860X_H */
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 83f5c67d3c41..94a9d06b9027 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -10,6 +10,7 @@ config SND_SOC_I2C_AND_SPI
10 10
11config SND_SOC_ALL_CODECS 11config SND_SOC_ALL_CODECS
12 tristate "Build all ASoC CODEC drivers" 12 tristate "Build all ASoC CODEC drivers"
13 select SND_SOC_88PM860X if MFD_88PM860X
13 select SND_SOC_L3 14 select SND_SOC_L3
14 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS 15 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
15 select SND_SOC_AD1836 if SPI_MASTER 16 select SND_SOC_AD1836 if SPI_MASTER
@@ -26,6 +27,7 @@ config SND_SOC_ALL_CODECS
26 select SND_SOC_CS4270 if I2C 27 select SND_SOC_CS4270 if I2C
27 select SND_SOC_DA7210 if I2C 28 select SND_SOC_DA7210 if I2C
28 select SND_SOC_JZ4740 if SOC_JZ4740 29 select SND_SOC_JZ4740 if SOC_JZ4740
30 select SND_SOC_MAX98088 if I2C
29 select SND_SOC_MAX9877 if I2C 31 select SND_SOC_MAX9877 if I2C
30 select SND_SOC_PCM3008 32 select SND_SOC_PCM3008
31 select SND_SOC_SPDIF 33 select SND_SOC_SPDIF
@@ -40,6 +42,7 @@ config SND_SOC_ALL_CODECS
40 select SND_SOC_TWL6040 if TWL4030_CORE 42 select SND_SOC_TWL6040 if TWL4030_CORE
41 select SND_SOC_UDA134X 43 select SND_SOC_UDA134X
42 select SND_SOC_UDA1380 if I2C 44 select SND_SOC_UDA1380 if I2C
45 select SND_SOC_WL1273 if WL1273_CORE
43 select SND_SOC_WM2000 if I2C 46 select SND_SOC_WM2000 if I2C
44 select SND_SOC_WM8350 if MFD_WM8350 47 select SND_SOC_WM8350 if MFD_WM8350
45 select SND_SOC_WM8400 if MFD_WM8400 48 select SND_SOC_WM8400 if MFD_WM8400
@@ -54,6 +57,7 @@ config SND_SOC_ALL_CODECS
54 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI 57 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
55 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI 58 select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI
56 select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI 59 select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI
60 select SND_SOC_WM8804 if SND_SOC_I2C_AND_SPI
57 select SND_SOC_WM8900 if I2C 61 select SND_SOC_WM8900 if I2C
58 select SND_SOC_WM8903 if I2C 62 select SND_SOC_WM8903 if I2C
59 select SND_SOC_WM8904 if I2C 63 select SND_SOC_WM8904 if I2C
@@ -61,9 +65,11 @@ config SND_SOC_ALL_CODECS
61 select SND_SOC_WM8955 if I2C 65 select SND_SOC_WM8955 if I2C
62 select SND_SOC_WM8960 if I2C 66 select SND_SOC_WM8960 if I2C
63 select SND_SOC_WM8961 if I2C 67 select SND_SOC_WM8961 if I2C
68 select SND_SOC_WM8962 if I2C
64 select SND_SOC_WM8971 if I2C 69 select SND_SOC_WM8971 if I2C
65 select SND_SOC_WM8974 if I2C 70 select SND_SOC_WM8974 if I2C
66 select SND_SOC_WM8978 if I2C 71 select SND_SOC_WM8978 if I2C
72 select SND_SOC_WM8985 if SND_SOC_I2C_AND_SPI
67 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI 73 select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
68 select SND_SOC_WM8990 if I2C 74 select SND_SOC_WM8990 if I2C
69 select SND_SOC_WM8993 if I2C 75 select SND_SOC_WM8993 if I2C
@@ -84,6 +90,9 @@ config SND_SOC_ALL_CODECS
84 90
85 If unsure select "N". 91 If unsure select "N".
86 92
93config SND_SOC_88PM860X
94 tristate
95
87config SND_SOC_WM_HUBS 96config SND_SOC_WM_HUBS
88 tristate 97 tristate
89 default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y 98 default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
@@ -150,6 +159,9 @@ config SND_SOC_L3
150config SND_SOC_DA7210 159config SND_SOC_DA7210
151 tristate 160 tristate
152 161
162config SND_SOC_MAX98088
163 tristate
164
153config SND_SOC_PCM3008 165config SND_SOC_PCM3008
154 tristate 166 tristate
155 167
@@ -188,6 +200,9 @@ config SND_SOC_UDA134X
188config SND_SOC_UDA1380 200config SND_SOC_UDA1380
189 tristate 201 tristate
190 202
203config SND_SOC_WL1273
204 tristate
205
191config SND_SOC_WM8350 206config SND_SOC_WM8350
192 tristate 207 tristate
193 208
@@ -227,6 +242,9 @@ config SND_SOC_WM8753
227config SND_SOC_WM8776 242config SND_SOC_WM8776
228 tristate 243 tristate
229 244
245config SND_SOC_WM8804
246 tristate
247
230config SND_SOC_WM8900 248config SND_SOC_WM8900
231 tristate 249 tristate
232 250
@@ -248,6 +266,9 @@ config SND_SOC_WM8960
248config SND_SOC_WM8961 266config SND_SOC_WM8961
249 tristate 267 tristate
250 268
269config SND_SOC_WM8962
270 tristate
271
251config SND_SOC_WM8971 272config SND_SOC_WM8971
252 tristate 273 tristate
253 274
@@ -257,6 +278,9 @@ config SND_SOC_WM8974
257config SND_SOC_WM8978 278config SND_SOC_WM8978
258 tristate 279 tristate
259 280
281config SND_SOC_WM8985
282 tristate
283
260config SND_SOC_WM8988 284config SND_SOC_WM8988
261 tristate 285 tristate
262 286
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 53524095759c..f67a2d6f7a46 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -1,3 +1,4 @@
1snd-soc-88pm860x-objs := 88pm860x-codec.o
1snd-soc-ac97-objs := ac97.o 2snd-soc-ac97-objs := ac97.o
2snd-soc-ad1836-objs := ad1836.o 3snd-soc-ad1836-objs := ad1836.o
3snd-soc-ad193x-objs := ad193x.o 4snd-soc-ad193x-objs := ad193x.o
@@ -14,6 +15,7 @@ snd-soc-cs4270-objs := cs4270.o
14snd-soc-cx20442-objs := cx20442.o 15snd-soc-cx20442-objs := cx20442.o
15snd-soc-da7210-objs := da7210.o 16snd-soc-da7210-objs := da7210.o
16snd-soc-l3-objs := l3.o 17snd-soc-l3-objs := l3.o
18snd-soc-max98088-objs := max98088.o
17snd-soc-pcm3008-objs := pcm3008.o 19snd-soc-pcm3008-objs := pcm3008.o
18snd-soc-spdif-objs := spdif_transciever.o 20snd-soc-spdif-objs := spdif_transciever.o
19snd-soc-ssm2602-objs := ssm2602.o 21snd-soc-ssm2602-objs := ssm2602.o
@@ -26,6 +28,7 @@ snd-soc-twl4030-objs := twl4030.o
26snd-soc-twl6040-objs := twl6040.o 28snd-soc-twl6040-objs := twl6040.o
27snd-soc-uda134x-objs := uda134x.o 29snd-soc-uda134x-objs := uda134x.o
28snd-soc-uda1380-objs := uda1380.o 30snd-soc-uda1380-objs := uda1380.o
31snd-soc-wl1273-objs := wl1273.o
29snd-soc-wm8350-objs := wm8350.o 32snd-soc-wm8350-objs := wm8350.o
30snd-soc-wm8400-objs := wm8400.o 33snd-soc-wm8400-objs := wm8400.o
31snd-soc-wm8510-objs := wm8510.o 34snd-soc-wm8510-objs := wm8510.o
@@ -39,6 +42,7 @@ snd-soc-wm8741-objs := wm8741.o
39snd-soc-wm8750-objs := wm8750.o 42snd-soc-wm8750-objs := wm8750.o
40snd-soc-wm8753-objs := wm8753.o 43snd-soc-wm8753-objs := wm8753.o
41snd-soc-wm8776-objs := wm8776.o 44snd-soc-wm8776-objs := wm8776.o
45snd-soc-wm8804-objs := wm8804.o
42snd-soc-wm8900-objs := wm8900.o 46snd-soc-wm8900-objs := wm8900.o
43snd-soc-wm8903-objs := wm8903.o 47snd-soc-wm8903-objs := wm8903.o
44snd-soc-wm8904-objs := wm8904.o 48snd-soc-wm8904-objs := wm8904.o
@@ -46,9 +50,11 @@ snd-soc-wm8940-objs := wm8940.o
46snd-soc-wm8955-objs := wm8955.o 50snd-soc-wm8955-objs := wm8955.o
47snd-soc-wm8960-objs := wm8960.o 51snd-soc-wm8960-objs := wm8960.o
48snd-soc-wm8961-objs := wm8961.o 52snd-soc-wm8961-objs := wm8961.o
53snd-soc-wm8962-objs := wm8962.o
49snd-soc-wm8971-objs := wm8971.o 54snd-soc-wm8971-objs := wm8971.o
50snd-soc-wm8974-objs := wm8974.o 55snd-soc-wm8974-objs := wm8974.o
51snd-soc-wm8978-objs := wm8978.o 56snd-soc-wm8978-objs := wm8978.o
57snd-soc-wm8985-objs := wm8985.o
52snd-soc-wm8988-objs := wm8988.o 58snd-soc-wm8988-objs := wm8988.o
53snd-soc-wm8990-objs := wm8990.o 59snd-soc-wm8990-objs := wm8990.o
54snd-soc-wm8993-objs := wm8993.o 60snd-soc-wm8993-objs := wm8993.o
@@ -66,6 +72,7 @@ snd-soc-tpa6130a2-objs := tpa6130a2.o
66snd-soc-wm2000-objs := wm2000.o 72snd-soc-wm2000-objs := wm2000.o
67snd-soc-wm9090-objs := wm9090.o 73snd-soc-wm9090-objs := wm9090.o
68 74
75obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
69obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 76obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
70obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o 77obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
71obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o 78obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
@@ -83,6 +90,7 @@ obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
83obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o 90obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
84obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 91obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
85obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o 92obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
93obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
86obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o 94obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
87obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o 95obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
88obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o 96obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@@ -95,6 +103,7 @@ obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
95obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o 103obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
96obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o 104obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
97obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 105obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
106obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
98obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o 107obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
99obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o 108obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
100obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 109obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
@@ -108,6 +117,7 @@ obj-$(CONFIG_SND_SOC_WM8741) += snd-soc-wm8741.o
108obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 117obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
109obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o 118obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
110obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o 119obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o
120obj-$(CONFIG_SND_SOC_WM8804) += snd-soc-wm8804.o
111obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o 121obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o
112obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o 122obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
113obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o 123obj-$(CONFIG_SND_SOC_WM8904) += snd-soc-wm8904.o
@@ -115,9 +125,11 @@ obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o
115obj-$(CONFIG_SND_SOC_WM8955) += snd-soc-wm8955.o 125obj-$(CONFIG_SND_SOC_WM8955) += snd-soc-wm8955.o
116obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o 126obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o
117obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o 127obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o
128obj-$(CONFIG_SND_SOC_WM8962) += snd-soc-wm8962.o
118obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o 129obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o
119obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o 130obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o
120obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o 131obj-$(CONFIG_SND_SOC_WM8978) += snd-soc-wm8978.o
132obj-$(CONFIG_SND_SOC_WM8985) += snd-soc-wm8985.o
121obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o 133obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o
122obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o 134obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o
123obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o 135obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 1f5e57a4bb7a..3c087936aa57 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -21,17 +21,13 @@
21#include <sound/ac97_codec.h> 21#include <sound/ac97_codec.h>
22#include <sound/initval.h> 22#include <sound/initval.h>
23#include <sound/soc.h> 23#include <sound/soc.h>
24#include "ac97.h"
25
26#define AC97_VERSION "0.6"
27 24
28static int ac97_prepare(struct snd_pcm_substream *substream, 25static int ac97_prepare(struct snd_pcm_substream *substream,
29 struct snd_soc_dai *dai) 26 struct snd_soc_dai *dai)
30{ 27{
31 struct snd_pcm_runtime *runtime = substream->runtime; 28 struct snd_pcm_runtime *runtime = substream->runtime;
32 struct snd_soc_pcm_runtime *rtd = substream->private_data; 29 struct snd_soc_pcm_runtime *rtd = substream->private_data;
33 struct snd_soc_device *socdev = rtd->socdev; 30 struct snd_soc_codec *codec = rtd->codec;
34 struct snd_soc_codec *codec = socdev->card->codec;
35 31
36 int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 32 int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
37 AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; 33 AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
@@ -46,8 +42,8 @@ static struct snd_soc_dai_ops ac97_dai_ops = {
46 .prepare = ac97_prepare, 42 .prepare = ac97_prepare,
47}; 43};
48 44
49struct snd_soc_dai ac97_dai = { 45static struct snd_soc_dai_driver ac97_dai = {
50 .name = "AC97 HiFi", 46 .name = "ac97-hifi",
51 .ac97_control = 1, 47 .ac97_control = 1,
52 .playback = { 48 .playback = {
53 .stream_name = "AC97 Playback", 49 .stream_name = "AC97 Playback",
@@ -63,7 +59,6 @@ struct snd_soc_dai ac97_dai = {
63 .formats = SND_SOC_STD_AC97_FMTS,}, 59 .formats = SND_SOC_STD_AC97_FMTS,},
64 .ops = &ac97_dai_ops, 60 .ops = &ac97_dai_ops,
65}; 61};
66EXPORT_SYMBOL_GPL(ac97_dai);
67 62
68static unsigned int ac97_read(struct snd_soc_codec *codec, 63static unsigned int ac97_read(struct snd_soc_codec *codec,
69 unsigned int reg) 64 unsigned int reg)
@@ -78,95 +73,41 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
78 return 0; 73 return 0;
79} 74}
80 75
81static int ac97_soc_probe(struct platform_device *pdev) 76static int ac97_soc_probe(struct snd_soc_codec *codec)
82{ 77{
83 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
84 struct snd_soc_card *card = socdev->card;
85 struct snd_soc_codec *codec;
86 struct snd_ac97_bus *ac97_bus; 78 struct snd_ac97_bus *ac97_bus;
87 struct snd_ac97_template ac97_template; 79 struct snd_ac97_template ac97_template;
88 int i; 80 int ret;
89 int ret = 0;
90
91 printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
92
93 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
94 if (!socdev->card->codec)
95 return -ENOMEM;
96 codec = socdev->card->codec;
97 mutex_init(&codec->mutex);
98
99 codec->name = "AC97";
100 codec->owner = THIS_MODULE;
101 codec->dai = &ac97_dai;
102 codec->num_dai = 1;
103 codec->write = ac97_write;
104 codec->read = ac97_read;
105 INIT_LIST_HEAD(&codec->dapm_widgets);
106 INIT_LIST_HEAD(&codec->dapm_paths);
107
108 /* register pcms */
109 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
110 if (ret < 0)
111 goto err;
112 81
113 /* add codec as bus device for standard ac97 */ 82 /* add codec as bus device for standard ac97 */
114 ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus); 83 ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus);
115 if (ret < 0) 84 if (ret < 0)
116 goto bus_err; 85 return ret;
117 86
118 memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); 87 memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
119 ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); 88 ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
120 if (ret < 0) 89 if (ret < 0)
121 goto bus_err; 90 return ret;
122
123 for (i = 0; i < card->num_links; i++) {
124 if (card->dai_link[i].codec_dai->ac97_control) {
125 snd_ac97_dev_add_pdata(codec->ac97,
126 card->dai_link[i].cpu_dai->ac97_pdata);
127 }
128 }
129 91
130 return 0; 92 return 0;
131
132bus_err:
133 snd_soc_free_pcms(socdev);
134
135err:
136 kfree(socdev->card->codec);
137 socdev->card->codec = NULL;
138 return ret;
139} 93}
140 94
141static int ac97_soc_remove(struct platform_device *pdev) 95static int ac97_soc_remove(struct snd_soc_codec *codec)
142{ 96{
143 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
144 struct snd_soc_codec *codec = socdev->card->codec;
145
146 if (!codec)
147 return 0;
148
149 snd_soc_free_pcms(socdev);
150 kfree(socdev->card->codec);
151
152 return 0; 97 return 0;
153} 98}
154 99
155#ifdef CONFIG_PM 100#ifdef CONFIG_PM
156static int ac97_soc_suspend(struct platform_device *pdev, pm_message_t msg) 101static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
157{ 102{
158 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 103 snd_ac97_suspend(codec->ac97);
159
160 snd_ac97_suspend(socdev->card->codec->ac97);
161 104
162 return 0; 105 return 0;
163} 106}
164 107
165static int ac97_soc_resume(struct platform_device *pdev) 108static int ac97_soc_resume(struct snd_soc_codec *codec)
166{ 109{
167 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 110 snd_ac97_resume(codec->ac97);
168
169 snd_ac97_resume(socdev->card->codec->ac97);
170 111
171 return 0; 112 return 0;
172} 113}
@@ -175,14 +116,50 @@ static int ac97_soc_resume(struct platform_device *pdev)
175#define ac97_soc_resume NULL 116#define ac97_soc_resume NULL
176#endif 117#endif
177 118
178struct snd_soc_codec_device soc_codec_dev_ac97 = { 119static struct snd_soc_codec_driver soc_codec_dev_ac97 = {
120 .write = ac97_write,
121 .read = ac97_read,
179 .probe = ac97_soc_probe, 122 .probe = ac97_soc_probe,
180 .remove = ac97_soc_remove, 123 .remove = ac97_soc_remove,
181 .suspend = ac97_soc_suspend, 124 .suspend = ac97_soc_suspend,
182 .resume = ac97_soc_resume, 125 .resume = ac97_soc_resume,
183}; 126};
184EXPORT_SYMBOL_GPL(soc_codec_dev_ac97); 127
128static __devinit int ac97_probe(struct platform_device *pdev)
129{
130 return snd_soc_register_codec(&pdev->dev,
131 &soc_codec_dev_ac97, &ac97_dai, 1);
132}
133
134static int __devexit ac97_remove(struct platform_device *pdev)
135{
136 snd_soc_unregister_codec(&pdev->dev);
137 return 0;
138}
139
140static struct platform_driver ac97_codec_driver = {
141 .driver = {
142 .name = "ac97-codec",
143 .owner = THIS_MODULE,
144 },
145
146 .probe = ac97_probe,
147 .remove = __devexit_p(ac97_remove),
148};
149
150static int __init ac97_init(void)
151{
152 return platform_driver_register(&ac97_codec_driver);
153}
154module_init(ac97_init);
155
156static void __exit ac97_exit(void)
157{
158 platform_driver_unregister(&ac97_codec_driver);
159}
160module_exit(ac97_exit);
185 161
186MODULE_DESCRIPTION("Soc Generic AC97 driver"); 162MODULE_DESCRIPTION("Soc Generic AC97 driver");
187MODULE_AUTHOR("Liam Girdwood"); 163MODULE_AUTHOR("Liam Girdwood");
188MODULE_LICENSE("GPL"); 164MODULE_LICENSE("GPL");
165MODULE_ALIAS("platform:ac97-codec");
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h
deleted file mode 100644
index 281aa42e2bbb..000000000000
--- a/sound/soc/codecs/ac97.h
+++ /dev/null
@@ -1,19 +0,0 @@
1/*
2 * linux/sound/codecs/ac97.h -- ALSA SoC Layer
3 *
4 * Author: Liam Girdwood
5 * Created: Dec 1st 2005
6 * Copyright: Wolfson Microelectronics. PLC.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __LINUX_SND_SOC_AC97_H
14#define __LINUX_SND_SOC_AC97_H
15
16extern struct snd_soc_codec_device soc_codec_dev_ac97;
17extern struct snd_soc_dai ac97_dai;
18
19#endif
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index a01006c8c606..d272534c8f84 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -33,15 +33,10 @@
33 33
34/* codec private data */ 34/* codec private data */
35struct ad1836_priv { 35struct ad1836_priv {
36 struct snd_soc_codec codec; 36 enum snd_soc_control_type control_type;
37 u16 reg_cache[AD1836_NUM_REGS]; 37 void *control_data;
38}; 38};
39 39
40static struct snd_soc_codec *ad1836_codec;
41struct snd_soc_codec_device soc_codec_dev_ad1836;
42static int ad1836_register(struct ad1836_priv *ad1836);
43static void ad1836_unregister(struct ad1836_priv *ad1836);
44
45/* 40/*
46 * AD1836 volume/mute/de-emphasis etc. controls 41 * AD1836 volume/mute/de-emphasis etc. controls
47 */ 42 */
@@ -146,8 +141,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
146 int word_len = 0; 141 int word_len = 0;
147 142
148 struct snd_soc_pcm_runtime *rtd = substream->private_data; 143 struct snd_soc_pcm_runtime *rtd = substream->private_data;
149 struct snd_soc_device *socdev = rtd->socdev; 144 struct snd_soc_codec *codec = rtd->codec;
150 struct snd_soc_codec *codec = socdev->card->codec;
151 145
152 /* bit size */ 146 /* bit size */
153 switch (params_format(params)) { 147 switch (params_format(params)) {
@@ -173,12 +167,9 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
173} 167}
174 168
175#ifdef CONFIG_PM 169#ifdef CONFIG_PM
176static int ad1836_soc_suspend(struct platform_device *pdev, 170static int ad1836_soc_suspend(struct snd_soc_codec *codec,
177 pm_message_t state) 171 pm_message_t state)
178{ 172{
179 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
180 struct snd_soc_codec *codec = socdev->card->codec;
181
182 /* reset clock control mode */ 173 /* reset clock control mode */
183 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 174 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
184 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; 175 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
@@ -186,11 +177,8 @@ static int ad1836_soc_suspend(struct platform_device *pdev,
186 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); 177 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
187} 178}
188 179
189static int ad1836_soc_resume(struct platform_device *pdev) 180static int ad1836_soc_resume(struct snd_soc_codec *codec)
190{ 181{
191 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
192 struct snd_soc_codec *codec = socdev->card->codec;
193
194 /* restore clock control mode */ 182 /* restore clock control mode */
195 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); 183 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
196 adc_ctrl2 |= AD1836_ADC_AUX; 184 adc_ctrl2 |= AD1836_ADC_AUX;
@@ -202,49 +190,14 @@ static int ad1836_soc_resume(struct platform_device *pdev)
202#define ad1836_soc_resume NULL 190#define ad1836_soc_resume NULL
203#endif 191#endif
204 192
205static int __devinit ad1836_spi_probe(struct spi_device *spi)
206{
207 struct snd_soc_codec *codec;
208 struct ad1836_priv *ad1836;
209
210 ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
211 if (ad1836 == NULL)
212 return -ENOMEM;
213
214 codec = &ad1836->codec;
215 codec->control_data = spi;
216 codec->dev = &spi->dev;
217
218 dev_set_drvdata(&spi->dev, ad1836);
219
220 return ad1836_register(ad1836);
221}
222
223static int __devexit ad1836_spi_remove(struct spi_device *spi)
224{
225 struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev);
226
227 ad1836_unregister(ad1836);
228 return 0;
229}
230
231static struct spi_driver ad1836_spi_driver = {
232 .driver = {
233 .name = "ad1836",
234 .owner = THIS_MODULE,
235 },
236 .probe = ad1836_spi_probe,
237 .remove = __devexit_p(ad1836_spi_remove),
238};
239
240static struct snd_soc_dai_ops ad1836_dai_ops = { 193static struct snd_soc_dai_ops ad1836_dai_ops = {
241 .hw_params = ad1836_hw_params, 194 .hw_params = ad1836_hw_params,
242 .set_fmt = ad1836_set_dai_fmt, 195 .set_fmt = ad1836_set_dai_fmt,
243}; 196};
244 197
245/* codec DAI instance */ 198/* codec DAI instance */
246struct snd_soc_dai ad1836_dai = { 199static struct snd_soc_dai_driver ad1836_dai = {
247 .name = "AD1836", 200 .name = "ad1836-hifi",
248 .playback = { 201 .playback = {
249 .stream_name = "Playback", 202 .stream_name = "Playback",
250 .channels_min = 2, 203 .channels_min = 2,
@@ -263,35 +216,13 @@ struct snd_soc_dai ad1836_dai = {
263 }, 216 },
264 .ops = &ad1836_dai_ops, 217 .ops = &ad1836_dai_ops,
265}; 218};
266EXPORT_SYMBOL_GPL(ad1836_dai);
267 219
268static int ad1836_register(struct ad1836_priv *ad1836) 220static int ad1836_probe(struct snd_soc_codec *codec)
269{ 221{
270 int ret; 222 struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec);
271 struct snd_soc_codec *codec = &ad1836->codec; 223 int ret = 0;
272
273 if (ad1836_codec) {
274 dev_err(codec->dev, "Another ad1836 is registered\n");
275 kfree(ad1836);
276 return -EINVAL;
277 }
278
279 mutex_init(&codec->mutex);
280 INIT_LIST_HEAD(&codec->dapm_widgets);
281 INIT_LIST_HEAD(&codec->dapm_paths);
282 snd_soc_codec_set_drvdata(codec, ad1836);
283 codec->reg_cache = ad1836->reg_cache;
284 codec->reg_cache_size = AD1836_NUM_REGS;
285 codec->name = "AD1836";
286 codec->owner = THIS_MODULE;
287 codec->dai = &ad1836_dai;
288 codec->num_dai = 1;
289 INIT_LIST_HEAD(&codec->dapm_widgets);
290 INIT_LIST_HEAD(&codec->dapm_paths);
291
292 ad1836_dai.dev = codec->dev;
293 ad1836_codec = codec;
294 224
225 codec->control_data = ad1836->control_data;
295 ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); 226 ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI);
296 if (ret < 0) { 227 if (ret < 0) {
297 dev_err(codec->dev, "failed to set cache I/O: %d\n", 228 dev_err(codec->dev, "failed to set cache I/O: %d\n",
@@ -319,81 +250,69 @@ static int ad1836_register(struct ad1836_priv *ad1836)
319 snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); 250 snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF);
320 snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); 251 snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF);
321 252
322 ret = snd_soc_register_codec(codec);
323 if (ret != 0) {
324 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
325 kfree(ad1836);
326 return ret;
327 }
328
329 ret = snd_soc_register_dai(&ad1836_dai);
330 if (ret != 0) {
331 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
332 snd_soc_unregister_codec(codec);
333 kfree(ad1836);
334 return ret;
335 }
336
337 return 0;
338}
339
340static void ad1836_unregister(struct ad1836_priv *ad1836)
341{
342 snd_soc_unregister_dai(&ad1836_dai);
343 snd_soc_unregister_codec(&ad1836->codec);
344 kfree(ad1836);
345 ad1836_codec = NULL;
346}
347
348static int ad1836_probe(struct platform_device *pdev)
349{
350 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
351 struct snd_soc_codec *codec;
352 int ret = 0;
353
354 if (ad1836_codec == NULL) {
355 dev_err(&pdev->dev, "Codec device not registered\n");
356 return -ENODEV;
357 }
358
359 socdev->card->codec = ad1836_codec;
360 codec = ad1836_codec;
361
362 /* register pcms */
363 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
364 if (ret < 0) {
365 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
366 goto pcm_err;
367 }
368
369 snd_soc_add_controls(codec, ad1836_snd_controls, 253 snd_soc_add_controls(codec, ad1836_snd_controls,
370 ARRAY_SIZE(ad1836_snd_controls)); 254 ARRAY_SIZE(ad1836_snd_controls));
371 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, 255 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
372 ARRAY_SIZE(ad1836_dapm_widgets)); 256 ARRAY_SIZE(ad1836_dapm_widgets));
373 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 257 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
374 258
375pcm_err:
376 return ret; 259 return ret;
377} 260}
378 261
379/* power down chip */ 262/* power down chip */
380static int ad1836_remove(struct platform_device *pdev) 263static int ad1836_remove(struct snd_soc_codec *codec)
381{ 264{
382 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 265 /* reset clock control mode */
383 266 u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2);
384 snd_soc_free_pcms(socdev); 267 adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK;
385 snd_soc_dapm_free(socdev);
386 268
387 return 0; 269 return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2);
388} 270}
389 271
390struct snd_soc_codec_device soc_codec_dev_ad1836 = { 272static struct snd_soc_codec_driver soc_codec_dev_ad1836 = {
391 .probe = ad1836_probe, 273 .probe = ad1836_probe,
392 .remove = ad1836_remove, 274 .remove = ad1836_remove,
393 .suspend = ad1836_soc_suspend, 275 .suspend = ad1836_soc_suspend,
394 .resume = ad1836_soc_resume, 276 .resume = ad1836_soc_resume,
277 .reg_cache_size = AD1836_NUM_REGS,
278 .reg_word_size = sizeof(u16),
279};
280
281static int __devinit ad1836_spi_probe(struct spi_device *spi)
282{
283 struct ad1836_priv *ad1836;
284 int ret;
285
286 ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
287 if (ad1836 == NULL)
288 return -ENOMEM;
289
290 spi_set_drvdata(spi, ad1836);
291 ad1836->control_data = spi;
292 ad1836->control_type = SND_SOC_SPI;
293
294 ret = snd_soc_register_codec(&spi->dev,
295 &soc_codec_dev_ad1836, &ad1836_dai, 1);
296 if (ret < 0)
297 kfree(ad1836);
298 return ret;
299}
300
301static int __devexit ad1836_spi_remove(struct spi_device *spi)
302{
303 snd_soc_unregister_codec(&spi->dev);
304 kfree(spi_get_drvdata(spi));
305 return 0;
306}
307
308static struct spi_driver ad1836_spi_driver = {
309 .driver = {
310 .name = "ad1836-codec",
311 .owner = THIS_MODULE,
312 },
313 .probe = ad1836_spi_probe,
314 .remove = __devexit_p(ad1836_spi_remove),
395}; 315};
396EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836);
397 316
398static int __init ad1836_init(void) 317static int __init ad1836_init(void)
399{ 318{
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
index e9d90d3951c5..845596717fdf 100644
--- a/sound/soc/codecs/ad1836.h
+++ b/sound/soc/codecs/ad1836.h
@@ -60,6 +60,4 @@
60 60
61#define AD1836_NUM_REGS 16 61#define AD1836_NUM_REGS 16
62 62
63extern struct snd_soc_dai ad1836_dai;
64extern struct snd_soc_codec_device soc_codec_dev_ad1836;
65#endif 63#endif
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index 1def75e4862f..fa2834c91b9f 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -24,9 +24,10 @@
24 24
25/* codec private data */ 25/* codec private data */
26struct ad193x_priv { 26struct ad193x_priv {
27 unsigned int sysclk;
28 struct snd_soc_codec codec;
29 u8 reg_cache[AD193X_NUM_REGS]; 27 u8 reg_cache[AD193X_NUM_REGS];
28 enum snd_soc_control_type bus_type;
29 void *control_data;
30 int sysclk;
30}; 31};
31 32
32/* ad193x register cache & default register settings */ 33/* ad193x register cache & default register settings */
@@ -34,9 +35,6 @@ static const u8 ad193x_reg[AD193X_NUM_REGS] = {
34 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 35 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
35}; 36};
36 37
37static struct snd_soc_codec *ad193x_codec;
38struct snd_soc_codec_device soc_codec_dev_ad193x;
39
40/* 38/*
41 * AD193X volume/mute/de-emphasis etc. controls 39 * AD193X volume/mute/de-emphasis etc. controls
42 */ 40 */
@@ -275,8 +273,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
275 int word_len = 0, reg = 0, master_rate = 0; 273 int word_len = 0, reg = 0, master_rate = 0;
276 274
277 struct snd_soc_pcm_runtime *rtd = substream->private_data; 275 struct snd_soc_pcm_runtime *rtd = substream->private_data;
278 struct snd_soc_device *socdev = rtd->socdev; 276 struct snd_soc_codec *codec = rtd->codec;
279 struct snd_soc_codec *codec = socdev->card->codec;
280 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec); 277 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
281 278
282 /* bit size */ 279 /* bit size */
@@ -323,100 +320,6 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
323 return 0; 320 return 0;
324} 321}
325 322
326static int ad193x_bus_probe(struct device *dev, void *ctrl_data, int bus_type)
327{
328 struct snd_soc_codec *codec;
329 struct ad193x_priv *ad193x;
330 int ret;
331
332 if (ad193x_codec) {
333 dev_err(dev, "Another ad193x is registered\n");
334 return -EINVAL;
335 }
336
337 ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
338 if (ad193x == NULL)
339 return -ENOMEM;
340
341 dev_set_drvdata(dev, ad193x);
342
343 codec = &ad193x->codec;
344 mutex_init(&codec->mutex);
345 codec->control_data = ctrl_data;
346 codec->dev = dev;
347 snd_soc_codec_set_drvdata(codec, ad193x);
348 codec->reg_cache = ad193x->reg_cache;
349 codec->reg_cache_size = AD193X_NUM_REGS;
350 codec->name = "AD193X";
351 codec->owner = THIS_MODULE;
352 codec->dai = &ad193x_dai;
353 codec->num_dai = 1;
354 INIT_LIST_HEAD(&codec->dapm_widgets);
355 INIT_LIST_HEAD(&codec->dapm_paths);
356
357 ad193x_dai.dev = codec->dev;
358 ad193x_codec = codec;
359
360 memcpy(codec->reg_cache, ad193x_reg, AD193X_NUM_REGS);
361
362 if (bus_type == SND_SOC_I2C)
363 ret = snd_soc_codec_set_cache_io(codec, 8, 8, bus_type);
364 else
365 ret = snd_soc_codec_set_cache_io(codec, 16, 8, bus_type);
366 if (ret < 0) {
367 dev_err(codec->dev, "failed to set cache I/O: %d\n",
368 ret);
369 kfree(ad193x);
370 return ret;
371 }
372
373 /* default setting for ad193x */
374
375 /* unmute dac channels */
376 snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
377 /* de-emphasis: 48kHz, powedown dac */
378 snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
379 /* powerdown dac, dac in tdm mode */
380 snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
381 /* high-pass filter enable */
382 snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
383 /* sata delay=1, adc aux mode */
384 snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
385 /* pll input: mclki/xi */
386 snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
387 snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
388 ad193x->sysclk = 12288000;
389
390 ret = snd_soc_register_codec(codec);
391 if (ret != 0) {
392 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
393 kfree(ad193x);
394 return ret;
395 }
396
397 ret = snd_soc_register_dai(&ad193x_dai);
398 if (ret != 0) {
399 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
400 snd_soc_unregister_codec(codec);
401 kfree(ad193x);
402 return ret;
403 }
404
405 return 0;
406}
407
408static int ad193x_bus_remove(struct device *dev)
409{
410 struct ad193x_priv *ad193x = dev_get_drvdata(dev);
411
412 snd_soc_unregister_dai(&ad193x_dai);
413 snd_soc_unregister_codec(&ad193x->codec);
414 kfree(ad193x);
415 ad193x_codec = NULL;
416
417 return 0;
418}
419
420static struct snd_soc_dai_ops ad193x_dai_ops = { 323static struct snd_soc_dai_ops ad193x_dai_ops = {
421 .hw_params = ad193x_hw_params, 324 .hw_params = ad193x_hw_params,
422 .digital_mute = ad193x_mute, 325 .digital_mute = ad193x_mute,
@@ -426,8 +329,8 @@ static struct snd_soc_dai_ops ad193x_dai_ops = {
426}; 329};
427 330
428/* codec DAI instance */ 331/* codec DAI instance */
429struct snd_soc_dai ad193x_dai = { 332static struct snd_soc_dai_driver ad193x_dai = {
430 .name = "AD193X", 333 .name = "ad193x-hifi",
431 .playback = { 334 .playback = {
432 .stream_name = "Playback", 335 .stream_name = "Playback",
433 .channels_min = 2, 336 .channels_min = 2,
@@ -446,28 +349,39 @@ struct snd_soc_dai ad193x_dai = {
446 }, 349 },
447 .ops = &ad193x_dai_ops, 350 .ops = &ad193x_dai_ops,
448}; 351};
449EXPORT_SYMBOL_GPL(ad193x_dai);
450 352
451static int ad193x_probe(struct platform_device *pdev) 353static int ad193x_probe(struct snd_soc_codec *codec)
452{ 354{
453 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 355 struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
454 struct snd_soc_codec *codec; 356 int ret;
455 int ret = 0;
456 357
457 if (ad193x_codec == NULL) { 358 codec->control_data = ad193x->control_data;
458 dev_err(&pdev->dev, "Codec device not registered\n"); 359 if (ad193x->bus_type == SND_SOC_I2C)
459 return -ENODEV; 360 ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->bus_type);
361 else
362 ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->bus_type);
363 if (ret < 0) {
364 dev_err(codec->dev, "failed to set cache I/O: %d\n",
365 ret);
366 kfree(ad193x);
367 return ret;
460 } 368 }
461 369
462 socdev->card->codec = ad193x_codec; 370 /* default setting for ad193x */
463 codec = ad193x_codec;
464 371
465 /* register pcms */ 372 /* unmute dac channels */
466 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 373 snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
467 if (ret < 0) { 374 /* de-emphasis: 48kHz, powedown dac */
468 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 375 snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
469 goto pcm_err; 376 /* powerdown dac, dac in tdm mode */
470 } 377 snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
378 /* high-pass filter enable */
379 snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
380 /* sata delay=1, adc aux mode */
381 snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
382 /* pll input: mclki/xi */
383 snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
384 snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
471 385
472 snd_soc_add_controls(codec, ad193x_snd_controls, 386 snd_soc_add_controls(codec, ad193x_snd_controls,
473 ARRAY_SIZE(ad193x_snd_controls)); 387 ARRAY_SIZE(ad193x_snd_controls));
@@ -475,41 +389,47 @@ static int ad193x_probe(struct platform_device *pdev)
475 ARRAY_SIZE(ad193x_dapm_widgets)); 389 ARRAY_SIZE(ad193x_dapm_widgets));
476 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 390 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
477 391
478pcm_err:
479 return ret; 392 return ret;
480} 393}
481 394
482/* power down chip */ 395static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
483static int ad193x_remove(struct platform_device *pdev)
484{
485 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
486
487 snd_soc_free_pcms(socdev);
488 snd_soc_dapm_free(socdev);
489
490 return 0;
491}
492
493struct snd_soc_codec_device soc_codec_dev_ad193x = {
494 .probe = ad193x_probe, 396 .probe = ad193x_probe,
495 .remove = ad193x_remove, 397 .reg_cache_default = ad193x_reg,
398 .reg_cache_size = AD193X_NUM_REGS,
399 .reg_word_size = sizeof(u16),
496}; 400};
497EXPORT_SYMBOL_GPL(soc_codec_dev_ad193x);
498 401
499#if defined(CONFIG_SPI_MASTER) 402#if defined(CONFIG_SPI_MASTER)
500static int __devinit ad193x_spi_probe(struct spi_device *spi) 403static int __devinit ad193x_spi_probe(struct spi_device *spi)
501{ 404{
502 return ad193x_bus_probe(&spi->dev, spi, SND_SOC_SPI); 405 struct ad193x_priv *ad193x;
406 int ret;
407
408 ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
409 if (ad193x == NULL)
410 return -ENOMEM;
411
412 spi_set_drvdata(spi, ad193x);
413 ad193x->control_data = spi;
414 ad193x->bus_type = SND_SOC_SPI;
415
416 ret = snd_soc_register_codec(&spi->dev,
417 &soc_codec_dev_ad193x, &ad193x_dai, 1);
418 if (ret < 0)
419 kfree(ad193x);
420 return ret;
503} 421}
504 422
505static int __devexit ad193x_spi_remove(struct spi_device *spi) 423static int __devexit ad193x_spi_remove(struct spi_device *spi)
506{ 424{
507 return ad193x_bus_remove(&spi->dev); 425 snd_soc_unregister_codec(&spi->dev);
426 kfree(spi_get_drvdata(spi));
427 return 0;
508} 428}
509 429
510static struct spi_driver ad193x_spi_driver = { 430static struct spi_driver ad193x_spi_driver = {
511 .driver = { 431 .driver = {
512 .name = "ad193x", 432 .name = "ad193x-codec",
513 .owner = THIS_MODULE, 433 .owner = THIS_MODULE,
514 }, 434 },
515 .probe = ad193x_spi_probe, 435 .probe = ad193x_spi_probe,
@@ -528,17 +448,34 @@ MODULE_DEVICE_TABLE(i2c, ad193x_id);
528static int __devinit ad193x_i2c_probe(struct i2c_client *client, 448static int __devinit ad193x_i2c_probe(struct i2c_client *client,
529 const struct i2c_device_id *id) 449 const struct i2c_device_id *id)
530{ 450{
531 return ad193x_bus_probe(&client->dev, client, SND_SOC_I2C); 451 struct ad193x_priv *ad193x;
452 int ret;
453
454 ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
455 if (ad193x == NULL)
456 return -ENOMEM;
457
458 i2c_set_clientdata(client, ad193x);
459 ad193x->control_data = client;
460 ad193x->bus_type = SND_SOC_I2C;
461
462 ret = snd_soc_register_codec(&client->dev,
463 &soc_codec_dev_ad193x, &ad193x_dai, 1);
464 if (ret < 0)
465 kfree(ad193x);
466 return ret;
532} 467}
533 468
534static int __devexit ad193x_i2c_remove(struct i2c_client *client) 469static int __devexit ad193x_i2c_remove(struct i2c_client *client)
535{ 470{
536 return ad193x_bus_remove(&client->dev); 471 snd_soc_unregister_codec(&client->dev);
472 kfree(i2c_get_clientdata(client));
473 return 0;
537} 474}
538 475
539static struct i2c_driver ad193x_i2c_driver = { 476static struct i2c_driver ad193x_i2c_driver = {
540 .driver = { 477 .driver = {
541 .name = "ad193x", 478 .name = "ad193x-codec",
542 }, 479 },
543 .probe = ad193x_i2c_probe, 480 .probe = ad193x_i2c_probe,
544 .remove = __devexit_p(ad193x_i2c_remove), 481 .remove = __devexit_p(ad193x_i2c_remove),
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index 654ba64ae04c..9747b5497877 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -80,7 +80,4 @@
80 80
81#define AD193X_NUM_REGS 17 81#define AD193X_NUM_REGS 17
82 82
83extern struct snd_soc_dai ad193x_dai;
84extern struct snd_soc_codec_device soc_codec_dev_ad193x;
85
86#endif 83#endif
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 70cfaec3be2c..410ccd5d41cd 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -33,11 +33,6 @@
33 33
34#include "ad1980.h" 34#include "ad1980.h"
35 35
36static unsigned int ac97_read(struct snd_soc_codec *codec,
37 unsigned int reg);
38static int ac97_write(struct snd_soc_codec *codec,
39 unsigned int reg, unsigned int val);
40
41/* 36/*
42 * AD1980 register cache 37 * AD1980 register cache
43 */ 38 */
@@ -138,8 +133,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
138 return 0; 133 return 0;
139} 134}
140 135
141struct snd_soc_dai ad1980_dai = { 136static struct snd_soc_dai_driver ad1980_dai = {
142 .name = "AC97", 137 .name = "ad1980-hifi",
143 .ac97_control = 1, 138 .ac97_control = 1,
144 .playback = { 139 .playback = {
145 .stream_name = "Playback", 140 .stream_name = "Playback",
@@ -185,53 +180,20 @@ err:
185 return -EIO; 180 return -EIO;
186} 181}
187 182
188static int ad1980_soc_probe(struct platform_device *pdev) 183static int ad1980_soc_probe(struct snd_soc_codec *codec)
189{ 184{
190 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 185 int ret;
191 struct snd_soc_codec *codec;
192 int ret = 0;
193 u16 vendor_id2; 186 u16 vendor_id2;
194 u16 ext_status; 187 u16 ext_status;
195 188
196 printk(KERN_INFO "AD1980 SoC Audio Codec\n"); 189 printk(KERN_INFO "AD1980 SoC Audio Codec\n");
197 190
198 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
199 if (socdev->card->codec == NULL)
200 return -ENOMEM;
201 codec = socdev->card->codec;
202 mutex_init(&codec->mutex);
203
204 codec->reg_cache =
205 kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL);
206 if (codec->reg_cache == NULL) {
207 ret = -ENOMEM;
208 goto cache_err;
209 }
210 memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \
211 ARRAY_SIZE(ad1980_reg));
212 codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg);
213 codec->reg_cache_step = 2;
214 codec->name = "AD1980";
215 codec->owner = THIS_MODULE;
216 codec->dai = &ad1980_dai;
217 codec->num_dai = 1;
218 codec->write = ac97_write;
219 codec->read = ac97_read;
220 INIT_LIST_HEAD(&codec->dapm_widgets);
221 INIT_LIST_HEAD(&codec->dapm_paths);
222
223 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); 191 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
224 if (ret < 0) { 192 if (ret < 0) {
225 printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); 193 printk(KERN_ERR "ad1980: failed to register AC97 codec\n");
226 goto codec_err; 194 return ret;
227 } 195 }
228 196
229 /* register pcms */
230 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
231 if (ret < 0)
232 goto pcm_err;
233
234
235 ret = ad1980_reset(codec, 0); 197 ret = ad1980_reset(codec, 0);
236 if (ret < 0) { 198 if (ret < 0) {
237 printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); 199 printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
@@ -270,41 +232,60 @@ static int ad1980_soc_probe(struct platform_device *pdev)
270 return 0; 232 return 0;
271 233
272reset_err: 234reset_err:
273 snd_soc_free_pcms(socdev);
274
275pcm_err:
276 snd_soc_free_ac97_codec(codec); 235 snd_soc_free_ac97_codec(codec);
277
278codec_err:
279 kfree(codec->reg_cache);
280
281cache_err:
282 kfree(socdev->card->codec);
283 socdev->card->codec = NULL;
284 return ret; 236 return ret;
285} 237}
286 238
287static int ad1980_soc_remove(struct platform_device *pdev) 239static int ad1980_soc_remove(struct snd_soc_codec *codec)
288{ 240{
289 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
290 struct snd_soc_codec *codec = socdev->card->codec;
291
292 if (codec == NULL)
293 return 0;
294
295 snd_soc_dapm_free(socdev);
296 snd_soc_free_pcms(socdev);
297 snd_soc_free_ac97_codec(codec); 241 snd_soc_free_ac97_codec(codec);
298 kfree(codec->reg_cache);
299 kfree(codec);
300 return 0; 242 return 0;
301} 243}
302 244
303struct snd_soc_codec_device soc_codec_dev_ad1980 = { 245static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
304 .probe = ad1980_soc_probe, 246 .probe = ad1980_soc_probe,
305 .remove = ad1980_soc_remove, 247 .remove = ad1980_soc_remove,
248 .reg_cache_size = ARRAY_SIZE(ad1980_reg),
249 .reg_word_size = sizeof(u16),
250 .reg_cache_default = ad1980_reg,
251 .reg_cache_step = 2,
252 .write = ac97_write,
253 .read = ac97_read,
306}; 254};
307EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); 255
256static __devinit int ad1980_probe(struct platform_device *pdev)
257{
258 return snd_soc_register_codec(&pdev->dev,
259 &soc_codec_dev_ad1980, &ad1980_dai, 1);
260}
261
262static int __devexit ad1980_remove(struct platform_device *pdev)
263{
264 snd_soc_unregister_codec(&pdev->dev);
265 return 0;
266}
267
268static struct platform_driver ad1980_codec_driver = {
269 .driver = {
270 .name = "ad1980-codec",
271 .owner = THIS_MODULE,
272 },
273
274 .probe = ad1980_probe,
275 .remove = __devexit_p(ad1980_remove),
276};
277
278static int __init ad1980_init(void)
279{
280 return platform_driver_register(&ad1980_codec_driver);
281}
282module_init(ad1980_init);
283
284static void __exit ad1980_exit(void)
285{
286 platform_driver_unregister(&ad1980_codec_driver);
287}
288module_exit(ad1980_exit);
308 289
309MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)"); 290MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)");
310MODULE_AUTHOR("Roy Huang, Cliff Cai"); 291MODULE_AUTHOR("Roy Huang, Cliff Cai");
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h
index 538f37c90806..eb0af44ad3df 100644
--- a/sound/soc/codecs/ad1980.h
+++ b/sound/soc/codecs/ad1980.h
@@ -23,7 +23,4 @@
23#define PR5 0x2000 23#define PR5 0x2000
24#define PR6 0x4000 24#define PR6 0x4000
25 25
26extern struct snd_soc_dai ad1980_dai;
27extern struct snd_soc_codec_device soc_codec_dev_ad1980;
28
29#endif 26#endif
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index 475807bea2c2..c53955fe17b6 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -23,8 +23,8 @@
23 23
24#include "ad73311.h" 24#include "ad73311.h"
25 25
26struct snd_soc_dai ad73311_dai = { 26static struct snd_soc_dai_driver ad73311_dai = {
27 .name = "AD73311", 27 .name = "ad73311-hifi",
28 .playback = { 28 .playback = {
29 .stream_name = "Playback", 29 .stream_name = "Playback",
30 .channels_min = 1, 30 .channels_min = 1,
@@ -38,68 +38,40 @@ struct snd_soc_dai ad73311_dai = {
38 .rates = SNDRV_PCM_RATE_8000, 38 .rates = SNDRV_PCM_RATE_8000,
39 .formats = SNDRV_PCM_FMTBIT_S16_LE, }, 39 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
40}; 40};
41EXPORT_SYMBOL_GPL(ad73311_dai);
42 41
43static int ad73311_soc_probe(struct platform_device *pdev) 42static struct snd_soc_codec_driver soc_codec_dev_ad73311;
44{
45 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
46 struct snd_soc_codec *codec;
47 int ret = 0;
48
49 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
50 if (codec == NULL)
51 return -ENOMEM;
52 mutex_init(&codec->mutex);
53 codec->name = "AD73311";
54 codec->owner = THIS_MODULE;
55 codec->dai = &ad73311_dai;
56 codec->num_dai = 1;
57 socdev->card->codec = codec;
58 INIT_LIST_HEAD(&codec->dapm_widgets);
59 INIT_LIST_HEAD(&codec->dapm_paths);
60
61 /* register pcms */
62 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
63 if (ret < 0) {
64 printk(KERN_ERR "ad73311: failed to create pcms\n");
65 goto pcm_err;
66 }
67
68 return ret;
69 43
70pcm_err: 44static int ad73311_probe(struct platform_device *pdev)
71 kfree(socdev->card->codec); 45{
72 socdev->card->codec = NULL; 46 return snd_soc_register_codec(&pdev->dev,
73 return ret; 47 &soc_codec_dev_ad73311, &ad73311_dai, 1);
74} 48}
75 49
76static int ad73311_soc_remove(struct platform_device *pdev) 50static int ad73311_remove(struct platform_device *pdev)
77{ 51{
78 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 52 snd_soc_unregister_codec(&pdev->dev);
79 struct snd_soc_codec *codec = socdev->card->codec;
80
81 if (codec == NULL)
82 return 0;
83 snd_soc_free_pcms(socdev);
84 kfree(codec);
85 return 0; 53 return 0;
86} 54}
87 55
88struct snd_soc_codec_device soc_codec_dev_ad73311 = { 56static struct platform_driver ad73311_codec_driver = {
89 .probe = ad73311_soc_probe, 57 .driver = {
90 .remove = ad73311_soc_remove, 58 .name = "ad73311-codec",
59 .owner = THIS_MODULE,
60 },
61
62 .probe = ad73311_probe,
63 .remove = __devexit_p(ad73311_remove),
91}; 64};
92EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
93 65
94static int __init ad73311_init(void) 66static int __init ad73311_init(void)
95{ 67{
96 return snd_soc_register_dai(&ad73311_dai); 68 return platform_driver_register(&ad73311_codec_driver);
97} 69}
98module_init(ad73311_init); 70module_init(ad73311_init);
99 71
100static void __exit ad73311_exit(void) 72static void __exit ad73311_exit(void)
101{ 73{
102 snd_soc_unregister_dai(&ad73311_dai); 74 platform_driver_unregister(&ad73311_codec_driver);
103} 75}
104module_exit(ad73311_exit); 76module_exit(ad73311_exit);
105 77
diff --git a/sound/soc/codecs/ad73311.h b/sound/soc/codecs/ad73311.h
index 569573d2d4d7..4b353eefc0bf 100644
--- a/sound/soc/codecs/ad73311.h
+++ b/sound/soc/codecs/ad73311.h
@@ -85,6 +85,4 @@
85#define REGF_INV (1 << 6) 85#define REGF_INV (1 << 6)
86#define REGF_ALB (1 << 7) 86#define REGF_ALB (1 << 7)
87 87
88extern struct snd_soc_dai ad73311_dai;
89extern struct snd_soc_codec_device soc_codec_dev_ad73311;
90#endif 88#endif
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index f8e75edb27b7..8402854ec15e 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -19,16 +19,12 @@
19#include <sound/initval.h> 19#include <sound/initval.h>
20#include <sound/soc.h> 20#include <sound/soc.h>
21 21
22#include "ads117x.h"
23
24#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000) 22#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
25
26#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) 23#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
27 24
28struct snd_soc_dai ads117x_dai = { 25static struct snd_soc_dai_driver ads117x_dai = {
29/* ADC */ 26/* ADC */
30 .name = "ADS117X ADC", 27 .name = "ads117x-hifi",
31 .id = 1,
32 .capture = { 28 .capture = {
33 .stream_name = "Capture", 29 .stream_name = "Capture",
34 .channels_min = 1, 30 .channels_min = 1,
@@ -36,75 +32,29 @@ struct snd_soc_dai ads117x_dai = {
36 .rates = ADS117X_RATES, 32 .rates = ADS117X_RATES,
37 .formats = ADS117X_FORMATS,}, 33 .formats = ADS117X_FORMATS,},
38}; 34};
39EXPORT_SYMBOL_GPL(ads117x_dai);
40
41static int ads117x_probe(struct platform_device *pdev)
42{
43 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
44 struct snd_soc_codec *codec;
45 int ret;
46
47 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
48 if (codec == NULL)
49 return -ENOMEM;
50 35
51 socdev->card->codec = codec; 36static struct snd_soc_codec_driver soc_codec_dev_ads117x;
52 mutex_init(&codec->mutex);
53 INIT_LIST_HEAD(&codec->dapm_widgets);
54 INIT_LIST_HEAD(&codec->dapm_paths);
55 codec->name = "ADS117X";
56 codec->owner = THIS_MODULE;
57 codec->dai = &ads117x_dai;
58 codec->num_dai = 1;
59
60 /* register pcms */
61 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
62 if (ret < 0) {
63 printk(KERN_ERR "ads117x: failed to create pcms\n");
64 kfree(codec);
65 return ret;
66 }
67
68 return 0;
69}
70
71static int ads117x_remove(struct platform_device *pdev)
72{
73 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
74 struct snd_soc_codec *codec = socdev->card->codec;
75
76 snd_soc_free_pcms(socdev);
77 kfree(codec);
78
79 return 0;
80}
81
82struct snd_soc_codec_device soc_codec_dev_ads117x = {
83 .probe = ads117x_probe,
84 .remove = ads117x_remove,
85};
86EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x);
87 37
88static __devinit int ads117x_platform_probe(struct platform_device *pdev) 38static __devinit int ads117x_probe(struct platform_device *pdev)
89{ 39{
90 ads117x_dai.dev = &pdev->dev; 40 return snd_soc_register_codec(&pdev->dev,
91 return snd_soc_register_dai(&ads117x_dai); 41 &soc_codec_dev_ads117x, &ads117x_dai, 1);
92} 42}
93 43
94static int __devexit ads117x_platform_remove(struct platform_device *pdev) 44static int __devexit ads117x_remove(struct platform_device *pdev)
95{ 45{
96 snd_soc_unregister_dai(&ads117x_dai); 46 snd_soc_unregister_codec(&pdev->dev);
97 return 0; 47 return 0;
98} 48}
99 49
100static struct platform_driver ads117x_codec_driver = { 50static struct platform_driver ads117x_codec_driver = {
101 .driver = { 51 .driver = {
102 .name = "ads117x", 52 .name = "ads117x-codec",
103 .owner = THIS_MODULE, 53 .owner = THIS_MODULE,
104 }, 54 },
105 55
106 .probe = ads117x_platform_probe, 56 .probe = ads117x_probe,
107 .remove = __devexit_p(ads117x_platform_remove), 57 .remove = __devexit_p(ads117x_remove),
108}; 58};
109 59
110static int __init ads117x_init(void) 60static int __init ads117x_init(void)
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h
index dbcf50ec9bd1..3ce028614002 100644
--- a/sound/soc/codecs/ads117x.h
+++ b/sound/soc/codecs/ads117x.h
@@ -9,5 +9,5 @@
9 * Free Software Foundation; either version 2 of the License, or (at your 9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. 10 * option) any later version.
11 */ 11 */
12extern struct snd_soc_dai ads117x_dai; 12extern struct snd_soc_dai_driver ads117x_dai;
13extern struct snd_soc_codec_device soc_codec_dev_ads117x; 13extern struct snd_soc_codec_driver soc_codec_dev_ads117x;
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 192aebda3029..c27f8f59dc66 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -17,8 +17,6 @@
17#include <linux/spi/spi.h> 17#include <linux/spi/spi.h>
18#include <sound/asoundef.h> 18#include <sound/asoundef.h>
19 19
20#include "ak4104.h"
21
22/* AK4104 registers addresses */ 20/* AK4104 registers addresses */
23#define AK4104_REG_CONTROL1 0x00 21#define AK4104_REG_CONTROL1 0x00
24#define AK4104_REG_RESERVED 0x01 22#define AK4104_REG_RESERVED 0x01
@@ -45,11 +43,11 @@
45#define AK4104_TX_TXE (1 << 0) 43#define AK4104_TX_TXE (1 << 0)
46#define AK4104_TX_V (1 << 1) 44#define AK4104_TX_V (1 << 1)
47 45
48#define DRV_NAME "ak4104" 46#define DRV_NAME "ak4104-codec"
49 47
50struct ak4104_private { 48struct ak4104_private {
51 struct snd_soc_codec codec; 49 enum snd_soc_control_type control_type;
52 u8 reg_cache[AK4104_NUM_REGS]; 50 void *control_data;
53}; 51};
54 52
55static int ak4104_fill_cache(struct snd_soc_codec *codec) 53static int ak4104_fill_cache(struct snd_soc_codec *codec)
@@ -58,7 +56,7 @@ static int ak4104_fill_cache(struct snd_soc_codec *codec)
58 u8 *reg_cache = codec->reg_cache; 56 u8 *reg_cache = codec->reg_cache;
59 struct spi_device *spi = codec->control_data; 57 struct spi_device *spi = codec->control_data;
60 58
61 for (i = 0; i < codec->reg_cache_size; i++) { 59 for (i = 0; i < codec->driver->reg_cache_size; i++) {
62 int ret = spi_w8r8(spi, i | AK4104_READ); 60 int ret = spi_w8r8(spi, i | AK4104_READ);
63 if (ret < 0) { 61 if (ret < 0) {
64 dev_err(&spi->dev, "SPI write failure\n"); 62 dev_err(&spi->dev, "SPI write failure\n");
@@ -76,7 +74,7 @@ static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
76{ 74{
77 u8 *reg_cache = codec->reg_cache; 75 u8 *reg_cache = codec->reg_cache;
78 76
79 if (reg >= codec->reg_cache_size) 77 if (reg >= codec->driver->reg_cache_size)
80 return -EINVAL; 78 return -EINVAL;
81 79
82 return reg_cache[reg]; 80 return reg_cache[reg];
@@ -88,7 +86,7 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
88 u8 *cache = codec->reg_cache; 86 u8 *cache = codec->reg_cache;
89 struct spi_device *spi = codec->control_data; 87 struct spi_device *spi = codec->control_data;
90 88
91 if (reg >= codec->reg_cache_size) 89 if (reg >= codec->driver->reg_cache_size)
92 return -EINVAL; 90 return -EINVAL;
93 91
94 /* only write to the hardware if value has changed */ 92 /* only write to the hardware if value has changed */
@@ -145,8 +143,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
145 struct snd_soc_dai *dai) 143 struct snd_soc_dai *dai)
146{ 144{
147 struct snd_soc_pcm_runtime *rtd = substream->private_data; 145 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct snd_soc_device *socdev = rtd->socdev; 146 struct snd_soc_codec *codec = rtd->codec;
149 struct snd_soc_codec *codec = socdev->card->codec;
150 int val = 0; 147 int val = 0;
151 148
152 /* set the IEC958 bits: consumer mode, no copyright bit */ 149 /* set the IEC958 bits: consumer mode, no copyright bit */
@@ -178,8 +175,8 @@ static struct snd_soc_dai_ops ak4101_dai_ops = {
178 .set_fmt = ak4104_set_dai_fmt, 175 .set_fmt = ak4104_set_dai_fmt,
179}; 176};
180 177
181struct snd_soc_dai ak4104_dai = { 178static struct snd_soc_dai_driver ak4104_dai = {
182 .name = DRV_NAME, 179 .name = "ak4104-hifi",
183 .playback = { 180 .playback = {
184 .stream_name = "Playback", 181 .stream_name = "Playback",
185 .channels_min = 2, 182 .channels_min = 2,
@@ -192,45 +189,17 @@ struct snd_soc_dai ak4104_dai = {
192 .ops = &ak4101_dai_ops, 189 .ops = &ak4101_dai_ops,
193}; 190};
194 191
195static struct snd_soc_codec *ak4104_codec; 192static int ak4104_probe(struct snd_soc_codec *codec)
196
197static int ak4104_spi_probe(struct spi_device *spi)
198{ 193{
199 struct snd_soc_codec *codec; 194 struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
200 struct ak4104_private *ak4104;
201 int ret, val; 195 int ret, val;
202 196
203 spi->bits_per_word = 8; 197 codec->control_data = ak4104->control_data;
204 spi->mode = SPI_MODE_0;
205 ret = spi_setup(spi);
206 if (ret < 0)
207 return ret;
208
209 ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
210 if (!ak4104) {
211 dev_err(&spi->dev, "could not allocate codec\n");
212 return -ENOMEM;
213 }
214
215 codec = &ak4104->codec;
216 mutex_init(&codec->mutex);
217 INIT_LIST_HEAD(&codec->dapm_widgets);
218 INIT_LIST_HEAD(&codec->dapm_paths);
219
220 codec->dev = &spi->dev;
221 codec->name = DRV_NAME;
222 codec->owner = THIS_MODULE;
223 codec->dai = &ak4104_dai;
224 codec->num_dai = 1;
225 snd_soc_codec_set_drvdata(codec, ak4104);
226 codec->control_data = spi;
227 codec->reg_cache = ak4104->reg_cache;
228 codec->reg_cache_size = AK4104_NUM_REGS;
229 198
230 /* read all regs and fill the cache */ 199 /* read all regs and fill the cache */
231 ret = ak4104_fill_cache(codec); 200 ret = ak4104_fill_cache(codec);
232 if (ret < 0) { 201 if (ret < 0) {
233 dev_err(&spi->dev, "failed to fill register cache\n"); 202 dev_err(codec->dev, "failed to fill register cache\n");
234 return ret; 203 return ret;
235 } 204 }
236 205
@@ -238,93 +207,81 @@ static int ak4104_spi_probe(struct spi_device *spi)
238 * should contain 0x5b. Not a good way to verify the presence of 207 * should contain 0x5b. Not a good way to verify the presence of
239 * the device, but there is no hardware ID register. */ 208 * the device, but there is no hardware ID register. */
240 if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) != 209 if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
241 AK4104_RESERVED_VAL) { 210 AK4104_RESERVED_VAL)
242 ret = -ENODEV; 211 return -ENODEV;
243 goto error_free_codec;
244 }
245 212
246 /* set power-up and non-reset bits */ 213 /* set power-up and non-reset bits */
247 val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1); 214 val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
248 val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN; 215 val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN;
249 ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val); 216 ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
250 if (ret < 0) 217 if (ret < 0)
251 goto error_free_codec; 218 return ret;
252 219
253 /* enable transmitter */ 220 /* enable transmitter */
254 val = ak4104_read_reg_cache(codec, AK4104_REG_TX); 221 val = ak4104_read_reg_cache(codec, AK4104_REG_TX);
255 val |= AK4104_TX_TXE; 222 val |= AK4104_TX_TXE;
256 ret = ak4104_spi_write(codec, AK4104_REG_TX, val); 223 ret = ak4104_spi_write(codec, AK4104_REG_TX, val);
257 if (ret < 0) 224 if (ret < 0)
258 goto error_free_codec; 225 return ret;
259
260 ak4104_codec = codec;
261 ret = snd_soc_register_dai(&ak4104_dai);
262 if (ret < 0) {
263 dev_err(&spi->dev, "failed to register DAI\n");
264 goto error_free_codec;
265 }
266 226
267 spi_set_drvdata(spi, ak4104); 227 dev_info(codec->dev, "SPI device initialized\n");
268 dev_info(&spi->dev, "SPI device initialized\n");
269 return 0; 228 return 0;
270
271error_free_codec:
272 kfree(ak4104);
273 ak4104_dai.dev = NULL;
274 return ret;
275} 229}
276 230
277static int __devexit ak4104_spi_remove(struct spi_device *spi) 231static int ak4104_remove(struct snd_soc_codec *codec)
278{ 232{
279 int ret, val; 233 int val, ret;
280 struct ak4104_private *ak4104 = spi_get_drvdata(spi);
281 234
282 val = ak4104_read_reg_cache(&ak4104->codec, AK4104_REG_CONTROL1); 235 val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
283 if (val < 0) 236 if (val < 0)
284 return val; 237 return val;
285 238
286 /* clear power-up and non-reset bits */ 239 /* clear power-up and non-reset bits */
287 val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN); 240 val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
288 ret = ak4104_spi_write(&ak4104->codec, AK4104_REG_CONTROL1, val); 241 ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
289 if (ret < 0)
290 return ret;
291 242
292 ak4104_codec = NULL; 243 return ret;
293 kfree(ak4104);
294 return 0;
295} 244}
296 245
297static int ak4104_probe(struct platform_device *pdev) 246static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
247 .probe = ak4104_probe,
248 .remove = ak4104_remove,
249 .reg_cache_size = AK4104_NUM_REGS,
250 .reg_word_size = sizeof(u16),
251};
252
253static int ak4104_spi_probe(struct spi_device *spi)
298{ 254{
299 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 255 struct ak4104_private *ak4104;
300 struct snd_soc_codec *codec = ak4104_codec;
301 int ret; 256 int ret;
302 257
303 /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */ 258 spi->bits_per_word = 8;
304 socdev->card->codec = codec; 259 spi->mode = SPI_MODE_0;
305 260 ret = spi_setup(spi);
306 /* Register PCMs */ 261 if (ret < 0)
307 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
308 if (ret < 0) {
309 dev_err(codec->dev, "failed to create pcms\n");
310 return ret; 262 return ret;
311 }
312 263
313 return 0; 264 ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
265 if (ak4104 == NULL)
266 return -ENOMEM;
267
268 ak4104->control_data = spi;
269 ak4104->control_type = SND_SOC_SPI;
270 spi_set_drvdata(spi, ak4104);
271
272 ret = snd_soc_register_codec(&spi->dev,
273 &soc_codec_device_ak4104, &ak4104_dai, 1);
274 if (ret < 0)
275 kfree(ak4104);
276 return ret;
314} 277}
315 278
316static int ak4104_remove(struct platform_device *pdev) 279static int __devexit ak4104_spi_remove(struct spi_device *spi)
317{ 280{
318 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 281 snd_soc_unregister_codec(&spi->dev);
319 snd_soc_free_pcms(socdev); 282 kfree(spi_get_drvdata(spi));
320 return 0; 283 return 0;
321}; 284}
322
323struct snd_soc_codec_device soc_codec_device_ak4104 = {
324 .probe = ak4104_probe,
325 .remove = ak4104_remove
326};
327EXPORT_SYMBOL_GPL(soc_codec_device_ak4104);
328 285
329static struct spi_driver ak4104_spi_driver = { 286static struct spi_driver ak4104_spi_driver = {
330 .driver = { 287 .driver = {
diff --git a/sound/soc/codecs/ak4104.h b/sound/soc/codecs/ak4104.h
deleted file mode 100644
index eb88fe7e4def..000000000000
--- a/sound/soc/codecs/ak4104.h
+++ /dev/null
@@ -1,7 +0,0 @@
1#ifndef _AK4104_H
2#define _AK4104_H
3
4extern struct snd_soc_dai ak4104_dai;
5extern struct snd_soc_codec_device soc_codec_device_ak4104;
6
7#endif
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index d4253675b2d3..cd88c8f32a38 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -31,11 +31,11 @@
31 31
32#define AK4535_VERSION "0.3" 32#define AK4535_VERSION "0.3"
33 33
34struct snd_soc_codec_device soc_codec_dev_ak4535;
35
36/* codec private data */ 34/* codec private data */
37struct ak4535_priv { 35struct ak4535_priv {
38 unsigned int sysclk; 36 unsigned int sysclk;
37 enum snd_soc_control_type control_type;
38 void *control_data;
39}; 39};
40 40
41/* 41/*
@@ -313,8 +313,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
313 struct snd_soc_dai *dai) 313 struct snd_soc_dai *dai)
314{ 314{
315 struct snd_soc_pcm_runtime *rtd = substream->private_data; 315 struct snd_soc_pcm_runtime *rtd = substream->private_data;
316 struct snd_soc_device *socdev = rtd->socdev; 316 struct snd_soc_codec *codec = rtd->codec;
317 struct snd_soc_codec *codec = socdev->card->codec;
318 struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec); 317 struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
319 u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5); 318 u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
320 int rate = params_rate(params), fs = 256; 319 int rate = params_rate(params), fs = 256;
@@ -378,14 +377,16 @@ static int ak4535_mute(struct snd_soc_dai *dai, int mute)
378static int ak4535_set_bias_level(struct snd_soc_codec *codec, 377static int ak4535_set_bias_level(struct snd_soc_codec *codec,
379 enum snd_soc_bias_level level) 378 enum snd_soc_bias_level level)
380{ 379{
381 u16 i; 380 u16 i, mute_reg;
382 381
383 switch (level) { 382 switch (level) {
384 case SND_SOC_BIAS_ON: 383 case SND_SOC_BIAS_ON:
385 ak4535_mute(codec->dai, 0); 384 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
385 ak4535_write(codec, AK4535_DAC, mute_reg);
386 break; 386 break;
387 case SND_SOC_BIAS_PREPARE: 387 case SND_SOC_BIAS_PREPARE:
388 ak4535_mute(codec->dai, 1); 388 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC) & 0xffdf;
389 ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
389 break; 390 break;
390 case SND_SOC_BIAS_STANDBY: 391 case SND_SOC_BIAS_STANDBY:
391 i = ak4535_read_reg_cache(codec, AK4535_PM1); 392 i = ak4535_read_reg_cache(codec, AK4535_PM1);
@@ -413,8 +414,8 @@ static struct snd_soc_dai_ops ak4535_dai_ops = {
413 .set_sysclk = ak4535_set_dai_sysclk, 414 .set_sysclk = ak4535_set_dai_sysclk,
414}; 415};
415 416
416struct snd_soc_dai ak4535_dai = { 417static struct snd_soc_dai_driver ak4535_dai = {
417 .name = "AK4535", 418 .name = "ak4535-hifi",
418 .playback = { 419 .playback = {
419 .stream_name = "Playback", 420 .stream_name = "Playback",
420 .channels_min = 1, 421 .channels_min = 1,
@@ -429,54 +430,27 @@ struct snd_soc_dai ak4535_dai = {
429 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 430 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
430 .ops = &ak4535_dai_ops, 431 .ops = &ak4535_dai_ops,
431}; 432};
432EXPORT_SYMBOL_GPL(ak4535_dai);
433 433
434static int ak4535_suspend(struct platform_device *pdev, pm_message_t state) 434static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
435{ 435{
436 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
437 struct snd_soc_codec *codec = socdev->card->codec;
438
439 ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF); 436 ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
440 return 0; 437 return 0;
441} 438}
442 439
443static int ak4535_resume(struct platform_device *pdev) 440static int ak4535_resume(struct snd_soc_codec *codec)
444{ 441{
445 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
446 struct snd_soc_codec *codec = socdev->card->codec;
447 ak4535_sync(codec); 442 ak4535_sync(codec);
448 ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 443 ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
449 return 0; 444 return 0;
450} 445}
451 446
452/* 447static int ak4535_probe(struct snd_soc_codec *codec)
453 * initialise the AK4535 driver
454 * register the mixer and dsp interfaces with the kernel
455 */
456static int ak4535_init(struct snd_soc_device *socdev)
457{ 448{
458 struct snd_soc_codec *codec = socdev->card->codec; 449 struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
459 int ret = 0;
460 450
461 codec->name = "AK4535"; 451 printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
462 codec->owner = THIS_MODULE;
463 codec->read = ak4535_read_reg_cache;
464 codec->write = ak4535_write;
465 codec->set_bias_level = ak4535_set_bias_level;
466 codec->dai = &ak4535_dai;
467 codec->num_dai = 1;
468 codec->reg_cache_size = ARRAY_SIZE(ak4535_reg);
469 codec->reg_cache = kmemdup(ak4535_reg, sizeof(ak4535_reg), GFP_KERNEL);
470
471 if (codec->reg_cache == NULL)
472 return -ENOMEM;
473 452
474 /* register pcms */ 453 codec->control_data = ak4535->control_data;
475 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
476 if (ret < 0) {
477 printk(KERN_ERR "ak4535: failed to create pcms\n");
478 goto pcm_err;
479 }
480 454
481 /* power on device */ 455 /* power on device */
482 ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 456 ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -485,39 +459,55 @@ static int ak4535_init(struct snd_soc_device *socdev)
485 ARRAY_SIZE(ak4535_snd_controls)); 459 ARRAY_SIZE(ak4535_snd_controls));
486 ak4535_add_widgets(codec); 460 ak4535_add_widgets(codec);
487 461
488 return ret; 462 return 0;
489 463}
490pcm_err:
491 kfree(codec->reg_cache);
492 464
493 return ret; 465/* power down chip */
466static int ak4535_remove(struct snd_soc_codec *codec)
467{
468 ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
469 return 0;
494} 470}
495 471
496static struct snd_soc_device *ak4535_socdev; 472static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
473 .probe = ak4535_probe,
474 .remove = ak4535_remove,
475 .suspend = ak4535_suspend,
476 .resume = ak4535_resume,
477 .read = ak4535_read_reg_cache,
478 .write = ak4535_write,
479 .set_bias_level = ak4535_set_bias_level,
480 .reg_cache_size = ARRAY_SIZE(ak4535_reg),
481 .reg_word_size = sizeof(u8),
482 .reg_cache_default = ak4535_reg,
483};
497 484
498#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 485#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
499 486static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
500static int ak4535_i2c_probe(struct i2c_client *i2c, 487 const struct i2c_device_id *id)
501 const struct i2c_device_id *id)
502{ 488{
503 struct snd_soc_device *socdev = ak4535_socdev; 489 struct ak4535_priv *ak4535;
504 struct snd_soc_codec *codec = socdev->card->codec;
505 int ret; 490 int ret;
506 491
507 i2c_set_clientdata(i2c, codec); 492 ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
508 codec->control_data = i2c; 493 if (ak4535 == NULL)
494 return -ENOMEM;
509 495
510 ret = ak4535_init(socdev); 496 i2c_set_clientdata(i2c, ak4535);
511 if (ret < 0) 497 ak4535->control_data = i2c;
512 printk(KERN_ERR "failed to initialise AK4535\n"); 498 ak4535->control_type = SND_SOC_I2C;
513 499
500 ret = snd_soc_register_codec(&i2c->dev,
501 &soc_codec_dev_ak4535, &ak4535_dai, 1);
502 if (ret < 0)
503 kfree(ak4535);
514 return ret; 504 return ret;
515} 505}
516 506
517static int ak4535_i2c_remove(struct i2c_client *client) 507static __devexit int ak4535_i2c_remove(struct i2c_client *client)
518{ 508{
519 struct snd_soc_codec *codec = i2c_get_clientdata(client); 509 snd_soc_unregister_codec(&client->dev);
520 kfree(codec->reg_cache); 510 kfree(i2c_get_clientdata(client));
521 return 0; 511 return 0;
522} 512}
523 513
@@ -529,138 +519,34 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
529 519
530static struct i2c_driver ak4535_i2c_driver = { 520static struct i2c_driver ak4535_i2c_driver = {
531 .driver = { 521 .driver = {
532 .name = "AK4535 I2C Codec", 522 .name = "ak4535-codec",
533 .owner = THIS_MODULE, 523 .owner = THIS_MODULE,
534 }, 524 },
535 .probe = ak4535_i2c_probe, 525 .probe = ak4535_i2c_probe,
536 .remove = ak4535_i2c_remove, 526 .remove = __devexit_p(ak4535_i2c_remove),
537 .id_table = ak4535_i2c_id, 527 .id_table = ak4535_i2c_id,
538}; 528};
539
540static int ak4535_add_i2c_device(struct platform_device *pdev,
541 const struct ak4535_setup_data *setup)
542{
543 struct i2c_board_info info;
544 struct i2c_adapter *adapter;
545 struct i2c_client *client;
546 int ret;
547
548 ret = i2c_add_driver(&ak4535_i2c_driver);
549 if (ret != 0) {
550 dev_err(&pdev->dev, "can't add i2c driver\n");
551 return ret;
552 }
553
554 memset(&info, 0, sizeof(struct i2c_board_info));
555 info.addr = setup->i2c_address;
556 strlcpy(info.type, "ak4535", I2C_NAME_SIZE);
557
558 adapter = i2c_get_adapter(setup->i2c_bus);
559 if (!adapter) {
560 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
561 setup->i2c_bus);
562 goto err_driver;
563 }
564
565 client = i2c_new_device(adapter, &info);
566 i2c_put_adapter(adapter);
567 if (!client) {
568 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
569 (unsigned int)info.addr);
570 goto err_driver;
571 }
572
573 return 0;
574
575err_driver:
576 i2c_del_driver(&ak4535_i2c_driver);
577 return -ENODEV;
578}
579#endif 529#endif
580 530
581static int ak4535_probe(struct platform_device *pdev) 531static int __init ak4535_modinit(void)
582{ 532{
583 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 533 int ret = 0;
584 struct ak4535_setup_data *setup;
585 struct snd_soc_codec *codec;
586 struct ak4535_priv *ak4535;
587 int ret;
588
589 printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
590
591 setup = socdev->codec_data;
592 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
593 if (codec == NULL)
594 return -ENOMEM;
595
596 ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
597 if (ak4535 == NULL) {
598 kfree(codec);
599 return -ENOMEM;
600 }
601
602 snd_soc_codec_set_drvdata(codec, ak4535);
603 socdev->card->codec = codec;
604 mutex_init(&codec->mutex);
605 INIT_LIST_HEAD(&codec->dapm_widgets);
606 INIT_LIST_HEAD(&codec->dapm_paths);
607
608 ak4535_socdev = socdev;
609 ret = -ENODEV;
610
611#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 534#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
612 if (setup->i2c_address) { 535 ret = i2c_add_driver(&ak4535_i2c_driver);
613 codec->hw_write = (hw_write_t)i2c_master_send;
614 ret = ak4535_add_i2c_device(pdev, setup);
615 }
616#endif
617
618 if (ret != 0) { 536 if (ret != 0) {
619 kfree(snd_soc_codec_get_drvdata(codec)); 537 printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
620 kfree(codec); 538 ret);
621 } 539 }
540#endif
622 return ret; 541 return ret;
623} 542}
543module_init(ak4535_modinit);
624 544
625/* power down chip */ 545static void __exit ak4535_exit(void)
626static int ak4535_remove(struct platform_device *pdev)
627{ 546{
628 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
629 struct snd_soc_codec *codec = socdev->card->codec;
630
631 if (codec->control_data)
632 ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
633
634 snd_soc_free_pcms(socdev);
635 snd_soc_dapm_free(socdev);
636#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 547#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
637 if (codec->control_data)
638 i2c_unregister_device(codec->control_data);
639 i2c_del_driver(&ak4535_i2c_driver); 548 i2c_del_driver(&ak4535_i2c_driver);
640#endif 549#endif
641 kfree(snd_soc_codec_get_drvdata(codec));
642 kfree(codec);
643
644 return 0;
645}
646
647struct snd_soc_codec_device soc_codec_dev_ak4535 = {
648 .probe = ak4535_probe,
649 .remove = ak4535_remove,
650 .suspend = ak4535_suspend,
651 .resume = ak4535_resume,
652};
653EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
654
655static int __init ak4535_modinit(void)
656{
657 return snd_soc_register_dai(&ak4535_dai);
658}
659module_init(ak4535_modinit);
660
661static void __exit ak4535_exit(void)
662{
663 snd_soc_unregister_dai(&ak4535_dai);
664} 550}
665module_exit(ak4535_exit); 551module_exit(ak4535_exit);
666 552
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
index c7a58703ea39..0431e5f634a2 100644
--- a/sound/soc/codecs/ak4535.h
+++ b/sound/soc/codecs/ak4535.h
@@ -36,12 +36,4 @@
36 36
37#define AK4535_CACHEREGNUM 0x10 37#define AK4535_CACHEREGNUM 0x10
38 38
39struct ak4535_setup_data {
40 int i2c_bus;
41 unsigned short i2c_address;
42};
43
44extern struct snd_soc_dai ak4535_dai;
45extern struct snd_soc_codec_device soc_codec_dev_ak4535;
46
47#endif 39#endif
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 3d7dc55305ec..90c90b7f4a2e 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -30,8 +30,6 @@
30#include <sound/initval.h> 30#include <sound/initval.h>
31#include <sound/tlv.h> 31#include <sound/tlv.h>
32 32
33#include "ak4642.h"
34
35#define AK4642_VERSION "0.0.1" 33#define AK4642_VERSION "0.0.1"
36 34
37#define PW_MGMT1 0x00 35#define PW_MGMT1 0x00
@@ -74,6 +72,12 @@
74 72
75#define AK4642_CACHEREGNUM 0x25 73#define AK4642_CACHEREGNUM 0x25
76 74
75/* PW_MGMT1*/
76#define PMVCM (1 << 6) /* VCOM Power Management */
77#define PMMIN (1 << 5) /* MIN Input Power Management */
78#define PMDAC (1 << 2) /* DAC Power Management */
79#define PMADL (1 << 0) /* MIC Amp Lch and ADC Lch Power Management */
80
77/* PW_MGMT2 */ 81/* PW_MGMT2 */
78#define HPMTN (1 << 6) 82#define HPMTN (1 << 6)
79#define PMHPL (1 << 5) 83#define PMHPL (1 << 5)
@@ -85,6 +89,23 @@
85#define PMHP_MASK (PMHPL | PMHPR) 89#define PMHP_MASK (PMHPL | PMHPR)
86#define PMHP PMHP_MASK 90#define PMHP PMHP_MASK
87 91
92/* PW_MGMT3 */
93#define PMADR (1 << 0) /* MIC L / ADC R Power Management */
94
95/* SG_SL1 */
96#define MINS (1 << 6) /* Switch from MIN to Speaker */
97#define DACL (1 << 4) /* Switch from DAC to Stereo or Receiver */
98#define PMMP (1 << 2) /* MPWR pin Power Management */
99#define MGAIN0 (1 << 0) /* MIC amp gain*/
100
101/* TIMER */
102#define ZTM(param) ((param & 0x3) << 4) /* ALC Zoro Crossing TimeOut */
103#define WTM(param) (((param & 0x4) << 4) | ((param & 0x3) << 2))
104
105/* ALC_CTL1 */
106#define ALC (1 << 5) /* ALC Enable */
107#define LMTH0 (1 << 0) /* ALC Limiter / Recovery Level */
108
88/* MD_CTL1 */ 109/* MD_CTL1 */
89#define PLL3 (1 << 7) 110#define PLL3 (1 << 7)
90#define PLL2 (1 << 6) 111#define PLL2 (1 << 6)
@@ -102,7 +123,11 @@
102#define FS3 (1 << 5) 123#define FS3 (1 << 5)
103#define FS_MASK (FS0 | FS1 | FS2 | FS3) 124#define FS_MASK (FS0 | FS1 | FS2 | FS3)
104 125
105struct snd_soc_codec_device soc_codec_dev_ak4642; 126/* MD_CTL3 */
127#define BST1 (1 << 3)
128
129/* MD_CTL4 */
130#define DACH (1 << 0)
106 131
107/* 132/*
108 * Playback Volume (table 39) 133 * Playback Volume (table 39)
@@ -123,11 +148,11 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
123 148
124/* codec private data */ 149/* codec private data */
125struct ak4642_priv { 150struct ak4642_priv {
126 struct snd_soc_codec codec; 151 unsigned int sysclk;
152 enum snd_soc_control_type control_type;
153 void *control_data;
127}; 154};
128 155
129static struct snd_soc_codec *ak4642_codec;
130
131/* 156/*
132 * ak4642 register cache 157 * ak4642 register cache
133 */ 158 */
@@ -219,11 +244,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
219 * This operation came from example code of 244 * This operation came from example code of
220 * "ASAHI KASEI AK4642" (japanese) manual p97. 245 * "ASAHI KASEI AK4642" (japanese) manual p97.
221 */ 246 */
222 ak4642_write(codec, 0x0f, 0x09); 247 snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
223 ak4642_write(codec, 0x0e, 0x19); 248 snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
224 ak4642_write(codec, 0x09, 0x91); 249 ak4642_write(codec, L_IVC, 0x91); /* volume */
225 ak4642_write(codec, 0x0c, 0x91); 250 ak4642_write(codec, R_IVC, 0x91); /* volume */
226 ak4642_write(codec, 0x00, 0x64); 251 snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC,
252 PMVCM | PMMIN | PMDAC);
227 snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP); 253 snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
228 snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN); 254 snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN);
229 } else { 255 } else {
@@ -240,13 +266,12 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
240 * This operation came from example code of 266 * This operation came from example code of
241 * "ASAHI KASEI AK4642" (japanese) manual p94. 267 * "ASAHI KASEI AK4642" (japanese) manual p94.
242 */ 268 */
243 ak4642_write(codec, 0x02, 0x05); 269 ak4642_write(codec, SG_SL1, PMMP | MGAIN0);
244 ak4642_write(codec, 0x06, 0x3c); 270 ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
245 ak4642_write(codec, 0x08, 0xe1); 271 ak4642_write(codec, ALC_CTL1, ALC | LMTH0);
246 ak4642_write(codec, 0x0b, 0x00); 272 snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL,
247 ak4642_write(codec, 0x07, 0x21); 273 PMVCM | PMADL);
248 ak4642_write(codec, 0x00, 0x41); 274 snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
249 ak4642_write(codec, 0x10, 0x01);
250 } 275 }
251 276
252 return 0; 277 return 0;
@@ -262,14 +287,14 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
262 /* stop headphone output */ 287 /* stop headphone output */
263 snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0); 288 snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0);
264 snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0); 289 snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0);
265 ak4642_write(codec, 0x00, 0x40); 290 snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, 0);
266 ak4642_write(codec, 0x0e, 0x11); 291 snd_soc_update_bits(codec, MD_CTL3, BST1, 0);
267 ak4642_write(codec, 0x0f, 0x08); 292 snd_soc_update_bits(codec, MD_CTL4, DACH, 0);
268 } else { 293 } else {
269 /* stop stereo input */ 294 /* stop stereo input */
270 ak4642_write(codec, 0x00, 0x40); 295 snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0);
271 ak4642_write(codec, 0x10, 0x00); 296 snd_soc_update_bits(codec, PW_MGMT3, PMADR, 0);
272 ak4642_write(codec, 0x07, 0x01); 297 snd_soc_update_bits(codec, ALC_CTL1, ALC, 0);
273 } 298 }
274} 299}
275 300
@@ -393,8 +418,8 @@ static struct snd_soc_dai_ops ak4642_dai_ops = {
393 .hw_params = ak4642_dai_hw_params, 418 .hw_params = ak4642_dai_hw_params,
394}; 419};
395 420
396struct snd_soc_dai ak4642_dai = { 421static struct snd_soc_dai_driver ak4642_dai = {
397 .name = "AK4642", 422 .name = "ak4642-hifi",
398 .playback = { 423 .playback = {
399 .stream_name = "Playback", 424 .stream_name = "Playback",
400 .channels_min = 1, 425 .channels_min = 1,
@@ -410,112 +435,65 @@ struct snd_soc_dai ak4642_dai = {
410 .ops = &ak4642_dai_ops, 435 .ops = &ak4642_dai_ops,
411 .symmetric_rates = 1, 436 .symmetric_rates = 1,
412}; 437};
413EXPORT_SYMBOL_GPL(ak4642_dai);
414 438
415static int ak4642_resume(struct platform_device *pdev) 439static int ak4642_resume(struct snd_soc_codec *codec)
416{ 440{
417 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
418 struct snd_soc_codec *codec = socdev->card->codec;
419
420 ak4642_sync(codec); 441 ak4642_sync(codec);
421 return 0; 442 return 0;
422} 443}
423 444
424/* 445
425 * initialise the AK4642 driver 446static int ak4642_probe(struct snd_soc_codec *codec)
426 * register the mixer and dsp interfaces with the kernel
427 */
428static int ak4642_init(struct ak4642_priv *ak4642)
429{ 447{
430 struct snd_soc_codec *codec = &ak4642->codec; 448 struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
431 int ret = 0;
432 449
433 if (ak4642_codec) { 450 dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
434 dev_err(codec->dev, "Another ak4642 is registered\n");
435 return -EINVAL;
436 }
437 451
438 mutex_init(&codec->mutex);
439 INIT_LIST_HEAD(&codec->dapm_widgets);
440 INIT_LIST_HEAD(&codec->dapm_paths);
441
442 snd_soc_codec_set_drvdata(codec, ak4642);
443 codec->name = "AK4642";
444 codec->owner = THIS_MODULE;
445 codec->read = ak4642_read_reg_cache;
446 codec->write = ak4642_write;
447 codec->dai = &ak4642_dai;
448 codec->num_dai = 1;
449 codec->hw_write = (hw_write_t)i2c_master_send; 452 codec->hw_write = (hw_write_t)i2c_master_send;
450 codec->reg_cache_size = ARRAY_SIZE(ak4642_reg); 453 codec->control_data = ak4642->control_data;
451 codec->reg_cache = kmemdup(ak4642_reg,
452 sizeof(ak4642_reg), GFP_KERNEL);
453 454
454 if (!codec->reg_cache) 455 snd_soc_add_controls(codec, ak4642_snd_controls,
455 return -ENOMEM; 456 ARRAY_SIZE(ak4642_snd_controls));
456
457 ak4642_dai.dev = codec->dev;
458 ak4642_codec = codec;
459
460 ret = snd_soc_register_codec(codec);
461 if (ret) {
462 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
463 goto reg_cache_err;
464 }
465
466 ret = snd_soc_register_dai(&ak4642_dai);
467 if (ret) {
468 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
469 snd_soc_unregister_codec(codec);
470 goto reg_cache_err;
471 }
472
473 return ret;
474
475reg_cache_err:
476 kfree(codec->reg_cache);
477 codec->reg_cache = NULL;
478 457
479 return ret; 458 return 0;
480} 459}
481 460
461static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
462 .probe = ak4642_probe,
463 .resume = ak4642_resume,
464 .read = ak4642_read_reg_cache,
465 .write = ak4642_write,
466 .reg_cache_size = ARRAY_SIZE(ak4642_reg),
467 .reg_word_size = sizeof(u8),
468 .reg_cache_default = ak4642_reg,
469};
470
482#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 471#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
483static int ak4642_i2c_probe(struct i2c_client *i2c, 472static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
484 const struct i2c_device_id *id) 473 const struct i2c_device_id *id)
485{ 474{
486 struct ak4642_priv *ak4642; 475 struct ak4642_priv *ak4642;
487 struct snd_soc_codec *codec;
488 int ret; 476 int ret;
489 477
490 ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); 478 ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL);
491 if (!ak4642) 479 if (!ak4642)
492 return -ENOMEM; 480 return -ENOMEM;
493 481
494 codec = &ak4642->codec;
495 codec->dev = &i2c->dev;
496
497 i2c_set_clientdata(i2c, ak4642); 482 i2c_set_clientdata(i2c, ak4642);
498 codec->control_data = i2c; 483 ak4642->control_data = i2c;
484 ak4642->control_type = SND_SOC_I2C;
499 485
500 ret = ak4642_init(ak4642); 486 ret = snd_soc_register_codec(&i2c->dev,
501 if (ret < 0) { 487 &soc_codec_dev_ak4642, &ak4642_dai, 1);
502 printk(KERN_ERR "failed to initialise AK4642\n"); 488 if (ret < 0)
503 kfree(ak4642); 489 kfree(ak4642);
504 }
505
506 return ret; 490 return ret;
507} 491}
508 492
509static int ak4642_i2c_remove(struct i2c_client *client) 493static __devexit int ak4642_i2c_remove(struct i2c_client *client)
510{ 494{
511 struct ak4642_priv *ak4642 = i2c_get_clientdata(client); 495 snd_soc_unregister_codec(&client->dev);
512 496 kfree(i2c_get_clientdata(client));
513 snd_soc_unregister_dai(&ak4642_dai);
514 snd_soc_unregister_codec(&ak4642->codec);
515 kfree(ak4642->codec.reg_cache);
516 kfree(ak4642);
517 ak4642_codec = NULL;
518
519 return 0; 497 return 0;
520} 498}
521 499
@@ -528,64 +506,15 @@ MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
528 506
529static struct i2c_driver ak4642_i2c_driver = { 507static struct i2c_driver ak4642_i2c_driver = {
530 .driver = { 508 .driver = {
531 .name = "AK4642 I2C Codec", 509 .name = "ak4642-codec",
532 .owner = THIS_MODULE, 510 .owner = THIS_MODULE,
533 }, 511 },
534 .probe = ak4642_i2c_probe, 512 .probe = ak4642_i2c_probe,
535 .remove = ak4642_i2c_remove, 513 .remove = __devexit_p(ak4642_i2c_remove),
536 .id_table = ak4642_i2c_id, 514 .id_table = ak4642_i2c_id,
537}; 515};
538
539#endif 516#endif
540 517
541static int ak4642_probe(struct platform_device *pdev)
542{
543 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
544 int ret;
545
546 if (!ak4642_codec) {
547 dev_err(&pdev->dev, "Codec device not registered\n");
548 return -ENODEV;
549 }
550
551 socdev->card->codec = ak4642_codec;
552
553 /* register pcms */
554 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
555 if (ret < 0) {
556 printk(KERN_ERR "ak4642: failed to create pcms\n");
557 goto pcm_err;
558 }
559
560 snd_soc_add_controls(ak4642_codec, ak4642_snd_controls,
561 ARRAY_SIZE(ak4642_snd_controls));
562
563 dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
564 return ret;
565
566pcm_err:
567 return ret;
568
569}
570
571/* power down chip */
572static int ak4642_remove(struct platform_device *pdev)
573{
574 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
575
576 snd_soc_free_pcms(socdev);
577 snd_soc_dapm_free(socdev);
578
579 return 0;
580}
581
582struct snd_soc_codec_device soc_codec_dev_ak4642 = {
583 .probe = ak4642_probe,
584 .remove = ak4642_remove,
585 .resume = ak4642_resume,
586};
587EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642);
588
589static int __init ak4642_modinit(void) 518static int __init ak4642_modinit(void)
590{ 519{
591 int ret = 0; 520 int ret = 0;
diff --git a/sound/soc/codecs/ak4642.h b/sound/soc/codecs/ak4642.h
deleted file mode 100644
index e476833d314e..000000000000
--- a/sound/soc/codecs/ak4642.h
+++ /dev/null
@@ -1,20 +0,0 @@
1/*
2 * ak4642.h -- AK4642 Soc Audio driver
3 *
4 * Copyright (C) 2009 Renesas Solutions Corp.
5 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
6 *
7 * Based on ak4535.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#ifndef _AK4642_H
15#define _AK4642_H
16
17extern struct snd_soc_dai ak4642_dai;
18extern struct snd_soc_codec_device soc_codec_dev_ak4642;
19
20#endif
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 87566932a3b1..24f5f49bb9d2 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -23,11 +23,11 @@
23 23
24#include "ak4671.h" 24#include "ak4671.h"
25 25
26static struct snd_soc_codec *ak4671_codec;
27 26
28/* codec private data */ 27/* codec private data */
29struct ak4671_priv { 28struct ak4671_priv {
30 struct snd_soc_codec codec; 29 enum snd_soc_control_type control_type;
30 void *control_data;
31 u8 reg_cache[AK4671_CACHEREGNUM]; 31 u8 reg_cache[AK4671_CACHEREGNUM];
32}; 32};
33 33
@@ -619,8 +619,8 @@ static struct snd_soc_dai_ops ak4671_dai_ops = {
619 .set_fmt = ak4671_set_dai_fmt, 619 .set_fmt = ak4671_set_dai_fmt,
620}; 620};
621 621
622struct snd_soc_dai ak4671_dai = { 622static struct snd_soc_dai_driver ak4671_dai = {
623 .name = "AK4671", 623 .name = "ak4671-hifi",
624 .playback = { 624 .playback = {
625 .stream_name = "Playback", 625 .stream_name = "Playback",
626 .channels_min = 1, 626 .channels_min = 1,
@@ -635,27 +635,18 @@ struct snd_soc_dai ak4671_dai = {
635 .formats = AK4671_FORMATS,}, 635 .formats = AK4671_FORMATS,},
636 .ops = &ak4671_dai_ops, 636 .ops = &ak4671_dai_ops,
637}; 637};
638EXPORT_SYMBOL_GPL(ak4671_dai);
639 638
640static int ak4671_probe(struct platform_device *pdev) 639static int ak4671_probe(struct snd_soc_codec *codec)
641{ 640{
642 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 641 struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
643 struct snd_soc_codec *codec; 642 int ret;
644 int ret = 0;
645
646 if (ak4671_codec == NULL) {
647 dev_err(&pdev->dev, "Codec device not registered\n");
648 return -ENODEV;
649 }
650 643
651 socdev->card->codec = ak4671_codec; 644 codec->hw_write = (hw_write_t)i2c_master_send;
652 codec = ak4671_codec;
653 645
654 /* register pcms */ 646 ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
655 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
656 if (ret < 0) { 647 if (ret < 0) {
657 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 648 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
658 goto pcm_err; 649 return ret;
659 } 650 }
660 651
661 snd_soc_add_controls(codec, ak4671_snd_controls, 652 snd_soc_add_controls(codec, ak4671_snd_controls,
@@ -665,121 +656,48 @@ static int ak4671_probe(struct platform_device *pdev)
665 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 656 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
666 657
667 return ret; 658 return ret;
668
669pcm_err:
670 return ret;
671} 659}
672 660
673static int ak4671_remove(struct platform_device *pdev) 661static int ak4671_remove(struct snd_soc_codec *codec)
674{ 662{
675 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 663 ak4671_set_bias_level(codec, SND_SOC_BIAS_OFF);
676
677 snd_soc_free_pcms(socdev);
678 snd_soc_dapm_free(socdev);
679
680 return 0; 664 return 0;
681} 665}
682 666
683struct snd_soc_codec_device soc_codec_dev_ak4671 = { 667static struct snd_soc_codec_driver soc_codec_dev_ak4671 = {
684 .probe = ak4671_probe, 668 .probe = ak4671_probe,
685 .remove = ak4671_remove, 669 .remove = ak4671_remove,
670 .set_bias_level = ak4671_set_bias_level,
671 .reg_cache_size = AK4671_CACHEREGNUM,
672 .reg_word_size = sizeof(u8),
673 .reg_cache_default = ak4671_reg,
686}; 674};
687EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671);
688
689static int ak4671_register(struct ak4671_priv *ak4671,
690 enum snd_soc_control_type control)
691{
692 int ret;
693 struct snd_soc_codec *codec = &ak4671->codec;
694
695 if (ak4671_codec) {
696 dev_err(codec->dev, "Another AK4671 is registered\n");
697 ret = -EINVAL;
698 goto err;
699 }
700
701 mutex_init(&codec->mutex);
702 INIT_LIST_HEAD(&codec->dapm_widgets);
703 INIT_LIST_HEAD(&codec->dapm_paths);
704
705 snd_soc_codec_set_drvdata(codec, ak4671);
706 codec->name = "AK4671";
707 codec->owner = THIS_MODULE;
708 codec->bias_level = SND_SOC_BIAS_OFF;
709 codec->set_bias_level = ak4671_set_bias_level;
710 codec->dai = &ak4671_dai;
711 codec->num_dai = 1;
712 codec->reg_cache_size = AK4671_CACHEREGNUM;
713 codec->reg_cache = &ak4671->reg_cache;
714
715 memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));
716
717 ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
718 if (ret < 0) {
719 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
720 goto err;
721 }
722
723 ak4671_dai.dev = codec->dev;
724 ak4671_codec = codec;
725
726 ret = snd_soc_register_codec(codec);
727 if (ret != 0) {
728 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
729 goto err;
730 }
731
732 ret = snd_soc_register_dai(&ak4671_dai);
733 if (ret != 0) {
734 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
735 goto err_codec;
736 }
737
738 return 0;
739
740err_codec:
741 snd_soc_unregister_codec(codec);
742err:
743 kfree(ak4671);
744 return ret;
745}
746
747static void ak4671_unregister(struct ak4671_priv *ak4671)
748{
749 ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF);
750 snd_soc_unregister_dai(&ak4671_dai);
751 snd_soc_unregister_codec(&ak4671->codec);
752 kfree(ak4671);
753 ak4671_codec = NULL;
754}
755 675
756static int __devinit ak4671_i2c_probe(struct i2c_client *client, 676static int __devinit ak4671_i2c_probe(struct i2c_client *client,
757 const struct i2c_device_id *id) 677 const struct i2c_device_id *id)
758{ 678{
759 struct ak4671_priv *ak4671; 679 struct ak4671_priv *ak4671;
760 struct snd_soc_codec *codec; 680 int ret;
761 681
762 ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL); 682 ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
763 if (ak4671 == NULL) 683 if (ak4671 == NULL)
764 return -ENOMEM; 684 return -ENOMEM;
765 685
766 codec = &ak4671->codec;
767 codec->hw_write = (hw_write_t)i2c_master_send;
768
769 i2c_set_clientdata(client, ak4671); 686 i2c_set_clientdata(client, ak4671);
770 codec->control_data = client; 687 ak4671->control_data = client;
771 688 ak4671->control_type = SND_SOC_I2C;
772 codec->dev = &client->dev;
773 689
774 return ak4671_register(ak4671, SND_SOC_I2C); 690 ret = snd_soc_register_codec(&client->dev,
691 &soc_codec_dev_ak4671, &ak4671_dai, 1);
692 if (ret < 0)
693 kfree(ak4671);
694 return ret;
775} 695}
776 696
777static __devexit int ak4671_i2c_remove(struct i2c_client *client) 697static __devexit int ak4671_i2c_remove(struct i2c_client *client)
778{ 698{
779 struct ak4671_priv *ak4671 = i2c_get_clientdata(client); 699 snd_soc_unregister_codec(&client->dev);
780 700 kfree(i2c_get_clientdata(client));
781 ak4671_unregister(ak4671);
782
783 return 0; 701 return 0;
784} 702}
785 703
@@ -791,7 +709,7 @@ MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
791 709
792static struct i2c_driver ak4671_i2c_driver = { 710static struct i2c_driver ak4671_i2c_driver = {
793 .driver = { 711 .driver = {
794 .name = "ak4671", 712 .name = "ak4671-codec",
795 .owner = THIS_MODULE, 713 .owner = THIS_MODULE,
796 }, 714 },
797 .probe = ak4671_i2c_probe, 715 .probe = ak4671_i2c_probe,
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h
index e2fad964e88b..61cb7ab7552c 100644
--- a/sound/soc/codecs/ak4671.h
+++ b/sound/soc/codecs/ak4671.h
@@ -150,7 +150,4 @@
150/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */ 150/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */
151#define AK4671_MUTEN 0x04 151#define AK4671_MUTEN 0x04
152 152
153extern struct snd_soc_dai ak4671_dai;
154extern struct snd_soc_codec_device soc_codec_dev_ak4671;
155
156#endif 153#endif
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index a320fb5a0e26..823643932dde 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -30,6 +30,7 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/clk.h> 31#include <linux/clk.h>
32#include <linux/mfd/davinci_voicecodec.h> 32#include <linux/mfd/davinci_voicecodec.h>
33#include <linux/spi/spi.h>
33 34
34#include <sound/core.h> 35#include <sound/core.h>
35#include <sound/pcm.h> 36#include <sound/pcm.h>
@@ -41,8 +42,6 @@
41 42
42#include <mach/dm365.h> 43#include <mach/dm365.h>
43 44
44#include "cq93vc.h"
45
46static inline unsigned int cq93vc_read(struct snd_soc_codec *codec, 45static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
47 unsigned int reg) 46 unsigned int reg)
48{ 47{
@@ -130,8 +129,8 @@ static struct snd_soc_dai_ops cq93vc_dai_ops = {
130 .set_sysclk = cq93vc_set_dai_sysclk, 129 .set_sysclk = cq93vc_set_dai_sysclk,
131}; 130};
132 131
133struct snd_soc_dai cq93vc_dai = { 132static struct snd_soc_dai_driver cq93vc_dai = {
134 .name = "CQ93VC", 133 .name = "cq93vc-hifi",
135 .playback = { 134 .playback = {
136 .stream_name = "Playback", 135 .stream_name = "Playback",
137 .channels_min = 1, 136 .channels_min = 1,
@@ -146,36 +145,20 @@ struct snd_soc_dai cq93vc_dai = {
146 .formats = CQ93VC_FORMATS,}, 145 .formats = CQ93VC_FORMATS,},
147 .ops = &cq93vc_dai_ops, 146 .ops = &cq93vc_dai_ops,
148}; 147};
149EXPORT_SYMBOL_GPL(cq93vc_dai);
150 148
151static int cq93vc_resume(struct platform_device *pdev) 149static int cq93vc_resume(struct snd_soc_codec *codec)
152{ 150{
153 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
154 struct snd_soc_codec *codec = socdev->card->codec;
155
156 cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 151 cq93vc_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
157 152
158 return 0; 153 return 0;
159} 154}
160 155
161static struct snd_soc_codec *cq93vc_codec; 156static int cq93vc_probe(struct snd_soc_codec *codec)
162
163static int cq93vc_probe(struct platform_device *pdev)
164{ 157{
165 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 158 struct davinci_vc *davinci_vc = codec->dev->platform_data;
166 struct device *dev = &pdev->dev; 159
167 struct snd_soc_codec *codec; 160 davinci_vc->cq93vc.codec = codec;
168 int ret; 161 codec->control_data = davinci_vc;
169
170 socdev->card->codec = cq93vc_codec;
171 codec = socdev->card->codec;
172
173 /* Register pcms */
174 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
175 if (ret < 0) {
176 dev_err(dev, "%s: failed to create pcms\n", pdev->name);
177 return ret;
178 }
179 162
180 /* Set controls */ 163 /* Set controls */
181 snd_soc_add_controls(codec, cq93vc_snd_controls, 164 snd_soc_add_controls(codec, cq93vc_snd_controls,
@@ -187,108 +170,51 @@ static int cq93vc_probe(struct platform_device *pdev)
187 return 0; 170 return 0;
188} 171}
189 172
190static int cq93vc_remove(struct platform_device *pdev) 173static int cq93vc_remove(struct snd_soc_codec *codec)
191{ 174{
192 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 175 cq93vc_set_bias_level(codec, SND_SOC_BIAS_OFF);
193
194 snd_soc_free_pcms(socdev);
195 snd_soc_dapm_free(socdev);
196 176
197 return 0; 177 return 0;
198} 178}
199 179
200struct snd_soc_codec_device soc_codec_dev_cq93vc = { 180static struct snd_soc_codec_driver soc_codec_dev_cq93vc = {
181 .read = cq93vc_read,
182 .write = cq93vc_write,
183 .set_bias_level = cq93vc_set_bias_level,
201 .probe = cq93vc_probe, 184 .probe = cq93vc_probe,
202 .remove = cq93vc_remove, 185 .remove = cq93vc_remove,
203 .resume = cq93vc_resume, 186 .resume = cq93vc_resume,
204}; 187};
205EXPORT_SYMBOL_GPL(soc_codec_dev_cq93vc);
206 188
207static __init int cq93vc_codec_probe(struct platform_device *pdev) 189static int cq93vc_platform_probe(struct platform_device *pdev)
208{ 190{
209 struct davinci_vc *davinci_vc = platform_get_drvdata(pdev); 191 return snd_soc_register_codec(&pdev->dev,
210 struct snd_soc_codec *codec; 192 &soc_codec_dev_cq93vc, &cq93vc_dai, 1);
211 int ret;
212
213 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
214 if (codec == NULL) {
215 dev_dbg(davinci_vc->dev,
216 "could not allocate memory for codec data\n");
217 return -ENOMEM;
218 }
219
220 davinci_vc->cq93vc.codec = codec;
221
222 cq93vc_dai.dev = &pdev->dev;
223
224 mutex_init(&codec->mutex);
225 INIT_LIST_HEAD(&codec->dapm_widgets);
226 INIT_LIST_HEAD(&codec->dapm_paths);
227 codec->dev = &pdev->dev;
228 codec->name = "CQ93VC";
229 codec->owner = THIS_MODULE;
230 codec->read = cq93vc_read;
231 codec->write = cq93vc_write;
232 codec->set_bias_level = cq93vc_set_bias_level;
233 codec->dai = &cq93vc_dai;
234 codec->num_dai = 1;
235 codec->control_data = davinci_vc;
236
237 cq93vc_codec = codec;
238
239 ret = snd_soc_register_codec(codec);
240 if (ret) {
241 dev_err(davinci_vc->dev, "failed to register codec\n");
242 goto fail1;
243 }
244
245 ret = snd_soc_register_dai(&cq93vc_dai);
246 if (ret) {
247 dev_err(davinci_vc->dev, "could register dai\n");
248 goto fail2;
249 }
250 return 0;
251
252fail2:
253 snd_soc_unregister_codec(codec);
254
255fail1:
256 kfree(codec);
257 cq93vc_codec = NULL;
258
259 return ret;
260} 193}
261 194
262static int __devexit cq93vc_codec_remove(struct platform_device *pdev) 195static int cq93vc_platform_remove(struct platform_device *pdev)
263{ 196{
264 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 197 snd_soc_unregister_codec(&pdev->dev);
265 struct snd_soc_codec *codec = socdev->card->codec;
266
267 snd_soc_unregister_dai(&cq93vc_dai);
268 snd_soc_unregister_codec(&codec);
269
270 kfree(codec);
271 cq93vc_codec = NULL;
272
273 return 0; 198 return 0;
274} 199}
275 200
276static struct platform_driver cq93vc_codec_driver = { 201static struct platform_driver cq93vc_codec_driver = {
277 .driver = { 202 .driver = {
278 .name = "cq93vc", 203 .name = "cq93vc-codec",
279 .owner = THIS_MODULE, 204 .owner = THIS_MODULE,
280 }, 205 },
281 .probe = cq93vc_codec_probe, 206
282 .remove = __devexit_p(cq93vc_codec_remove), 207 .probe = cq93vc_platform_probe,
208 .remove = __devexit_p(cq93vc_platform_remove),
283}; 209};
284 210
285static __init int cq93vc_init(void) 211static int __init cq93vc_init(void)
286{ 212{
287 return platform_driver_probe(&cq93vc_codec_driver, cq93vc_codec_probe); 213 return platform_driver_register(&cq93vc_codec_driver);
288} 214}
289module_init(cq93vc_init); 215module_init(cq93vc_init);
290 216
291static __exit void cq93vc_exit(void) 217static void __exit cq93vc_exit(void)
292{ 218{
293 platform_driver_unregister(&cq93vc_codec_driver); 219 platform_driver_unregister(&cq93vc_codec_driver);
294} 220}
diff --git a/sound/soc/codecs/cq93vc.h b/sound/soc/codecs/cq93vc.h
deleted file mode 100644
index 845b1968ef9c..000000000000
--- a/sound/soc/codecs/cq93vc.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * ALSA SoC CQ0093 Voice Codec Driver for DaVinci platforms
3 *
4 * Copyright (C) 2010 Texas Instruments, Inc
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifndef _CQ93VC_H
24#define _CQ93VC_H
25
26extern struct snd_soc_dai cq93vc_dai;
27extern struct snd_soc_codec_device soc_codec_dev_cq93vc;
28
29#endif
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 30d949239def..6d4bdc609ac8 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -31,8 +31,6 @@
31#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/regulator/consumer.h> 32#include <linux/regulator/consumer.h>
33 33
34#include "cs4270.h"
35
36/* 34/*
37 * The codec isn't really big-endian or little-endian, since the I2S 35 * The codec isn't really big-endian or little-endian, since the I2S
38 * interface requires data to be sent serially with the MSbit first. 36 * interface requires data to be sent serially with the MSbit first.
@@ -114,7 +112,8 @@ static const char *supply_names[] = {
114 112
115/* Private data for the CS4270 */ 113/* Private data for the CS4270 */
116struct cs4270_private { 114struct cs4270_private {
117 struct snd_soc_codec codec; 115 enum snd_soc_control_type control_type;
116 void *control_data;
118 u8 reg_cache[CS4270_NUMREGS]; 117 u8 reg_cache[CS4270_NUMREGS];
119 unsigned int mclk; /* Input frequency of the MCLK pin */ 118 unsigned int mclk; /* Input frequency of the MCLK pin */
120 unsigned int mode; /* The mode (I2S or left-justified) */ 119 unsigned int mode; /* The mode (I2S or left-justified) */
@@ -212,44 +211,8 @@ static int cs4270_set_dai_sysclk(struct snd_soc_dai *codec_dai,
212{ 211{
213 struct snd_soc_codec *codec = codec_dai->codec; 212 struct snd_soc_codec *codec = codec_dai->codec;
214 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 213 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
215 unsigned int rates = 0;
216 unsigned int rate_min = -1;
217 unsigned int rate_max = 0;
218 unsigned int i;
219 214
220 cs4270->mclk = freq; 215 cs4270->mclk = freq;
221
222 if (cs4270->mclk) {
223 for (i = 0; i < NUM_MCLK_RATIOS; i++) {
224 unsigned int rate = freq / cs4270_mode_ratios[i].ratio;
225 rates |= snd_pcm_rate_to_rate_bit(rate);
226 if (rate < rate_min)
227 rate_min = rate;
228 if (rate > rate_max)
229 rate_max = rate;
230 }
231 /* FIXME: soc should support a rate list */
232 rates &= ~SNDRV_PCM_RATE_KNOT;
233
234 if (!rates) {
235 dev_err(codec->dev, "could not find a valid sample rate\n");
236 return -EINVAL;
237 }
238 } else {
239 /* enable all possible rates */
240 rates = SNDRV_PCM_RATE_8000_192000;
241 rate_min = 8000;
242 rate_max = 192000;
243 }
244
245 codec_dai->playback.rates = rates;
246 codec_dai->playback.rate_min = rate_min;
247 codec_dai->playback.rate_max = rate_max;
248
249 codec_dai->capture.rates = rates;
250 codec_dai->capture.rate_min = rate_min;
251 codec_dai->capture.rate_max = rate_max;
252
253 return 0; 216 return 0;
254} 217}
255 218
@@ -410,8 +373,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
410 struct snd_soc_dai *dai) 373 struct snd_soc_dai *dai)
411{ 374{
412 struct snd_soc_pcm_runtime *rtd = substream->private_data; 375 struct snd_soc_pcm_runtime *rtd = substream->private_data;
413 struct snd_soc_device *socdev = rtd->socdev; 376 struct snd_soc_codec *codec = rtd->codec;
414 struct snd_soc_codec *codec = socdev->card->codec;
415 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 377 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
416 int ret; 378 int ret;
417 unsigned int i; 379 unsigned int i;
@@ -549,19 +511,6 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
549 snd_soc_get_volsw, cs4270_soc_put_mute), 511 snd_soc_get_volsw, cs4270_soc_put_mute),
550}; 512};
551 513
552/*
553 * cs4270_codec - global variable to store codec for the ASoC probe function
554 *
555 * If struct i2c_driver had a private_data field, we wouldn't need to use
556 * cs4270_codec. This is the only way to pass the codec structure from
557 * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good
558 * way to synchronize these two functions. cs4270_i2c_probe() can be called
559 * multiple times before cs4270_probe() is called even once. So for now, we
560 * also only allow cs4270_i2c_probe() to be run once. That means that we do
561 * not support more than one cs4270 device in the system, at least for now.
562 */
563static struct snd_soc_codec *cs4270_codec;
564
565static struct snd_soc_dai_ops cs4270_dai_ops = { 514static struct snd_soc_dai_ops cs4270_dai_ops = {
566 .hw_params = cs4270_hw_params, 515 .hw_params = cs4270_hw_params,
567 .set_sysclk = cs4270_set_dai_sysclk, 516 .set_sysclk = cs4270_set_dai_sysclk,
@@ -569,25 +518,28 @@ static struct snd_soc_dai_ops cs4270_dai_ops = {
569 .digital_mute = cs4270_dai_mute, 518 .digital_mute = cs4270_dai_mute,
570}; 519};
571 520
572struct snd_soc_dai cs4270_dai = { 521static struct snd_soc_dai_driver cs4270_dai = {
573 .name = "cs4270", 522 .name = "cs4270-hifi",
574 .playback = { 523 .playback = {
575 .stream_name = "Playback", 524 .stream_name = "Playback",
576 .channels_min = 1, 525 .channels_min = 1,
577 .channels_max = 2, 526 .channels_max = 2,
578 .rates = 0, 527 .rates = SNDRV_PCM_RATE_CONTINUOUS,
528 .rate_min = 4000,
529 .rate_max = 216000,
579 .formats = CS4270_FORMATS, 530 .formats = CS4270_FORMATS,
580 }, 531 },
581 .capture = { 532 .capture = {
582 .stream_name = "Capture", 533 .stream_name = "Capture",
583 .channels_min = 1, 534 .channels_min = 1,
584 .channels_max = 2, 535 .channels_max = 2,
585 .rates = 0, 536 .rates = SNDRV_PCM_RATE_CONTINUOUS,
537 .rate_min = 4000,
538 .rate_max = 216000,
586 .formats = CS4270_FORMATS, 539 .formats = CS4270_FORMATS,
587 }, 540 },
588 .ops = &cs4270_dai_ops, 541 .ops = &cs4270_dai_ops,
589}; 542};
590EXPORT_SYMBOL_GPL(cs4270_dai);
591 543
592/** 544/**
593 * cs4270_probe - ASoC probe function 545 * cs4270_probe - ASoC probe function
@@ -596,153 +548,19 @@ EXPORT_SYMBOL_GPL(cs4270_dai);
596 * This function is called when ASoC has all the pieces it needs to 548 * This function is called when ASoC has all the pieces it needs to
597 * instantiate a sound driver. 549 * instantiate a sound driver.
598 */ 550 */
599static int cs4270_probe(struct platform_device *pdev) 551static int cs4270_probe(struct snd_soc_codec *codec)
600{
601 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
602 struct snd_soc_codec *codec = cs4270_codec;
603 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
604 int i, ret;
605
606 /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
607 socdev->card->codec = codec;
608
609 /* Register PCMs */
610 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
611 if (ret < 0) {
612 dev_err(codec->dev, "failed to create pcms\n");
613 return ret;
614 }
615
616 /* Add the non-DAPM controls */
617 ret = snd_soc_add_controls(codec, cs4270_snd_controls,
618 ARRAY_SIZE(cs4270_snd_controls));
619 if (ret < 0) {
620 dev_err(codec->dev, "failed to add controls\n");
621 goto error_free_pcms;
622 }
623
624 /* get the power supply regulators */
625 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
626 cs4270->supplies[i].supply = supply_names[i];
627
628 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
629 cs4270->supplies);
630 if (ret < 0)
631 goto error_free_pcms;
632
633 ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
634 cs4270->supplies);
635 if (ret < 0)
636 goto error_free_regulators;
637
638 return 0;
639
640error_free_regulators:
641 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
642 cs4270->supplies);
643
644error_free_pcms:
645 snd_soc_free_pcms(socdev);
646
647 return ret;
648}
649
650/**
651 * cs4270_remove - ASoC remove function
652 * @pdev: platform device
653 *
654 * This function is the counterpart to cs4270_probe().
655 */
656static int cs4270_remove(struct platform_device *pdev)
657{ 552{
658 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
659 struct snd_soc_codec *codec = cs4270_codec;
660 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 553 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
554 int i, ret, reg;
661 555
662 snd_soc_free_pcms(socdev); 556 codec->control_data = cs4270->control_data;
663 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
664 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
665
666 return 0;
667};
668
669/**
670 * cs4270_i2c_probe - initialize the I2C interface of the CS4270
671 * @i2c_client: the I2C client object
672 * @id: the I2C device ID (ignored)
673 *
674 * This function is called whenever the I2C subsystem finds a device that
675 * matches the device ID given via a prior call to i2c_add_driver().
676 */
677static int cs4270_i2c_probe(struct i2c_client *i2c_client,
678 const struct i2c_device_id *id)
679{
680 struct snd_soc_codec *codec;
681 struct cs4270_private *cs4270;
682 unsigned int reg;
683 int ret;
684
685 /* For now, we only support one cs4270 device in the system. See the
686 * comment for cs4270_codec.
687 */
688 if (cs4270_codec) {
689 dev_err(&i2c_client->dev, "ignoring CS4270 at addr %X\n",
690 i2c_client->addr);
691 dev_err(&i2c_client->dev, "only one per board allowed\n");
692 /* Should we return something other than ENODEV here? */
693 return -ENODEV;
694 }
695
696 /* Verify that we have a CS4270 */
697
698 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
699 if (ret < 0) {
700 dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
701 i2c_client->addr);
702 return ret;
703 }
704 /* The top four bits of the chip ID should be 1100. */
705 if ((ret & 0xF0) != 0xC0) {
706 dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
707 i2c_client->addr);
708 return -ENODEV;
709 }
710
711 dev_info(&i2c_client->dev, "found device at i2c address %X\n",
712 i2c_client->addr);
713 dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
714
715 /* Allocate enough space for the snd_soc_codec structure
716 and our private data together. */
717 cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
718 if (!cs4270) {
719 dev_err(&i2c_client->dev, "could not allocate codec\n");
720 return -ENOMEM;
721 }
722 codec = &cs4270->codec;
723
724 mutex_init(&codec->mutex);
725 INIT_LIST_HEAD(&codec->dapm_widgets);
726 INIT_LIST_HEAD(&codec->dapm_paths);
727
728 codec->dev = &i2c_client->dev;
729 codec->name = "CS4270";
730 codec->owner = THIS_MODULE;
731 codec->dai = &cs4270_dai;
732 codec->num_dai = 1;
733 snd_soc_codec_set_drvdata(codec, cs4270);
734 codec->control_data = i2c_client;
735 codec->read = cs4270_read_reg_cache;
736 codec->write = cs4270_i2c_write;
737 codec->reg_cache = cs4270->reg_cache;
738 codec->reg_cache_size = CS4270_NUMREGS;
739 557
740 /* The I2C interface is set up, so pre-fill our register cache */ 558 /* The I2C interface is set up, so pre-fill our register cache */
741 559
742 ret = cs4270_fill_cache(codec); 560 ret = cs4270_fill_cache(codec);
743 if (ret < 0) { 561 if (ret < 0) {
744 dev_err(&i2c_client->dev, "failed to fill register cache\n"); 562 dev_err(codec->dev, "failed to fill register cache\n");
745 goto error_free_codec; 563 return ret;
746 } 564 }
747 565
748 /* Disable auto-mute. This feature appears to be buggy. In some 566 /* Disable auto-mute. This feature appears to be buggy. In some
@@ -755,7 +573,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
755 reg &= ~CS4270_MUTE_AUTO; 573 reg &= ~CS4270_MUTE_AUTO;
756 ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); 574 ret = cs4270_i2c_write(codec, CS4270_MUTE, reg);
757 if (ret < 0) { 575 if (ret < 0) {
758 dev_err(&i2c_client->dev, "i2c write failed\n"); 576 dev_err(codec->dev, "i2c write failed\n");
759 return ret; 577 return ret;
760 } 578 }
761 579
@@ -769,65 +587,56 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
769 reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); 587 reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
770 ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); 588 ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
771 if (ret < 0) { 589 if (ret < 0) {
772 dev_err(&i2c_client->dev, "i2c write failed\n"); 590 dev_err(codec->dev, "i2c write failed\n");
773 return ret; 591 return ret;
774 } 592 }
775 593
776 /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI 594 /* Add the non-DAPM controls */
777 * structure for each CS4270 device, but the machine driver needs to 595 ret = snd_soc_add_controls(codec, cs4270_snd_controls,
778 * have a pointer to the DAI structure, so for now it must be a global 596 ARRAY_SIZE(cs4270_snd_controls));
779 * variable.
780 */
781 cs4270_dai.dev = &i2c_client->dev;
782
783 /* Register the DAI. If all the other ASoC driver have already
784 * registered, then this will call our probe function, so
785 * cs4270_codec needs to be ready.
786 */
787 cs4270_codec = codec;
788 ret = snd_soc_register_dai(&cs4270_dai);
789 if (ret < 0) { 597 if (ret < 0) {
790 dev_err(&i2c_client->dev, "failed to register DAIe\n"); 598 dev_err(codec->dev, "failed to add controls\n");
791 goto error_free_codec; 599 return ret;
792 } 600 }
793 601
794 i2c_set_clientdata(i2c_client, cs4270); 602 /* get the power supply regulators */
603 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
604 cs4270->supplies[i].supply = supply_names[i];
605
606 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies),
607 cs4270->supplies);
608 if (ret < 0)
609 return ret;
610
611 ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
612 cs4270->supplies);
613 if (ret < 0)
614 goto error_free_regulators;
795 615
796 return 0; 616 return 0;
797 617
798error_free_codec: 618error_free_regulators:
799 kfree(cs4270); 619 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies),
800 cs4270_codec = NULL; 620 cs4270->supplies);
801 cs4270_dai.dev = NULL;
802 621
803 return ret; 622 return ret;
804} 623}
805 624
806/** 625/**
807 * cs4270_i2c_remove - remove an I2C device 626 * cs4270_remove - ASoC remove function
808 * @i2c_client: the I2C client object 627 * @pdev: platform device
809 * 628 *
810 * This function is the counterpart to cs4270_i2c_probe(). 629 * This function is the counterpart to cs4270_probe().
811 */ 630 */
812static int cs4270_i2c_remove(struct i2c_client *i2c_client) 631static int cs4270_remove(struct snd_soc_codec *codec)
813{ 632{
814 struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); 633 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
815 634
816 kfree(cs4270); 635 regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
817 cs4270_codec = NULL; 636 regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies);
818 cs4270_dai.dev = NULL;
819 637
820 return 0; 638 return 0;
821}
822
823/*
824 * cs4270_id - I2C device IDs supported by this driver
825 */
826static struct i2c_device_id cs4270_id[] = {
827 {"cs4270", 0},
828 {}
829}; 639};
830MODULE_DEVICE_TABLE(i2c, cs4270_id);
831 640
832#ifdef CONFIG_PM 641#ifdef CONFIG_PM
833 642
@@ -840,9 +649,8 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
840 * and all registers are written back to the hardware when resuming. 649 * and all registers are written back to the hardware when resuming.
841 */ 650 */
842 651
843static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) 652static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
844{ 653{
845 struct snd_soc_codec *codec = cs4270_codec;
846 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 654 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
847 int reg, ret; 655 int reg, ret;
848 656
@@ -860,9 +668,8 @@ static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
860 return 0; 668 return 0;
861} 669}
862 670
863static int cs4270_soc_resume(struct platform_device *pdev) 671static int cs4270_soc_resume(struct snd_soc_codec *codec)
864{ 672{
865 struct snd_soc_codec *codec = cs4270_codec;
866 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); 673 struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
867 struct i2c_client *i2c_client = codec->control_data; 674 struct i2c_client *i2c_client = codec->control_data;
868 int reg; 675 int reg;
@@ -896,6 +703,95 @@ static int cs4270_soc_resume(struct platform_device *pdev)
896#endif /* CONFIG_PM */ 703#endif /* CONFIG_PM */
897 704
898/* 705/*
706 * ASoC codec device structure
707 *
708 * Assign this variable to the codec_dev field of the machine driver's
709 * snd_soc_device structure.
710 */
711static struct snd_soc_codec_driver soc_codec_device_cs4270 = {
712 .probe = cs4270_probe,
713 .remove = cs4270_remove,
714 .suspend = cs4270_soc_suspend,
715 .resume = cs4270_soc_resume,
716 .read = cs4270_read_reg_cache,
717 .write = cs4270_i2c_write,
718 .reg_cache_size = CS4270_NUMREGS,
719 .reg_word_size = sizeof(u8),
720};
721
722/**
723 * cs4270_i2c_probe - initialize the I2C interface of the CS4270
724 * @i2c_client: the I2C client object
725 * @id: the I2C device ID (ignored)
726 *
727 * This function is called whenever the I2C subsystem finds a device that
728 * matches the device ID given via a prior call to i2c_add_driver().
729 */
730static int cs4270_i2c_probe(struct i2c_client *i2c_client,
731 const struct i2c_device_id *id)
732{
733 struct cs4270_private *cs4270;
734 int ret;
735
736 /* Verify that we have a CS4270 */
737
738 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
739 if (ret < 0) {
740 dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n",
741 i2c_client->addr);
742 return ret;
743 }
744 /* The top four bits of the chip ID should be 1100. */
745 if ((ret & 0xF0) != 0xC0) {
746 dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n",
747 i2c_client->addr);
748 return -ENODEV;
749 }
750
751 dev_info(&i2c_client->dev, "found device at i2c address %X\n",
752 i2c_client->addr);
753 dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
754
755 cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
756 if (!cs4270) {
757 dev_err(&i2c_client->dev, "could not allocate codec\n");
758 return -ENOMEM;
759 }
760
761 i2c_set_clientdata(i2c_client, cs4270);
762 cs4270->control_data = i2c_client;
763 cs4270->control_type = SND_SOC_I2C;
764
765 ret = snd_soc_register_codec(&i2c_client->dev,
766 &soc_codec_device_cs4270, &cs4270_dai, 1);
767 if (ret < 0)
768 kfree(cs4270);
769 return ret;
770}
771
772/**
773 * cs4270_i2c_remove - remove an I2C device
774 * @i2c_client: the I2C client object
775 *
776 * This function is the counterpart to cs4270_i2c_probe().
777 */
778static int cs4270_i2c_remove(struct i2c_client *i2c_client)
779{
780 snd_soc_unregister_codec(&i2c_client->dev);
781 kfree(i2c_get_clientdata(i2c_client));
782 return 0;
783}
784
785/*
786 * cs4270_id - I2C device IDs supported by this driver
787 */
788static struct i2c_device_id cs4270_id[] = {
789 {"cs4270", 0},
790 {}
791};
792MODULE_DEVICE_TABLE(i2c, cs4270_id);
793
794/*
899 * cs4270_i2c_driver - I2C device identification 795 * cs4270_i2c_driver - I2C device identification
900 * 796 *
901 * This structure tells the I2C subsystem how to identify and support a 797 * This structure tells the I2C subsystem how to identify and support a
@@ -903,7 +799,7 @@ static int cs4270_soc_resume(struct platform_device *pdev)
903 */ 799 */
904static struct i2c_driver cs4270_i2c_driver = { 800static struct i2c_driver cs4270_i2c_driver = {
905 .driver = { 801 .driver = {
906 .name = "cs4270", 802 .name = "cs4270-codec",
907 .owner = THIS_MODULE, 803 .owner = THIS_MODULE,
908 }, 804 },
909 .id_table = cs4270_id, 805 .id_table = cs4270_id,
@@ -911,20 +807,6 @@ static struct i2c_driver cs4270_i2c_driver = {
911 .remove = cs4270_i2c_remove, 807 .remove = cs4270_i2c_remove,
912}; 808};
913 809
914/*
915 * ASoC codec device structure
916 *
917 * Assign this variable to the codec_dev field of the machine driver's
918 * snd_soc_device structure.
919 */
920struct snd_soc_codec_device soc_codec_device_cs4270 = {
921 .probe = cs4270_probe,
922 .remove = cs4270_remove,
923 .suspend = cs4270_soc_suspend,
924 .resume = cs4270_soc_resume,
925};
926EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
927
928static int __init cs4270_init(void) 810static int __init cs4270_init(void)
929{ 811{
930 pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); 812 pr_info("Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
diff --git a/sound/soc/codecs/cs4270.h b/sound/soc/codecs/cs4270.h
deleted file mode 100644
index adc6cd9667d4..000000000000
--- a/sound/soc/codecs/cs4270.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * Cirrus Logic CS4270 ALSA SoC Codec Driver
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
6 * Copyright 2007 Freescale Semiconductor, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#ifndef _CS4270_H
13#define _CS4270_H
14
15/*
16 * The ASoC codec DAI structure for the CS4270. Assign this structure to
17 * the .codec_dai field of your machine driver's snd_soc_dai_link structure.
18 */
19extern struct snd_soc_dai cs4270_dai;
20
21/*
22 * The ASoC codec device structure for the CS4270. Assign this structure
23 * to the .codec_dev field of your machine driver's snd_soc_device
24 * structure.
25 */
26extern struct snd_soc_codec_device soc_codec_device_cs4270;
27
28#endif
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index dd9b8550c402..cb086eaf4e07 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -42,15 +42,14 @@ enum master_slave_mode {
42}; 42};
43 43
44struct cs42l51_private { 44struct cs42l51_private {
45 enum snd_soc_control_type control_type;
46 void *control_data;
45 unsigned int mclk; 47 unsigned int mclk;
46 unsigned int audio_mode; /* The mode (I2S or left-justified) */ 48 unsigned int audio_mode; /* The mode (I2S or left-justified) */
47 enum master_slave_mode func; 49 enum master_slave_mode func;
48 struct snd_soc_codec codec;
49 u8 reg_cache[CS42L51_NUMREGS]; 50 u8 reg_cache[CS42L51_NUMREGS];
50}; 51};
51 52
52static struct snd_soc_codec *cs42l51_codec;
53
54#define CS42L51_FORMATS ( \ 53#define CS42L51_FORMATS ( \
55 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ 54 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
56 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ 55 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \
@@ -75,134 +74,6 @@ static int cs42l51_fill_cache(struct snd_soc_codec *codec)
75 return 0; 74 return 0;
76} 75}
77 76
78static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
79 const struct i2c_device_id *id)
80{
81 struct snd_soc_codec *codec;
82 struct cs42l51_private *cs42l51;
83 int ret = 0;
84 int reg;
85
86 if (cs42l51_codec)
87 return -EBUSY;
88
89 /* Verify that we have a CS42L51 */
90 ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
91 if (ret < 0) {
92 dev_err(&i2c_client->dev, "failed to read I2C\n");
93 goto error;
94 }
95
96 if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
97 (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
98 dev_err(&i2c_client->dev, "Invalid chip id\n");
99 ret = -ENODEV;
100 goto error;
101 }
102
103 dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
104 ret & 7);
105
106 cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
107 if (!cs42l51) {
108 dev_err(&i2c_client->dev, "could not allocate codec\n");
109 return -ENOMEM;
110 }
111 codec = &cs42l51->codec;
112
113 mutex_init(&codec->mutex);
114 INIT_LIST_HEAD(&codec->dapm_widgets);
115 INIT_LIST_HEAD(&codec->dapm_paths);
116
117 codec->dev = &i2c_client->dev;
118 codec->name = "CS42L51";
119 codec->owner = THIS_MODULE;
120 codec->dai = &cs42l51_dai;
121 codec->num_dai = 1;
122 snd_soc_codec_set_drvdata(codec, cs42l51);
123
124 codec->control_data = i2c_client;
125 codec->reg_cache = cs42l51->reg_cache;
126 codec->reg_cache_size = CS42L51_NUMREGS;
127 i2c_set_clientdata(i2c_client, codec);
128
129 ret = cs42l51_fill_cache(codec);
130 if (ret < 0) {
131 dev_err(&i2c_client->dev, "failed to fill register cache\n");
132 goto error_alloc;
133 }
134
135 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
136 if (ret < 0) {
137 dev_err(&i2c_client->dev, "Failed to set cache I/O: %d\n", ret);
138 goto error_alloc;
139 }
140
141 /*
142 * DAC configuration
143 * - Use signal processor
144 * - auto mute
145 * - vol changes immediate
146 * - no de-emphasize
147 */
148 reg = CS42L51_DAC_CTL_DATA_SEL(1)
149 | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
150 ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
151 if (ret < 0)
152 goto error_alloc;
153
154 cs42l51_dai.dev = codec->dev;
155 cs42l51_codec = codec;
156
157 ret = snd_soc_register_codec(codec);
158 if (ret != 0) {
159 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
160 goto error_alloc;
161 }
162
163 ret = snd_soc_register_dai(&cs42l51_dai);
164 if (ret < 0) {
165 dev_err(&i2c_client->dev, "failed to register DAIe\n");
166 goto error_reg;
167 }
168
169 return 0;
170
171error_reg:
172 snd_soc_unregister_codec(codec);
173error_alloc:
174 kfree(cs42l51);
175error:
176 return ret;
177}
178
179static int cs42l51_i2c_remove(struct i2c_client *client)
180{
181 struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
182 snd_soc_unregister_dai(&cs42l51_dai);
183 snd_soc_unregister_codec(cs42l51_codec);
184 cs42l51_codec = NULL;
185 kfree(cs42l51);
186 return 0;
187}
188
189
190static const struct i2c_device_id cs42l51_id[] = {
191 {"cs42l51", 0},
192 {}
193};
194MODULE_DEVICE_TABLE(i2c, cs42l51_id);
195
196static struct i2c_driver cs42l51_i2c_driver = {
197 .driver = {
198 .name = "CS42L51 I2C",
199 .owner = THIS_MODULE,
200 },
201 .id_table = cs42l51_id,
202 .probe = cs42l51_i2c_probe,
203 .remove = cs42l51_i2c_remove,
204};
205
206static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, 77static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol,
207 struct snd_ctl_elem_value *ucontrol) 78 struct snd_ctl_elem_value *ucontrol)
208{ 79{
@@ -484,51 +355,8 @@ static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai,
484{ 355{
485 struct snd_soc_codec *codec = codec_dai->codec; 356 struct snd_soc_codec *codec = codec_dai->codec;
486 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); 357 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
487 struct cs42l51_ratios *ratios = NULL;
488 int nr_ratios = 0;
489 unsigned int rates = 0;
490 unsigned int rate_min = -1;
491 unsigned int rate_max = 0;
492 int i;
493 358
494 cs42l51->mclk = freq; 359 cs42l51->mclk = freq;
495
496 switch (cs42l51->func) {
497 case MODE_MASTER:
498 return -EINVAL;
499 case MODE_SLAVE:
500 ratios = slave_ratios;
501 nr_ratios = ARRAY_SIZE(slave_ratios);
502 break;
503 case MODE_SLAVE_AUTO:
504 ratios = slave_auto_ratios;
505 nr_ratios = ARRAY_SIZE(slave_auto_ratios);
506 break;
507 }
508
509 for (i = 0; i < nr_ratios; i++) {
510 unsigned int rate = freq / ratios[i].ratio;
511 rates |= snd_pcm_rate_to_rate_bit(rate);
512 if (rate < rate_min)
513 rate_min = rate;
514 if (rate > rate_max)
515 rate_max = rate;
516 }
517 rates &= ~SNDRV_PCM_RATE_KNOT;
518
519 if (!rates) {
520 dev_err(codec->dev, "could not find a valid sample rate\n");
521 return -EINVAL;
522 }
523
524 codec_dai->playback.rates = rates;
525 codec_dai->playback.rate_min = rate_min;
526 codec_dai->playback.rate_max = rate_max;
527
528 codec_dai->capture.rates = rates;
529 codec_dai->capture.rate_min = rate_min;
530 codec_dai->capture.rate_max = rate_max;
531
532 return 0; 360 return 0;
533} 361}
534 362
@@ -537,8 +365,7 @@ static int cs42l51_hw_params(struct snd_pcm_substream *substream,
537 struct snd_soc_dai *dai) 365 struct snd_soc_dai *dai)
538{ 366{
539 struct snd_soc_pcm_runtime *rtd = substream->private_data; 367 struct snd_soc_pcm_runtime *rtd = substream->private_data;
540 struct snd_soc_device *socdev = rtd->socdev; 368 struct snd_soc_codec *codec = rtd->codec;
541 struct snd_soc_codec *codec = socdev->card->codec;
542 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); 369 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
543 int ret; 370 int ret;
544 unsigned int i; 371 unsigned int i;
@@ -670,8 +497,8 @@ static struct snd_soc_dai_ops cs42l51_dai_ops = {
670 .digital_mute = cs42l51_dai_mute, 497 .digital_mute = cs42l51_dai_mute,
671}; 498};
672 499
673struct snd_soc_dai cs42l51_dai = { 500static struct snd_soc_dai_driver cs42l51_dai = {
674 .name = "CS42L51 HiFi", 501 .name = "cs42l51-hifi",
675 .playback = { 502 .playback = {
676 .stream_name = "Playback", 503 .stream_name = "Playback",
677 .channels_min = 1, 504 .channels_min = 1,
@@ -688,30 +515,39 @@ struct snd_soc_dai cs42l51_dai = {
688 }, 515 },
689 .ops = &cs42l51_dai_ops, 516 .ops = &cs42l51_dai_ops,
690}; 517};
691EXPORT_SYMBOL_GPL(cs42l51_dai);
692
693 518
694static int cs42l51_probe(struct platform_device *pdev) 519static int cs42l51_probe(struct snd_soc_codec *codec)
695{ 520{
696 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 521 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
697 struct snd_soc_codec *codec; 522 int ret, reg;
698 int ret = 0;
699 523
700 if (!cs42l51_codec) { 524 codec->control_data = cs42l51->control_data;
701 dev_err(&pdev->dev, "CS42L51 codec not yet registered\n");
702 return -EINVAL;
703 }
704 525
705 socdev->card->codec = cs42l51_codec; 526 ret = cs42l51_fill_cache(codec);
706 codec = socdev->card->codec; 527 if (ret < 0) {
528 dev_err(codec->dev, "failed to fill register cache\n");
529 return ret;
530 }
707 531
708 /* Register PCMs */ 532 ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type);
709 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
710 if (ret < 0) { 533 if (ret < 0) {
711 dev_err(&pdev->dev, "failed to create PCMs\n"); 534 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
712 return ret; 535 return ret;
713 } 536 }
714 537
538 /*
539 * DAC configuration
540 * - Use signal processor
541 * - auto mute
542 * - vol changes immediate
543 * - no de-emphasize
544 */
545 reg = CS42L51_DAC_CTL_DATA_SEL(1)
546 | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0);
547 ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg);
548 if (ret < 0)
549 return ret;
550
715 snd_soc_add_controls(codec, cs42l51_snd_controls, 551 snd_soc_add_controls(codec, cs42l51_snd_controls,
716 ARRAY_SIZE(cs42l51_snd_controls)); 552 ARRAY_SIZE(cs42l51_snd_controls));
717 snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets, 553 snd_soc_dapm_new_controls(codec, cs42l51_dapm_widgets,
@@ -722,22 +558,77 @@ static int cs42l51_probe(struct platform_device *pdev)
722 return 0; 558 return 0;
723} 559}
724 560
561static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
562 .probe = cs42l51_probe,
563 .reg_cache_size = CS42L51_NUMREGS,
564 .reg_word_size = sizeof(u8),
565};
725 566
726static int cs42l51_remove(struct platform_device *pdev) 567static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
568 const struct i2c_device_id *id)
727{ 569{
728 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 570 struct cs42l51_private *cs42l51;
571 int ret;
729 572
730 snd_soc_free_pcms(socdev); 573 /* Verify that we have a CS42L51 */
731 snd_soc_dapm_free(socdev); 574 ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID);
575 if (ret < 0) {
576 dev_err(&i2c_client->dev, "failed to read I2C\n");
577 goto error;
578 }
579
580 if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) &&
581 (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) {
582 dev_err(&i2c_client->dev, "Invalid chip id\n");
583 ret = -ENODEV;
584 goto error;
585 }
586
587 dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
588 ret & 7);
589
590 cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
591 if (!cs42l51) {
592 dev_err(&i2c_client->dev, "could not allocate codec\n");
593 return -ENOMEM;
594 }
595
596 i2c_set_clientdata(i2c_client, cs42l51);
597 cs42l51->control_data = i2c_client;
598 cs42l51->control_type = SND_SOC_I2C;
732 599
600 ret = snd_soc_register_codec(&i2c_client->dev,
601 &soc_codec_device_cs42l51, &cs42l51_dai, 1);
602 if (ret < 0)
603 kfree(cs42l51);
604error:
605 return ret;
606}
607
608static int cs42l51_i2c_remove(struct i2c_client *client)
609{
610 struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
611
612 snd_soc_unregister_codec(&client->dev);
613 kfree(cs42l51);
733 return 0; 614 return 0;
734} 615}
735 616
736struct snd_soc_codec_device soc_codec_device_cs42l51 = { 617static const struct i2c_device_id cs42l51_id[] = {
737 .probe = cs42l51_probe, 618 {"cs42l51", 0},
738 .remove = cs42l51_remove 619 {}
620};
621MODULE_DEVICE_TABLE(i2c, cs42l51_id);
622
623static struct i2c_driver cs42l51_i2c_driver = {
624 .driver = {
625 .name = "cs42l51-codec",
626 .owner = THIS_MODULE,
627 },
628 .id_table = cs42l51_id,
629 .probe = cs42l51_i2c_probe,
630 .remove = cs42l51_i2c_remove,
739}; 631};
740EXPORT_SYMBOL_GPL(soc_codec_device_cs42l51);
741 632
742static int __init cs42l51_init(void) 633static int __init cs42l51_init(void)
743{ 634{
@@ -758,6 +649,6 @@ static void __exit cs42l51_exit(void)
758} 649}
759module_exit(cs42l51_exit); 650module_exit(cs42l51_exit);
760 651
761MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>"); 652MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
762MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); 653MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
763MODULE_LICENSE("GPL"); 654MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l51.h b/sound/soc/codecs/cs42l51.h
index 8f0bd9786ad2..2beeb171db4b 100644
--- a/sound/soc/codecs/cs42l51.h
+++ b/sound/soc/codecs/cs42l51.h
@@ -158,6 +158,4 @@
158#define CS42L51_LASTREG 0x20 158#define CS42L51_LASTREG 0x20
159#define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1) 159#define CS42L51_NUMREGS (CS42L51_LASTREG - CS42L51_FIRSTREG + 1)
160 160
161extern struct snd_soc_dai cs42l51_dai;
162extern struct snd_soc_codec_device soc_codec_device_cs42l51;
163#endif 161#endif
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index f07a415c753f..e8d27c8f9ba3 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -24,7 +24,8 @@
24 24
25 25
26struct cx20442_priv { 26struct cx20442_priv {
27 struct snd_soc_codec codec; 27 enum snd_soc_control_type control_type;
28 void *control_data;
28 u8 reg_cache[1]; 29 u8 reg_cache[1];
29}; 30};
30 31
@@ -102,7 +103,7 @@ static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec,
102{ 103{
103 u8 *reg_cache = codec->reg_cache; 104 u8 *reg_cache = codec->reg_cache;
104 105
105 if (reg >= codec->reg_cache_size) 106 if (reg >= codec->driver->reg_cache_size)
106 return -EINVAL; 107 return -EINVAL;
107 108
108 return reg_cache[reg]; 109 return reg_cache[reg];
@@ -164,16 +165,17 @@ static int cx20442_pm_to_v253_vsp(u8 value)
164static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, 165static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
165 unsigned int value) 166 unsigned int value)
166{ 167{
168 struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
167 u8 *reg_cache = codec->reg_cache; 169 u8 *reg_cache = codec->reg_cache;
168 int vls, vsp, old, len; 170 int vls, vsp, old, len;
169 char buf[18]; 171 char buf[18];
170 172
171 if (reg >= codec->reg_cache_size) 173 if (reg >= codec->driver->reg_cache_size)
172 return -EINVAL; 174 return -EINVAL;
173 175
174 /* hw_write and control_data pointers required for talking to the modem 176 /* hw_write and control_data pointers required for talking to the modem
175 * are expected to be set by the line discipline initialization code */ 177 * are expected to be set by the line discipline initialization code */
176 if (!codec->hw_write || !codec->control_data) 178 if (!codec->hw_write || !cx20442->control_data)
177 return -EIO; 179 return -EIO;
178 180
179 old = reg_cache[reg]; 181 old = reg_cache[reg];
@@ -202,17 +204,13 @@ static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg,
202 return -ENOMEM; 204 return -ENOMEM;
203 205
204 dev_dbg(codec->dev, "%s: %s\n", __func__, buf); 206 dev_dbg(codec->dev, "%s: %s\n", __func__, buf);
205 if (codec->hw_write(codec->control_data, buf, len) != len) 207 if (codec->hw_write(cx20442->control_data, buf, len) != len)
206 return -EIO; 208 return -EIO;
207 209
208 return 0; 210 return 0;
209} 211}
210 212
211 213
212/* Moved up here as line discipline referres it during initialization */
213static struct snd_soc_codec *cx20442_codec;
214
215
216/* 214/*
217 * Line discpline related code 215 * Line discpline related code
218 * 216 *
@@ -228,15 +226,15 @@ static const char *v253_init = "ate0m0q0+fclass=8\r";
228/* Line discipline .open() */ 226/* Line discipline .open() */
229static int v253_open(struct tty_struct *tty) 227static int v253_open(struct tty_struct *tty)
230{ 228{
231 struct snd_soc_codec *codec = cx20442_codec;
232 int ret, len = strlen(v253_init); 229 int ret, len = strlen(v253_init);
233 230
234 /* Doesn't make sense without write callback */ 231 /* Doesn't make sense without write callback */
235 if (!tty->ops->write) 232 if (!tty->ops->write)
236 return -EINVAL; 233 return -EINVAL;
237 234
238 /* Pass the codec structure address for use by other ldisc callbacks */ 235 /* Won't work if no codec pointer has been passed by a card driver */
239 tty->disc_data = codec; 236 if (!tty->disc_data)
237 return -ENODEV;
240 238
241 if (tty->ops->write(tty, v253_init, len) != len) { 239 if (tty->ops->write(tty, v253_init, len) != len) {
242 ret = -EIO; 240 ret = -EIO;
@@ -253,15 +251,18 @@ err:
253static void v253_close(struct tty_struct *tty) 251static void v253_close(struct tty_struct *tty)
254{ 252{
255 struct snd_soc_codec *codec = tty->disc_data; 253 struct snd_soc_codec *codec = tty->disc_data;
254 struct cx20442_priv *cx20442;
256 255
257 tty->disc_data = NULL; 256 tty->disc_data = NULL;
258 257
259 if (!codec) 258 if (!codec)
260 return; 259 return;
261 260
261 cx20442 = snd_soc_codec_get_drvdata(codec);
262
262 /* Prevent the codec driver from further accessing the modem */ 263 /* Prevent the codec driver from further accessing the modem */
263 codec->hw_write = NULL; 264 codec->hw_write = NULL;
264 codec->control_data = NULL; 265 cx20442->control_data = NULL;
265 codec->pop_time = 0; 266 codec->pop_time = 0;
266} 267}
267 268
@@ -277,15 +278,18 @@ static void v253_receive(struct tty_struct *tty,
277 const unsigned char *cp, char *fp, int count) 278 const unsigned char *cp, char *fp, int count)
278{ 279{
279 struct snd_soc_codec *codec = tty->disc_data; 280 struct snd_soc_codec *codec = tty->disc_data;
281 struct cx20442_priv *cx20442;
280 282
281 if (!codec) 283 if (!codec)
282 return; 284 return;
283 285
284 if (!codec->control_data) { 286 cx20442 = snd_soc_codec_get_drvdata(codec);
287
288 if (!cx20442->control_data) {
285 /* First modem response, complete setup procedure */ 289 /* First modem response, complete setup procedure */
286 290
287 /* Set up codec driver access to modem controls */ 291 /* Set up codec driver access to modem controls */
288 codec->control_data = tty; 292 cx20442->control_data = tty;
289 codec->hw_write = (hw_write_t)tty->ops->write; 293 codec->hw_write = (hw_write_t)tty->ops->write;
290 codec->pop_time = 1; 294 codec->pop_time = 1;
291 } 295 }
@@ -313,8 +317,8 @@ EXPORT_SYMBOL_GPL(v253_ops);
313 * Codec DAI 317 * Codec DAI
314 */ 318 */
315 319
316struct snd_soc_dai cx20442_dai = { 320static struct snd_soc_dai_driver cx20442_dai = {
317 .name = "CX20442", 321 .name = "cx20442-voice",
318 .playback = { 322 .playback = {
319 .stream_name = "Playback", 323 .stream_name = "Playback",
320 .channels_min = 1, 324 .channels_min = 1,
@@ -330,142 +334,63 @@ struct snd_soc_dai cx20442_dai = {
330 .formats = SNDRV_PCM_FMTBIT_S16_LE, 334 .formats = SNDRV_PCM_FMTBIT_S16_LE,
331 }, 335 },
332}; 336};
333EXPORT_SYMBOL_GPL(cx20442_dai);
334 337
335static int cx20442_codec_probe(struct platform_device *pdev) 338static int cx20442_codec_probe(struct snd_soc_codec *codec)
336{ 339{
337 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 340 struct cx20442_priv *cx20442;
338 struct snd_soc_codec *codec;
339 int ret;
340
341 if (!cx20442_codec) {
342 dev_err(&pdev->dev, "cx20442 not yet discovered\n");
343 return -ENODEV;
344 }
345 codec = cx20442_codec;
346
347 socdev->card->codec = codec;
348 341
349 /* register pcms */ 342 cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
350 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 343 if (cx20442 == NULL)
351 if (ret < 0) { 344 return -ENOMEM;
352 dev_err(&pdev->dev, "failed to create pcms\n"); 345 snd_soc_codec_set_drvdata(codec, cx20442);
353 goto pcm_err;
354 }
355 346
356 cx20442_add_widgets(codec); 347 cx20442_add_widgets(codec);
357 348
358pcm_err: 349 cx20442->control_data = NULL;
359 return ret; 350 codec->hw_write = NULL;
351 codec->pop_time = 0;
352
353 return 0;
360} 354}
361 355
362/* power down chip */ 356/* power down chip */
363static int cx20442_codec_remove(struct platform_device *pdev) 357static int cx20442_codec_remove(struct snd_soc_codec *codec)
364{ 358{
365 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 359 struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
366 360
367 snd_soc_free_pcms(socdev); 361 if (cx20442->control_data) {
368 snd_soc_dapm_free(socdev); 362 struct tty_struct *tty = cx20442->control_data;
363 tty_hangup(tty);
364 }
369 365
366 kfree(cx20442);
370 return 0; 367 return 0;
371} 368}
372 369
373struct snd_soc_codec_device cx20442_codec_dev = { 370static struct snd_soc_codec_driver cx20442_codec_dev = {
374 .probe = cx20442_codec_probe, 371 .probe = cx20442_codec_probe,
375 .remove = cx20442_codec_remove, 372 .remove = cx20442_codec_remove,
373 .reg_cache_size = 1,
374 .reg_word_size = sizeof(u8),
375 .read = cx20442_read_reg_cache,
376 .write = cx20442_write,
376}; 377};
377EXPORT_SYMBOL_GPL(cx20442_codec_dev);
378
379static int cx20442_register(struct cx20442_priv *cx20442)
380{
381 struct snd_soc_codec *codec = &cx20442->codec;
382 int ret;
383
384 mutex_init(&codec->mutex);
385 INIT_LIST_HEAD(&codec->dapm_widgets);
386 INIT_LIST_HEAD(&codec->dapm_paths);
387
388 codec->name = "CX20442";
389 codec->owner = THIS_MODULE;
390 snd_soc_codec_set_drvdata(codec, cx20442);
391
392 codec->dai = &cx20442_dai;
393 codec->num_dai = 1;
394
395 codec->reg_cache = &cx20442->reg_cache;
396 codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache);
397 codec->read = cx20442_read_reg_cache;
398 codec->write = cx20442_write;
399
400 codec->bias_level = SND_SOC_BIAS_OFF;
401
402 cx20442_dai.dev = codec->dev;
403
404 cx20442_codec = codec;
405
406 ret = snd_soc_register_codec(codec);
407 if (ret != 0) {
408 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
409 goto err;
410 }
411
412 ret = snd_soc_register_dai(&cx20442_dai);
413 if (ret != 0) {
414 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
415 goto err_codec;
416 }
417
418 return 0;
419
420err_codec:
421 snd_soc_unregister_codec(codec);
422err:
423 cx20442_codec = NULL;
424 kfree(cx20442);
425 return ret;
426}
427
428static void cx20442_unregister(struct cx20442_priv *cx20442)
429{
430 snd_soc_unregister_dai(&cx20442_dai);
431 snd_soc_unregister_codec(&cx20442->codec);
432
433 cx20442_codec = NULL;
434 kfree(cx20442);
435}
436 378
437static int cx20442_platform_probe(struct platform_device *pdev) 379static int cx20442_platform_probe(struct platform_device *pdev)
438{ 380{
439 struct cx20442_priv *cx20442; 381 return snd_soc_register_codec(&pdev->dev,
440 struct snd_soc_codec *codec; 382 &cx20442_codec_dev, &cx20442_dai, 1);
441
442 cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
443 if (cx20442 == NULL)
444 return -ENOMEM;
445
446 codec = &cx20442->codec;
447
448 codec->control_data = NULL;
449 codec->hw_write = NULL;
450 codec->pop_time = 0;
451
452 codec->dev = &pdev->dev;
453 platform_set_drvdata(pdev, cx20442);
454
455 return cx20442_register(cx20442);
456} 383}
457 384
458static int __exit cx20442_platform_remove(struct platform_device *pdev) 385static int __exit cx20442_platform_remove(struct platform_device *pdev)
459{ 386{
460 struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); 387 snd_soc_unregister_codec(&pdev->dev);
461
462 cx20442_unregister(cx20442);
463 return 0; 388 return 0;
464} 389}
465 390
466static struct platform_driver cx20442_platform_driver = { 391static struct platform_driver cx20442_platform_driver = {
467 .driver = { 392 .driver = {
468 .name = "cx20442", 393 .name = "cx20442-codec",
469 .owner = THIS_MODULE, 394 .owner = THIS_MODULE,
470 }, 395 },
471 .probe = cx20442_platform_probe, 396 .probe = cx20442_platform_probe,
@@ -487,4 +412,4 @@ module_exit(cx20442_exit);
487MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); 412MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
488MODULE_AUTHOR("Janusz Krzysztofik"); 413MODULE_AUTHOR("Janusz Krzysztofik");
489MODULE_LICENSE("GPL"); 414MODULE_LICENSE("GPL");
490MODULE_ALIAS("platform:cx20442"); 415MODULE_ALIAS("platform:cx20442-codec");
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h
index 688a5eb62e17..c7a7c79ef0cd 100644
--- a/sound/soc/codecs/cx20442.h
+++ b/sound/soc/codecs/cx20442.h
@@ -13,8 +13,6 @@
13#ifndef _CX20442_CODEC_H 13#ifndef _CX20442_CODEC_H
14#define _CX20442_CODEC_H 14#define _CX20442_CODEC_H
15 15
16extern struct snd_soc_dai cx20442_dai;
17extern struct snd_soc_codec_device cx20442_codec_dev;
18extern struct tty_ldisc_ops v253_ops; 16extern struct tty_ldisc_ops v253_ops;
19 17
20#endif 18#endif
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 3c51d6a57523..58bb9b994811 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -25,8 +25,6 @@
25#include <sound/initval.h> 25#include <sound/initval.h>
26#include <sound/tlv.h> 26#include <sound/tlv.h>
27 27
28#include "da7210.h"
29
30/* DA7210 register space */ 28/* DA7210 register space */
31#define DA7210_STATUS 0x02 29#define DA7210_STATUS 0x02
32#define DA7210_STARTUP1 0x03 30#define DA7210_STARTUP1 0x03
@@ -162,11 +160,10 @@ static const struct snd_kcontrol_new da7210_snd_controls[] = {
162 160
163/* Codec private data */ 161/* Codec private data */
164struct da7210_priv { 162struct da7210_priv {
165 struct snd_soc_codec codec; 163 enum snd_soc_control_type control_type;
164 void *control_data;
166}; 165};
167 166
168static struct snd_soc_codec *da7210_codec;
169
170/* 167/*
171 * Register cache 168 * Register cache
172 */ 169 */
@@ -209,12 +206,12 @@ static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)
209 u8 *cache = codec->reg_cache; 206 u8 *cache = codec->reg_cache;
210 u8 data[2]; 207 u8 data[2];
211 208
212 BUG_ON(codec->volatile_register); 209 BUG_ON(codec->driver->volatile_register);
213 210
214 data[0] = reg & 0xff; 211 data[0] = reg & 0xff;
215 data[1] = value & 0xff; 212 data[1] = value & 0xff;
216 213
217 if (reg >= codec->reg_cache_size) 214 if (reg >= codec->driver->reg_cache_size)
218 return -EIO; 215 return -EIO;
219 216
220 if (2 != codec->hw_write(codec->control_data, data, 2)) 217 if (2 != codec->hw_write(codec->control_data, data, 2))
@@ -267,8 +264,7 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
267 struct snd_soc_dai *dai) 264 struct snd_soc_dai *dai)
268{ 265{
269 struct snd_soc_pcm_runtime *rtd = substream->private_data; 266 struct snd_soc_pcm_runtime *rtd = substream->private_data;
270 struct snd_soc_device *socdev = rtd->socdev; 267 struct snd_soc_codec *codec = rtd->codec;
271 struct snd_soc_codec *codec = socdev->card->codec;
272 u32 dai_cfg1; 268 u32 dai_cfg1;
273 u32 hpf_reg, hpf_mask, hpf_value; 269 u32 hpf_reg, hpf_mask, hpf_value;
274 u32 fs, bypass; 270 u32 fs, bypass;
@@ -430,9 +426,8 @@ static struct snd_soc_dai_ops da7210_dai_ops = {
430 .set_fmt = da7210_set_dai_fmt, 426 .set_fmt = da7210_set_dai_fmt,
431}; 427};
432 428
433struct snd_soc_dai da7210_dai = { 429static struct snd_soc_dai_driver da7210_dai = {
434 .name = "DA7210 IIS", 430 .name = "da7210-hifi",
435 .id = 0,
436 /* playback capabilities */ 431 /* playback capabilities */
437 .playback = { 432 .playback = {
438 .stream_name = "Playback", 433 .stream_name = "Playback",
@@ -452,55 +447,15 @@ struct snd_soc_dai da7210_dai = {
452 .ops = &da7210_dai_ops, 447 .ops = &da7210_dai_ops,
453 .symmetric_rates = 1, 448 .symmetric_rates = 1,
454}; 449};
455EXPORT_SYMBOL_GPL(da7210_dai);
456 450
457/* 451static int da7210_probe(struct snd_soc_codec *codec)
458 * Initialize the DA7210 driver
459 * register the mixer and dsp interfaces with the kernel
460 */
461static int da7210_init(struct da7210_priv *da7210)
462{ 452{
463 struct snd_soc_codec *codec = &da7210->codec; 453 struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
464 int ret = 0;
465 454
466 if (da7210_codec) { 455 dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
467 dev_err(codec->dev, "Another da7210 is registered\n");
468 return -EINVAL;
469 }
470 456
471 mutex_init(&codec->mutex); 457 codec->control_data = da7210->control_data;
472 INIT_LIST_HEAD(&codec->dapm_widgets);
473 INIT_LIST_HEAD(&codec->dapm_paths);
474
475 snd_soc_codec_set_drvdata(codec, da7210);
476 codec->name = "DA7210";
477 codec->owner = THIS_MODULE;
478 codec->read = da7210_read;
479 codec->write = da7210_write;
480 codec->dai = &da7210_dai;
481 codec->num_dai = 1;
482 codec->hw_write = (hw_write_t)i2c_master_send; 458 codec->hw_write = (hw_write_t)i2c_master_send;
483 codec->reg_cache_size = ARRAY_SIZE(da7210_reg);
484 codec->reg_cache = kmemdup(da7210_reg,
485 sizeof(da7210_reg), GFP_KERNEL);
486
487 if (!codec->reg_cache)
488 return -ENOMEM;
489
490 da7210_dai.dev = codec->dev;
491 da7210_codec = codec;
492
493 ret = snd_soc_register_codec(codec);
494 if (ret) {
495 dev_err(codec->dev, "Failed to register CODEC: %d\n", ret);
496 goto init_err;
497 }
498
499 ret = snd_soc_register_dai(&da7210_dai);
500 if (ret) {
501 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
502 goto codec_err;
503 }
504 459
505 /* FIXME 460 /* FIXME
506 * 461 *
@@ -583,54 +538,50 @@ static int da7210_init(struct da7210_priv *da7210)
583 /* Activate all enabled subsystem */ 538 /* Activate all enabled subsystem */
584 da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); 539 da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
585 540
586 return ret; 541 snd_soc_add_controls(codec, da7210_snd_controls,
587 542 ARRAY_SIZE(da7210_snd_controls));
588codec_err:
589 snd_soc_unregister_codec(codec);
590init_err:
591 kfree(codec->reg_cache);
592 codec->reg_cache = NULL;
593 543
594 return ret; 544 dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
595 545
546 return 0;
596} 547}
597 548
549static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
550 .probe = da7210_probe,
551 .read = da7210_read,
552 .write = da7210_write,
553 .reg_cache_size = ARRAY_SIZE(da7210_reg),
554 .reg_word_size = sizeof(u8),
555 .reg_cache_default = da7210_reg,
556};
557
598#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 558#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
599static int __devinit da7210_i2c_probe(struct i2c_client *i2c, 559static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
600 const struct i2c_device_id *id) 560 const struct i2c_device_id *id)
601{ 561{
602 struct da7210_priv *da7210; 562 struct da7210_priv *da7210;
603 struct snd_soc_codec *codec;
604 int ret; 563 int ret;
605 564
606 da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL); 565 da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL);
607 if (!da7210) 566 if (!da7210)
608 return -ENOMEM; 567 return -ENOMEM;
609 568
610 codec = &da7210->codec;
611 codec->dev = &i2c->dev;
612
613 i2c_set_clientdata(i2c, da7210); 569 i2c_set_clientdata(i2c, da7210);
614 codec->control_data = i2c; 570 da7210->control_data = i2c;
571 da7210->control_type = SND_SOC_I2C;
615 572
616 ret = da7210_init(da7210); 573 ret = snd_soc_register_codec(&i2c->dev,
617 if (ret < 0) { 574 &soc_codec_dev_da7210, &da7210_dai, 1);
618 pr_err("Failed to initialise da7210 audio codec\n"); 575 if (ret < 0)
619 kfree(da7210); 576 kfree(da7210);
620 }
621 577
622 return ret; 578 return ret;
623} 579}
624 580
625static int __devexit da7210_i2c_remove(struct i2c_client *client) 581static int __devexit da7210_i2c_remove(struct i2c_client *client)
626{ 582{
627 struct da7210_priv *da7210 = i2c_get_clientdata(client); 583 snd_soc_unregister_codec(&client->dev);
628 584 kfree(i2c_get_clientdata(client));
629 snd_soc_unregister_dai(&da7210_dai);
630 kfree(da7210->codec.reg_cache);
631 kfree(da7210);
632 da7210_codec = NULL;
633
634 return 0; 585 return 0;
635} 586}
636 587
@@ -643,59 +594,15 @@ MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
643/* I2C codec control layer */ 594/* I2C codec control layer */
644static struct i2c_driver da7210_i2c_driver = { 595static struct i2c_driver da7210_i2c_driver = {
645 .driver = { 596 .driver = {
646 .name = "DA7210 I2C Codec", 597 .name = "da7210-codec",
647 .owner = THIS_MODULE, 598 .owner = THIS_MODULE,
648 }, 599 },
649 .probe = da7210_i2c_probe, 600 .probe = da7210_i2c_probe,
650 .remove = __devexit_p(da7210_i2c_remove), 601 .remove = __devexit_p(da7210_i2c_remove),
651 .id_table = da7210_i2c_id, 602 .id_table = da7210_i2c_id,
652}; 603};
653#endif 604#endif
654 605
655static int da7210_probe(struct platform_device *pdev)
656{
657 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
658 struct snd_soc_codec *codec;
659 int ret;
660
661 if (!da7210_codec) {
662 dev_err(&pdev->dev, "Codec device not registered\n");
663 return -ENODEV;
664 }
665
666 socdev->card->codec = da7210_codec;
667 codec = da7210_codec;
668
669 /* Register pcms */
670 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
671 if (ret < 0)
672 goto pcm_err;
673
674 snd_soc_add_controls(da7210_codec, da7210_snd_controls,
675 ARRAY_SIZE(da7210_snd_controls));
676
677 dev_info(&pdev->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
678
679pcm_err:
680 return ret;
681}
682
683static int da7210_remove(struct platform_device *pdev)
684{
685 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
686
687 snd_soc_free_pcms(socdev);
688 snd_soc_dapm_free(socdev);
689
690 return 0;
691}
692
693struct snd_soc_codec_device soc_codec_dev_da7210 = {
694 .probe = da7210_probe,
695 .remove = da7210_remove,
696};
697EXPORT_SYMBOL_GPL(soc_codec_dev_da7210);
698
699static int __init da7210_modinit(void) 606static int __init da7210_modinit(void)
700{ 607{
701 int ret = 0; 608 int ret = 0;
diff --git a/sound/soc/codecs/da7210.h b/sound/soc/codecs/da7210.h
deleted file mode 100644
index 390d621eb742..000000000000
--- a/sound/soc/codecs/da7210.h
+++ /dev/null
@@ -1,24 +0,0 @@
1/*
2 * da7210.h -- audio driver for da7210
3 *
4 * Copyright (c) 2009 Dialog Semiconductor
5 * Written by David Chen <Dajun.chen@diasemi.com>
6 *
7 * Copyright (C) 2009 Renesas Solutions Corp.
8 * Cleanups by Kuninori Morimoto <morimoto.kuninori@renesas.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#ifndef _DA7210_H
18#define _DA7210_H
19
20extern struct snd_soc_dai da7210_dai;
21extern struct snd_soc_codec_device soc_codec_dev_da7210;
22
23#endif
24
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index 66557de1e4fe..16253ec9b022 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -74,29 +74,22 @@ static const uint32_t jz4740_codec_regs[] = {
74struct jz4740_codec { 74struct jz4740_codec {
75 void __iomem *base; 75 void __iomem *base;
76 struct resource *mem; 76 struct resource *mem;
77
78 uint32_t reg_cache[2];
79 struct snd_soc_codec codec;
80}; 77};
81 78
82static inline struct jz4740_codec *codec_to_jz4740(struct snd_soc_codec *codec)
83{
84 return container_of(codec, struct jz4740_codec, codec);
85}
86
87static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, 79static unsigned int jz4740_codec_read(struct snd_soc_codec *codec,
88 unsigned int reg) 80 unsigned int reg)
89{ 81{
90 struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); 82 struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
91 return readl(jz4740_codec->base + (reg << 2)); 83 return readl(jz4740_codec->base + (reg << 2));
92} 84}
93 85
94static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, 86static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg,
95 unsigned int val) 87 unsigned int val)
96{ 88{
97 struct jz4740_codec *jz4740_codec = codec_to_jz4740(codec); 89 struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec);
90 u32 *cache = codec->reg_cache;
98 91
99 jz4740_codec->reg_cache[reg] = val; 92 cache[reg] = val;
100 writel(val, jz4740_codec->base + (reg << 2)); 93 writel(val, jz4740_codec->base + (reg << 2));
101 94
102 return 0; 95 return 0;
@@ -172,8 +165,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
172{ 165{
173 uint32_t val; 166 uint32_t val;
174 struct snd_soc_pcm_runtime *rtd = substream->private_data; 167 struct snd_soc_pcm_runtime *rtd = substream->private_data;
175 struct snd_soc_device *socdev = rtd->socdev; 168 struct snd_soc_codec *codec =rtd->codec;
176 struct snd_soc_codec *codec = socdev->card->codec;
177 169
178 switch (params_rate(params)) { 170 switch (params_rate(params)) {
179 case 8000: 171 case 8000:
@@ -219,8 +211,8 @@ static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
219 .hw_params = jz4740_codec_hw_params, 211 .hw_params = jz4740_codec_hw_params,
220}; 212};
221 213
222struct snd_soc_dai jz4740_codec_dai = { 214static struct snd_soc_dai_driver jz4740_codec_dai = {
223 .name = "jz4740", 215 .name = "jz4740-hifi",
224 .playback = { 216 .playback = {
225 .stream_name = "Playback", 217 .stream_name = "Playback",
226 .channels_min = 2, 218 .channels_min = 2,
@@ -238,7 +230,6 @@ struct snd_soc_dai jz4740_codec_dai = {
238 .ops = &jz4740_codec_dai_ops, 230 .ops = &jz4740_codec_dai_ops,
239 .symmetric_rates = 1, 231 .symmetric_rates = 1,
240}; 232};
241EXPORT_SYMBOL_GPL(jz4740_codec_dai);
242 233
243static void jz4740_codec_wakeup(struct snd_soc_codec *codec) 234static void jz4740_codec_wakeup(struct snd_soc_codec *codec)
244{ 235{
@@ -302,23 +293,10 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec,
302 return 0; 293 return 0;
303} 294}
304 295
305static struct snd_soc_codec *jz4740_codec_codec; 296static int jz4740_codec_dev_probe(struct snd_soc_codec *codec)
306
307static int jz4740_codec_dev_probe(struct platform_device *pdev)
308{ 297{
309 int ret; 298 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
310 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 299 JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
311 struct snd_soc_codec *codec = jz4740_codec_codec;
312
313 BUG_ON(!codec);
314
315 socdev->card->codec = codec;
316
317 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
318 if (ret) {
319 dev_err(&pdev->dev, "Failed to create pcms: %d\n", ret);
320 return ret;
321 }
322 300
323 snd_soc_add_controls(codec, jz4740_codec_controls, 301 snd_soc_add_controls(codec, jz4740_codec_controls,
324 ARRAY_SIZE(jz4740_codec_controls)); 302 ARRAY_SIZE(jz4740_codec_controls));
@@ -331,34 +309,27 @@ static int jz4740_codec_dev_probe(struct platform_device *pdev)
331 309
332 snd_soc_dapm_new_widgets(codec); 310 snd_soc_dapm_new_widgets(codec);
333 311
312 jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
313
334 return 0; 314 return 0;
335} 315}
336 316
337static int jz4740_codec_dev_remove(struct platform_device *pdev) 317static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)
338{ 318{
339 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 319 jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
340
341 snd_soc_free_pcms(socdev);
342 snd_soc_dapm_free(socdev);
343 320
344 return 0; 321 return 0;
345} 322}
346 323
347#ifdef CONFIG_PM_SLEEP 324#ifdef CONFIG_PM_SLEEP
348 325
349static int jz4740_codec_suspend(struct platform_device *pdev, pm_message_t state) 326static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
350{ 327{
351 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
352 struct snd_soc_codec *codec = socdev->card->codec;
353
354 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF); 328 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
355} 329}
356 330
357static int jz4740_codec_resume(struct platform_device *pdev) 331static int jz4740_codec_resume(struct snd_soc_codec *codec)
358{ 332{
359 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
360 struct snd_soc_codec *codec = socdev->card->codec;
361
362 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 333 return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
363} 334}
364 335
@@ -367,19 +338,23 @@ static int jz4740_codec_resume(struct platform_device *pdev)
367#define jz4740_codec_resume NULL 338#define jz4740_codec_resume NULL
368#endif 339#endif
369 340
370struct snd_soc_codec_device soc_codec_dev_jz4740_codec = { 341static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = {
371 .probe = jz4740_codec_dev_probe, 342 .probe = jz4740_codec_dev_probe,
372 .remove = jz4740_codec_dev_remove, 343 .remove = jz4740_codec_dev_remove,
373 .suspend = jz4740_codec_suspend, 344 .suspend = jz4740_codec_suspend,
374 .resume = jz4740_codec_resume, 345 .resume = jz4740_codec_resume,
346 .read = jz4740_codec_read,
347 .write = jz4740_codec_write,
348 .set_bias_level = jz4740_codec_set_bias_level,
349 .reg_cache_default = jz4740_codec_regs,
350 .reg_word_size = sizeof(u32),
351 .reg_cache_size = 2,
375}; 352};
376EXPORT_SYMBOL_GPL(soc_codec_dev_jz4740_codec);
377 353
378static int __devinit jz4740_codec_probe(struct platform_device *pdev) 354static int __devinit jz4740_codec_probe(struct platform_device *pdev)
379{ 355{
380 int ret; 356 int ret;
381 struct jz4740_codec *jz4740_codec; 357 struct jz4740_codec *jz4740_codec;
382 struct snd_soc_codec *codec;
383 struct resource *mem; 358 struct resource *mem;
384 359
385 jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL); 360 jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
@@ -408,55 +383,17 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
408 } 383 }
409 jz4740_codec->mem = mem; 384 jz4740_codec->mem = mem;
410 385
411 jz4740_codec_dai.dev = &pdev->dev;
412
413 codec = &jz4740_codec->codec;
414
415 codec->dev = &pdev->dev;
416 codec->name = "jz4740";
417 codec->owner = THIS_MODULE;
418
419 codec->read = jz4740_codec_read;
420 codec->write = jz4740_codec_write;
421 codec->set_bias_level = jz4740_codec_set_bias_level;
422 codec->bias_level = SND_SOC_BIAS_OFF;
423
424 codec->dai = &jz4740_codec_dai;
425 codec->num_dai = 1;
426
427 codec->reg_cache = jz4740_codec->reg_cache;
428 codec->reg_cache_size = 2;
429 memcpy(codec->reg_cache, jz4740_codec_regs, sizeof(jz4740_codec_regs));
430
431 mutex_init(&codec->mutex);
432 INIT_LIST_HEAD(&codec->dapm_widgets);
433 INIT_LIST_HEAD(&codec->dapm_paths);
434
435 jz4740_codec_codec = codec;
436
437 snd_soc_update_bits(codec, JZ4740_REG_CODEC_1,
438 JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE);
439
440 platform_set_drvdata(pdev, jz4740_codec); 386 platform_set_drvdata(pdev, jz4740_codec);
441 387
442 ret = snd_soc_register_codec(codec); 388 ret = snd_soc_register_codec(&pdev->dev,
389 &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
443 if (ret) { 390 if (ret) {
444 dev_err(&pdev->dev, "Failed to register codec\n"); 391 dev_err(&pdev->dev, "Failed to register codec\n");
445 goto err_iounmap; 392 goto err_iounmap;
446 } 393 }
447 394
448 ret = snd_soc_register_dai(&jz4740_codec_dai);
449 if (ret) {
450 dev_err(&pdev->dev, "Failed to register codec dai\n");
451 goto err_unregister_codec;
452 }
453
454 jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
455
456 return 0; 395 return 0;
457 396
458err_unregister_codec:
459 snd_soc_unregister_codec(codec);
460err_iounmap: 397err_iounmap:
461 iounmap(jz4740_codec->base); 398 iounmap(jz4740_codec->base);
462err_release_mem_region: 399err_release_mem_region:
@@ -472,8 +409,7 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
472 struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); 409 struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev);
473 struct resource *mem = jz4740_codec->mem; 410 struct resource *mem = jz4740_codec->mem;
474 411
475 snd_soc_unregister_dai(&jz4740_codec_dai); 412 snd_soc_unregister_codec(&pdev->dev);
476 snd_soc_unregister_codec(&jz4740_codec->codec);
477 413
478 iounmap(jz4740_codec->base); 414 iounmap(jz4740_codec->base);
479 release_mem_region(mem->start, resource_size(mem)); 415 release_mem_region(mem->start, resource_size(mem));
diff --git a/sound/soc/codecs/jz4740.h b/sound/soc/codecs/jz4740.h
deleted file mode 100644
index b5a0691be763..000000000000
--- a/sound/soc/codecs/jz4740.h
+++ /dev/null
@@ -1,20 +0,0 @@
1/*
2 * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * You should have received a copy of the GNU General Public License along
9 * with this program; if not, write to the Free Software Foundation, Inc.,
10 * 675 Mass Ave, Cambridge, MA 02139, USA.
11 *
12 */
13
14#ifndef __SND_SOC_CODECS_JZ4740_CODEC_H__
15#define __SND_SOC_CODECS_JZ4740_CODEC_H__
16
17extern struct snd_soc_dai jz4740_codec_dai;
18extern struct snd_soc_codec_device soc_codec_dev_jz4740_codec;
19
20#endif
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
new file mode 100644
index 000000000000..e7a40d16df90
--- /dev/null
+++ b/sound/soc/codecs/max98088.c
@@ -0,0 +1,2097 @@
1/*
2 * max98088.c -- MAX98088 ALSA SoC Audio driver
3 *
4 * Copyright 2010 Maxim Integrated Products
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/module.h>
12#include <linux/moduleparam.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/delay.h>
16#include <linux/pm.h>
17#include <linux/i2c.h>
18#include <linux/platform_device.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/pcm_params.h>
22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24#include <sound/initval.h>
25#include <sound/tlv.h>
26#include <linux/slab.h>
27#include <asm/div64.h>
28#include <sound/max98088.h>
29#include "max98088.h"
30
31struct max98088_cdata {
32 unsigned int rate;
33 unsigned int fmt;
34 int eq_sel;
35};
36
37struct max98088_priv {
38 u8 reg_cache[M98088_REG_CNT];
39 void *control_data;
40 struct max98088_pdata *pdata;
41 unsigned int sysclk;
42 struct max98088_cdata dai[2];
43 int eq_textcnt;
44 const char **eq_texts;
45 struct soc_enum eq_enum;
46 u8 ina_state;
47 u8 inb_state;
48 unsigned int ex_mode;
49 unsigned int digmic;
50 unsigned int mic1pre;
51 unsigned int mic2pre;
52 unsigned int extmic_mode;
53};
54
55static const u8 max98088_reg[M98088_REG_CNT] = {
56 0x00, /* 00 IRQ status */
57 0x00, /* 01 MIC status */
58 0x00, /* 02 jack status */
59 0x00, /* 03 battery voltage */
60 0x00, /* 04 */
61 0x00, /* 05 */
62 0x00, /* 06 */
63 0x00, /* 07 */
64 0x00, /* 08 */
65 0x00, /* 09 */
66 0x00, /* 0A */
67 0x00, /* 0B */
68 0x00, /* 0C */
69 0x00, /* 0D */
70 0x00, /* 0E */
71 0x00, /* 0F interrupt enable */
72
73 0x00, /* 10 master clock */
74 0x00, /* 11 DAI1 clock mode */
75 0x00, /* 12 DAI1 clock control */
76 0x00, /* 13 DAI1 clock control */
77 0x00, /* 14 DAI1 format */
78 0x00, /* 15 DAI1 clock */
79 0x00, /* 16 DAI1 config */
80 0x00, /* 17 DAI1 TDM */
81 0x00, /* 18 DAI1 filters */
82 0x00, /* 19 DAI2 clock mode */
83 0x00, /* 1A DAI2 clock control */
84 0x00, /* 1B DAI2 clock control */
85 0x00, /* 1C DAI2 format */
86 0x00, /* 1D DAI2 clock */
87 0x00, /* 1E DAI2 config */
88 0x00, /* 1F DAI2 TDM */
89
90 0x00, /* 20 DAI2 filters */
91 0x00, /* 21 data config */
92 0x00, /* 22 DAC mixer */
93 0x00, /* 23 left ADC mixer */
94 0x00, /* 24 right ADC mixer */
95 0x00, /* 25 left HP mixer */
96 0x00, /* 26 right HP mixer */
97 0x00, /* 27 HP control */
98 0x00, /* 28 left REC mixer */
99 0x00, /* 29 right REC mixer */
100 0x00, /* 2A REC control */
101 0x00, /* 2B left SPK mixer */
102 0x00, /* 2C right SPK mixer */
103 0x00, /* 2D SPK control */
104 0x00, /* 2E sidetone */
105 0x00, /* 2F DAI1 playback level */
106
107 0x00, /* 30 DAI1 playback level */
108 0x00, /* 31 DAI2 playback level */
109 0x00, /* 32 DAI2 playbakc level */
110 0x00, /* 33 left ADC level */
111 0x00, /* 34 right ADC level */
112 0x00, /* 35 MIC1 level */
113 0x00, /* 36 MIC2 level */
114 0x00, /* 37 INA level */
115 0x00, /* 38 INB level */
116 0x00, /* 39 left HP volume */
117 0x00, /* 3A right HP volume */
118 0x00, /* 3B left REC volume */
119 0x00, /* 3C right REC volume */
120 0x00, /* 3D left SPK volume */
121 0x00, /* 3E right SPK volume */
122 0x00, /* 3F MIC config */
123
124 0x00, /* 40 MIC threshold */
125 0x00, /* 41 excursion limiter filter */
126 0x00, /* 42 excursion limiter threshold */
127 0x00, /* 43 ALC */
128 0x00, /* 44 power limiter threshold */
129 0x00, /* 45 power limiter config */
130 0x00, /* 46 distortion limiter config */
131 0x00, /* 47 audio input */
132 0x00, /* 48 microphone */
133 0x00, /* 49 level control */
134 0x00, /* 4A bypass switches */
135 0x00, /* 4B jack detect */
136 0x00, /* 4C input enable */
137 0x00, /* 4D output enable */
138 0xF0, /* 4E bias control */
139 0x00, /* 4F DAC power */
140
141 0x0F, /* 50 DAC power */
142 0x00, /* 51 system */
143 0x00, /* 52 DAI1 EQ1 */
144 0x00, /* 53 DAI1 EQ1 */
145 0x00, /* 54 DAI1 EQ1 */
146 0x00, /* 55 DAI1 EQ1 */
147 0x00, /* 56 DAI1 EQ1 */
148 0x00, /* 57 DAI1 EQ1 */
149 0x00, /* 58 DAI1 EQ1 */
150 0x00, /* 59 DAI1 EQ1 */
151 0x00, /* 5A DAI1 EQ1 */
152 0x00, /* 5B DAI1 EQ1 */
153 0x00, /* 5C DAI1 EQ2 */
154 0x00, /* 5D DAI1 EQ2 */
155 0x00, /* 5E DAI1 EQ2 */
156 0x00, /* 5F DAI1 EQ2 */
157
158 0x00, /* 60 DAI1 EQ2 */
159 0x00, /* 61 DAI1 EQ2 */
160 0x00, /* 62 DAI1 EQ2 */
161 0x00, /* 63 DAI1 EQ2 */
162 0x00, /* 64 DAI1 EQ2 */
163 0x00, /* 65 DAI1 EQ2 */
164 0x00, /* 66 DAI1 EQ3 */
165 0x00, /* 67 DAI1 EQ3 */
166 0x00, /* 68 DAI1 EQ3 */
167 0x00, /* 69 DAI1 EQ3 */
168 0x00, /* 6A DAI1 EQ3 */
169 0x00, /* 6B DAI1 EQ3 */
170 0x00, /* 6C DAI1 EQ3 */
171 0x00, /* 6D DAI1 EQ3 */
172 0x00, /* 6E DAI1 EQ3 */
173 0x00, /* 6F DAI1 EQ3 */
174
175 0x00, /* 70 DAI1 EQ4 */
176 0x00, /* 71 DAI1 EQ4 */
177 0x00, /* 72 DAI1 EQ4 */
178 0x00, /* 73 DAI1 EQ4 */
179 0x00, /* 74 DAI1 EQ4 */
180 0x00, /* 75 DAI1 EQ4 */
181 0x00, /* 76 DAI1 EQ4 */
182 0x00, /* 77 DAI1 EQ4 */
183 0x00, /* 78 DAI1 EQ4 */
184 0x00, /* 79 DAI1 EQ4 */
185 0x00, /* 7A DAI1 EQ5 */
186 0x00, /* 7B DAI1 EQ5 */
187 0x00, /* 7C DAI1 EQ5 */
188 0x00, /* 7D DAI1 EQ5 */
189 0x00, /* 7E DAI1 EQ5 */
190 0x00, /* 7F DAI1 EQ5 */
191
192 0x00, /* 80 DAI1 EQ5 */
193 0x00, /* 81 DAI1 EQ5 */
194 0x00, /* 82 DAI1 EQ5 */
195 0x00, /* 83 DAI1 EQ5 */
196 0x00, /* 84 DAI2 EQ1 */
197 0x00, /* 85 DAI2 EQ1 */
198 0x00, /* 86 DAI2 EQ1 */
199 0x00, /* 87 DAI2 EQ1 */
200 0x00, /* 88 DAI2 EQ1 */
201 0x00, /* 89 DAI2 EQ1 */
202 0x00, /* 8A DAI2 EQ1 */
203 0x00, /* 8B DAI2 EQ1 */
204 0x00, /* 8C DAI2 EQ1 */
205 0x00, /* 8D DAI2 EQ1 */
206 0x00, /* 8E DAI2 EQ2 */
207 0x00, /* 8F DAI2 EQ2 */
208
209 0x00, /* 90 DAI2 EQ2 */
210 0x00, /* 91 DAI2 EQ2 */
211 0x00, /* 92 DAI2 EQ2 */
212 0x00, /* 93 DAI2 EQ2 */
213 0x00, /* 94 DAI2 EQ2 */
214 0x00, /* 95 DAI2 EQ2 */
215 0x00, /* 96 DAI2 EQ2 */
216 0x00, /* 97 DAI2 EQ2 */
217 0x00, /* 98 DAI2 EQ3 */
218 0x00, /* 99 DAI2 EQ3 */
219 0x00, /* 9A DAI2 EQ3 */
220 0x00, /* 9B DAI2 EQ3 */
221 0x00, /* 9C DAI2 EQ3 */
222 0x00, /* 9D DAI2 EQ3 */
223 0x00, /* 9E DAI2 EQ3 */
224 0x00, /* 9F DAI2 EQ3 */
225
226 0x00, /* A0 DAI2 EQ3 */
227 0x00, /* A1 DAI2 EQ3 */
228 0x00, /* A2 DAI2 EQ4 */
229 0x00, /* A3 DAI2 EQ4 */
230 0x00, /* A4 DAI2 EQ4 */
231 0x00, /* A5 DAI2 EQ4 */
232 0x00, /* A6 DAI2 EQ4 */
233 0x00, /* A7 DAI2 EQ4 */
234 0x00, /* A8 DAI2 EQ4 */
235 0x00, /* A9 DAI2 EQ4 */
236 0x00, /* AA DAI2 EQ4 */
237 0x00, /* AB DAI2 EQ4 */
238 0x00, /* AC DAI2 EQ5 */
239 0x00, /* AD DAI2 EQ5 */
240 0x00, /* AE DAI2 EQ5 */
241 0x00, /* AF DAI2 EQ5 */
242
243 0x00, /* B0 DAI2 EQ5 */
244 0x00, /* B1 DAI2 EQ5 */
245 0x00, /* B2 DAI2 EQ5 */
246 0x00, /* B3 DAI2 EQ5 */
247 0x00, /* B4 DAI2 EQ5 */
248 0x00, /* B5 DAI2 EQ5 */
249 0x00, /* B6 DAI1 biquad */
250 0x00, /* B7 DAI1 biquad */
251 0x00, /* B8 DAI1 biquad */
252 0x00, /* B9 DAI1 biquad */
253 0x00, /* BA DAI1 biquad */
254 0x00, /* BB DAI1 biquad */
255 0x00, /* BC DAI1 biquad */
256 0x00, /* BD DAI1 biquad */
257 0x00, /* BE DAI1 biquad */
258 0x00, /* BF DAI1 biquad */
259
260 0x00, /* C0 DAI2 biquad */
261 0x00, /* C1 DAI2 biquad */
262 0x00, /* C2 DAI2 biquad */
263 0x00, /* C3 DAI2 biquad */
264 0x00, /* C4 DAI2 biquad */
265 0x00, /* C5 DAI2 biquad */
266 0x00, /* C6 DAI2 biquad */
267 0x00, /* C7 DAI2 biquad */
268 0x00, /* C8 DAI2 biquad */
269 0x00, /* C9 DAI2 biquad */
270 0x00, /* CA */
271 0x00, /* CB */
272 0x00, /* CC */
273 0x00, /* CD */
274 0x00, /* CE */
275 0x00, /* CF */
276
277 0x00, /* D0 */
278 0x00, /* D1 */
279 0x00, /* D2 */
280 0x00, /* D3 */
281 0x00, /* D4 */
282 0x00, /* D5 */
283 0x00, /* D6 */
284 0x00, /* D7 */
285 0x00, /* D8 */
286 0x00, /* D9 */
287 0x00, /* DA */
288 0x70, /* DB */
289 0x00, /* DC */
290 0x00, /* DD */
291 0x00, /* DE */
292 0x00, /* DF */
293
294 0x00, /* E0 */
295 0x00, /* E1 */
296 0x00, /* E2 */
297 0x00, /* E3 */
298 0x00, /* E4 */
299 0x00, /* E5 */
300 0x00, /* E6 */
301 0x00, /* E7 */
302 0x00, /* E8 */
303 0x00, /* E9 */
304 0x00, /* EA */
305 0x00, /* EB */
306 0x00, /* EC */
307 0x00, /* ED */
308 0x00, /* EE */
309 0x00, /* EF */
310
311 0x00, /* F0 */
312 0x00, /* F1 */
313 0x00, /* F2 */
314 0x00, /* F3 */
315 0x00, /* F4 */
316 0x00, /* F5 */
317 0x00, /* F6 */
318 0x00, /* F7 */
319 0x00, /* F8 */
320 0x00, /* F9 */
321 0x00, /* FA */
322 0x00, /* FB */
323 0x00, /* FC */
324 0x00, /* FD */
325 0x00, /* FE */
326 0x00, /* FF */
327};
328
329static struct {
330 int readable;
331 int writable;
332 int vol;
333} max98088_access[M98088_REG_CNT] = {
334 { 0xFF, 0xFF, 1 }, /* 00 IRQ status */
335 { 0xFF, 0x00, 1 }, /* 01 MIC status */
336 { 0xFF, 0x00, 1 }, /* 02 jack status */
337 { 0x1F, 0x1F, 1 }, /* 03 battery voltage */
338 { 0xFF, 0xFF, 0 }, /* 04 */
339 { 0xFF, 0xFF, 0 }, /* 05 */
340 { 0xFF, 0xFF, 0 }, /* 06 */
341 { 0xFF, 0xFF, 0 }, /* 07 */
342 { 0xFF, 0xFF, 0 }, /* 08 */
343 { 0xFF, 0xFF, 0 }, /* 09 */
344 { 0xFF, 0xFF, 0 }, /* 0A */
345 { 0xFF, 0xFF, 0 }, /* 0B */
346 { 0xFF, 0xFF, 0 }, /* 0C */
347 { 0xFF, 0xFF, 0 }, /* 0D */
348 { 0xFF, 0xFF, 0 }, /* 0E */
349 { 0xFF, 0xFF, 0 }, /* 0F interrupt enable */
350
351 { 0xFF, 0xFF, 0 }, /* 10 master clock */
352 { 0xFF, 0xFF, 0 }, /* 11 DAI1 clock mode */
353 { 0xFF, 0xFF, 0 }, /* 12 DAI1 clock control */
354 { 0xFF, 0xFF, 0 }, /* 13 DAI1 clock control */
355 { 0xFF, 0xFF, 0 }, /* 14 DAI1 format */
356 { 0xFF, 0xFF, 0 }, /* 15 DAI1 clock */
357 { 0xFF, 0xFF, 0 }, /* 16 DAI1 config */
358 { 0xFF, 0xFF, 0 }, /* 17 DAI1 TDM */
359 { 0xFF, 0xFF, 0 }, /* 18 DAI1 filters */
360 { 0xFF, 0xFF, 0 }, /* 19 DAI2 clock mode */
361 { 0xFF, 0xFF, 0 }, /* 1A DAI2 clock control */
362 { 0xFF, 0xFF, 0 }, /* 1B DAI2 clock control */
363 { 0xFF, 0xFF, 0 }, /* 1C DAI2 format */
364 { 0xFF, 0xFF, 0 }, /* 1D DAI2 clock */
365 { 0xFF, 0xFF, 0 }, /* 1E DAI2 config */
366 { 0xFF, 0xFF, 0 }, /* 1F DAI2 TDM */
367
368 { 0xFF, 0xFF, 0 }, /* 20 DAI2 filters */
369 { 0xFF, 0xFF, 0 }, /* 21 data config */
370 { 0xFF, 0xFF, 0 }, /* 22 DAC mixer */
371 { 0xFF, 0xFF, 0 }, /* 23 left ADC mixer */
372 { 0xFF, 0xFF, 0 }, /* 24 right ADC mixer */
373 { 0xFF, 0xFF, 0 }, /* 25 left HP mixer */
374 { 0xFF, 0xFF, 0 }, /* 26 right HP mixer */
375 { 0xFF, 0xFF, 0 }, /* 27 HP control */
376 { 0xFF, 0xFF, 0 }, /* 28 left REC mixer */
377 { 0xFF, 0xFF, 0 }, /* 29 right REC mixer */
378 { 0xFF, 0xFF, 0 }, /* 2A REC control */
379 { 0xFF, 0xFF, 0 }, /* 2B left SPK mixer */
380 { 0xFF, 0xFF, 0 }, /* 2C right SPK mixer */
381 { 0xFF, 0xFF, 0 }, /* 2D SPK control */
382 { 0xFF, 0xFF, 0 }, /* 2E sidetone */
383 { 0xFF, 0xFF, 0 }, /* 2F DAI1 playback level */
384
385 { 0xFF, 0xFF, 0 }, /* 30 DAI1 playback level */
386 { 0xFF, 0xFF, 0 }, /* 31 DAI2 playback level */
387 { 0xFF, 0xFF, 0 }, /* 32 DAI2 playbakc level */
388 { 0xFF, 0xFF, 0 }, /* 33 left ADC level */
389 { 0xFF, 0xFF, 0 }, /* 34 right ADC level */
390 { 0xFF, 0xFF, 0 }, /* 35 MIC1 level */
391 { 0xFF, 0xFF, 0 }, /* 36 MIC2 level */
392 { 0xFF, 0xFF, 0 }, /* 37 INA level */
393 { 0xFF, 0xFF, 0 }, /* 38 INB level */
394 { 0xFF, 0xFF, 0 }, /* 39 left HP volume */
395 { 0xFF, 0xFF, 0 }, /* 3A right HP volume */
396 { 0xFF, 0xFF, 0 }, /* 3B left REC volume */
397 { 0xFF, 0xFF, 0 }, /* 3C right REC volume */
398 { 0xFF, 0xFF, 0 }, /* 3D left SPK volume */
399 { 0xFF, 0xFF, 0 }, /* 3E right SPK volume */
400 { 0xFF, 0xFF, 0 }, /* 3F MIC config */
401
402 { 0xFF, 0xFF, 0 }, /* 40 MIC threshold */
403 { 0xFF, 0xFF, 0 }, /* 41 excursion limiter filter */
404 { 0xFF, 0xFF, 0 }, /* 42 excursion limiter threshold */
405 { 0xFF, 0xFF, 0 }, /* 43 ALC */
406 { 0xFF, 0xFF, 0 }, /* 44 power limiter threshold */
407 { 0xFF, 0xFF, 0 }, /* 45 power limiter config */
408 { 0xFF, 0xFF, 0 }, /* 46 distortion limiter config */
409 { 0xFF, 0xFF, 0 }, /* 47 audio input */
410 { 0xFF, 0xFF, 0 }, /* 48 microphone */
411 { 0xFF, 0xFF, 0 }, /* 49 level control */
412 { 0xFF, 0xFF, 0 }, /* 4A bypass switches */
413 { 0xFF, 0xFF, 0 }, /* 4B jack detect */
414 { 0xFF, 0xFF, 0 }, /* 4C input enable */
415 { 0xFF, 0xFF, 0 }, /* 4D output enable */
416 { 0xFF, 0xFF, 0 }, /* 4E bias control */
417 { 0xFF, 0xFF, 0 }, /* 4F DAC power */
418
419 { 0xFF, 0xFF, 0 }, /* 50 DAC power */
420 { 0xFF, 0xFF, 0 }, /* 51 system */
421 { 0xFF, 0xFF, 0 }, /* 52 DAI1 EQ1 */
422 { 0xFF, 0xFF, 0 }, /* 53 DAI1 EQ1 */
423 { 0xFF, 0xFF, 0 }, /* 54 DAI1 EQ1 */
424 { 0xFF, 0xFF, 0 }, /* 55 DAI1 EQ1 */
425 { 0xFF, 0xFF, 0 }, /* 56 DAI1 EQ1 */
426 { 0xFF, 0xFF, 0 }, /* 57 DAI1 EQ1 */
427 { 0xFF, 0xFF, 0 }, /* 58 DAI1 EQ1 */
428 { 0xFF, 0xFF, 0 }, /* 59 DAI1 EQ1 */
429 { 0xFF, 0xFF, 0 }, /* 5A DAI1 EQ1 */
430 { 0xFF, 0xFF, 0 }, /* 5B DAI1 EQ1 */
431 { 0xFF, 0xFF, 0 }, /* 5C DAI1 EQ2 */
432 { 0xFF, 0xFF, 0 }, /* 5D DAI1 EQ2 */
433 { 0xFF, 0xFF, 0 }, /* 5E DAI1 EQ2 */
434 { 0xFF, 0xFF, 0 }, /* 5F DAI1 EQ2 */
435
436 { 0xFF, 0xFF, 0 }, /* 60 DAI1 EQ2 */
437 { 0xFF, 0xFF, 0 }, /* 61 DAI1 EQ2 */
438 { 0xFF, 0xFF, 0 }, /* 62 DAI1 EQ2 */
439 { 0xFF, 0xFF, 0 }, /* 63 DAI1 EQ2 */
440 { 0xFF, 0xFF, 0 }, /* 64 DAI1 EQ2 */
441 { 0xFF, 0xFF, 0 }, /* 65 DAI1 EQ2 */
442 { 0xFF, 0xFF, 0 }, /* 66 DAI1 EQ3 */
443 { 0xFF, 0xFF, 0 }, /* 67 DAI1 EQ3 */
444 { 0xFF, 0xFF, 0 }, /* 68 DAI1 EQ3 */
445 { 0xFF, 0xFF, 0 }, /* 69 DAI1 EQ3 */
446 { 0xFF, 0xFF, 0 }, /* 6A DAI1 EQ3 */
447 { 0xFF, 0xFF, 0 }, /* 6B DAI1 EQ3 */
448 { 0xFF, 0xFF, 0 }, /* 6C DAI1 EQ3 */
449 { 0xFF, 0xFF, 0 }, /* 6D DAI1 EQ3 */
450 { 0xFF, 0xFF, 0 }, /* 6E DAI1 EQ3 */
451 { 0xFF, 0xFF, 0 }, /* 6F DAI1 EQ3 */
452
453 { 0xFF, 0xFF, 0 }, /* 70 DAI1 EQ4 */
454 { 0xFF, 0xFF, 0 }, /* 71 DAI1 EQ4 */
455 { 0xFF, 0xFF, 0 }, /* 72 DAI1 EQ4 */
456 { 0xFF, 0xFF, 0 }, /* 73 DAI1 EQ4 */
457 { 0xFF, 0xFF, 0 }, /* 74 DAI1 EQ4 */
458 { 0xFF, 0xFF, 0 }, /* 75 DAI1 EQ4 */
459 { 0xFF, 0xFF, 0 }, /* 76 DAI1 EQ4 */
460 { 0xFF, 0xFF, 0 }, /* 77 DAI1 EQ4 */
461 { 0xFF, 0xFF, 0 }, /* 78 DAI1 EQ4 */
462 { 0xFF, 0xFF, 0 }, /* 79 DAI1 EQ4 */
463 { 0xFF, 0xFF, 0 }, /* 7A DAI1 EQ5 */
464 { 0xFF, 0xFF, 0 }, /* 7B DAI1 EQ5 */
465 { 0xFF, 0xFF, 0 }, /* 7C DAI1 EQ5 */
466 { 0xFF, 0xFF, 0 }, /* 7D DAI1 EQ5 */
467 { 0xFF, 0xFF, 0 }, /* 7E DAI1 EQ5 */
468 { 0xFF, 0xFF, 0 }, /* 7F DAI1 EQ5 */
469
470 { 0xFF, 0xFF, 0 }, /* 80 DAI1 EQ5 */
471 { 0xFF, 0xFF, 0 }, /* 81 DAI1 EQ5 */
472 { 0xFF, 0xFF, 0 }, /* 82 DAI1 EQ5 */
473 { 0xFF, 0xFF, 0 }, /* 83 DAI1 EQ5 */
474 { 0xFF, 0xFF, 0 }, /* 84 DAI2 EQ1 */
475 { 0xFF, 0xFF, 0 }, /* 85 DAI2 EQ1 */
476 { 0xFF, 0xFF, 0 }, /* 86 DAI2 EQ1 */
477 { 0xFF, 0xFF, 0 }, /* 87 DAI2 EQ1 */
478 { 0xFF, 0xFF, 0 }, /* 88 DAI2 EQ1 */
479 { 0xFF, 0xFF, 0 }, /* 89 DAI2 EQ1 */
480 { 0xFF, 0xFF, 0 }, /* 8A DAI2 EQ1 */
481 { 0xFF, 0xFF, 0 }, /* 8B DAI2 EQ1 */
482 { 0xFF, 0xFF, 0 }, /* 8C DAI2 EQ1 */
483 { 0xFF, 0xFF, 0 }, /* 8D DAI2 EQ1 */
484 { 0xFF, 0xFF, 0 }, /* 8E DAI2 EQ2 */
485 { 0xFF, 0xFF, 0 }, /* 8F DAI2 EQ2 */
486
487 { 0xFF, 0xFF, 0 }, /* 90 DAI2 EQ2 */
488 { 0xFF, 0xFF, 0 }, /* 91 DAI2 EQ2 */
489 { 0xFF, 0xFF, 0 }, /* 92 DAI2 EQ2 */
490 { 0xFF, 0xFF, 0 }, /* 93 DAI2 EQ2 */
491 { 0xFF, 0xFF, 0 }, /* 94 DAI2 EQ2 */
492 { 0xFF, 0xFF, 0 }, /* 95 DAI2 EQ2 */
493 { 0xFF, 0xFF, 0 }, /* 96 DAI2 EQ2 */
494 { 0xFF, 0xFF, 0 }, /* 97 DAI2 EQ2 */
495 { 0xFF, 0xFF, 0 }, /* 98 DAI2 EQ3 */
496 { 0xFF, 0xFF, 0 }, /* 99 DAI2 EQ3 */
497 { 0xFF, 0xFF, 0 }, /* 9A DAI2 EQ3 */
498 { 0xFF, 0xFF, 0 }, /* 9B DAI2 EQ3 */
499 { 0xFF, 0xFF, 0 }, /* 9C DAI2 EQ3 */
500 { 0xFF, 0xFF, 0 }, /* 9D DAI2 EQ3 */
501 { 0xFF, 0xFF, 0 }, /* 9E DAI2 EQ3 */
502 { 0xFF, 0xFF, 0 }, /* 9F DAI2 EQ3 */
503
504 { 0xFF, 0xFF, 0 }, /* A0 DAI2 EQ3 */
505 { 0xFF, 0xFF, 0 }, /* A1 DAI2 EQ3 */
506 { 0xFF, 0xFF, 0 }, /* A2 DAI2 EQ4 */
507 { 0xFF, 0xFF, 0 }, /* A3 DAI2 EQ4 */
508 { 0xFF, 0xFF, 0 }, /* A4 DAI2 EQ4 */
509 { 0xFF, 0xFF, 0 }, /* A5 DAI2 EQ4 */
510 { 0xFF, 0xFF, 0 }, /* A6 DAI2 EQ4 */
511 { 0xFF, 0xFF, 0 }, /* A7 DAI2 EQ4 */
512 { 0xFF, 0xFF, 0 }, /* A8 DAI2 EQ4 */
513 { 0xFF, 0xFF, 0 }, /* A9 DAI2 EQ4 */
514 { 0xFF, 0xFF, 0 }, /* AA DAI2 EQ4 */
515 { 0xFF, 0xFF, 0 }, /* AB DAI2 EQ4 */
516 { 0xFF, 0xFF, 0 }, /* AC DAI2 EQ5 */
517 { 0xFF, 0xFF, 0 }, /* AD DAI2 EQ5 */
518 { 0xFF, 0xFF, 0 }, /* AE DAI2 EQ5 */
519 { 0xFF, 0xFF, 0 }, /* AF DAI2 EQ5 */
520
521 { 0xFF, 0xFF, 0 }, /* B0 DAI2 EQ5 */
522 { 0xFF, 0xFF, 0 }, /* B1 DAI2 EQ5 */
523 { 0xFF, 0xFF, 0 }, /* B2 DAI2 EQ5 */
524 { 0xFF, 0xFF, 0 }, /* B3 DAI2 EQ5 */
525 { 0xFF, 0xFF, 0 }, /* B4 DAI2 EQ5 */
526 { 0xFF, 0xFF, 0 }, /* B5 DAI2 EQ5 */
527 { 0xFF, 0xFF, 0 }, /* B6 DAI1 biquad */
528 { 0xFF, 0xFF, 0 }, /* B7 DAI1 biquad */
529 { 0xFF, 0xFF, 0 }, /* B8 DAI1 biquad */
530 { 0xFF, 0xFF, 0 }, /* B9 DAI1 biquad */
531 { 0xFF, 0xFF, 0 }, /* BA DAI1 biquad */
532 { 0xFF, 0xFF, 0 }, /* BB DAI1 biquad */
533 { 0xFF, 0xFF, 0 }, /* BC DAI1 biquad */
534 { 0xFF, 0xFF, 0 }, /* BD DAI1 biquad */
535 { 0xFF, 0xFF, 0 }, /* BE DAI1 biquad */
536 { 0xFF, 0xFF, 0 }, /* BF DAI1 biquad */
537
538 { 0xFF, 0xFF, 0 }, /* C0 DAI2 biquad */
539 { 0xFF, 0xFF, 0 }, /* C1 DAI2 biquad */
540 { 0xFF, 0xFF, 0 }, /* C2 DAI2 biquad */
541 { 0xFF, 0xFF, 0 }, /* C3 DAI2 biquad */
542 { 0xFF, 0xFF, 0 }, /* C4 DAI2 biquad */
543 { 0xFF, 0xFF, 0 }, /* C5 DAI2 biquad */
544 { 0xFF, 0xFF, 0 }, /* C6 DAI2 biquad */
545 { 0xFF, 0xFF, 0 }, /* C7 DAI2 biquad */
546 { 0xFF, 0xFF, 0 }, /* C8 DAI2 biquad */
547 { 0xFF, 0xFF, 0 }, /* C9 DAI2 biquad */
548 { 0x00, 0x00, 0 }, /* CA */
549 { 0x00, 0x00, 0 }, /* CB */
550 { 0x00, 0x00, 0 }, /* CC */
551 { 0x00, 0x00, 0 }, /* CD */
552 { 0x00, 0x00, 0 }, /* CE */
553 { 0x00, 0x00, 0 }, /* CF */
554
555 { 0x00, 0x00, 0 }, /* D0 */
556 { 0x00, 0x00, 0 }, /* D1 */
557 { 0x00, 0x00, 0 }, /* D2 */
558 { 0x00, 0x00, 0 }, /* D3 */
559 { 0x00, 0x00, 0 }, /* D4 */
560 { 0x00, 0x00, 0 }, /* D5 */
561 { 0x00, 0x00, 0 }, /* D6 */
562 { 0x00, 0x00, 0 }, /* D7 */
563 { 0x00, 0x00, 0 }, /* D8 */
564 { 0x00, 0x00, 0 }, /* D9 */
565 { 0x00, 0x00, 0 }, /* DA */
566 { 0x00, 0x00, 0 }, /* DB */
567 { 0x00, 0x00, 0 }, /* DC */
568 { 0x00, 0x00, 0 }, /* DD */
569 { 0x00, 0x00, 0 }, /* DE */
570 { 0x00, 0x00, 0 }, /* DF */
571
572 { 0x00, 0x00, 0 }, /* E0 */
573 { 0x00, 0x00, 0 }, /* E1 */
574 { 0x00, 0x00, 0 }, /* E2 */
575 { 0x00, 0x00, 0 }, /* E3 */
576 { 0x00, 0x00, 0 }, /* E4 */
577 { 0x00, 0x00, 0 }, /* E5 */
578 { 0x00, 0x00, 0 }, /* E6 */
579 { 0x00, 0x00, 0 }, /* E7 */
580 { 0x00, 0x00, 0 }, /* E8 */
581 { 0x00, 0x00, 0 }, /* E9 */
582 { 0x00, 0x00, 0 }, /* EA */
583 { 0x00, 0x00, 0 }, /* EB */
584 { 0x00, 0x00, 0 }, /* EC */
585 { 0x00, 0x00, 0 }, /* ED */
586 { 0x00, 0x00, 0 }, /* EE */
587 { 0x00, 0x00, 0 }, /* EF */
588
589 { 0x00, 0x00, 0 }, /* F0 */
590 { 0x00, 0x00, 0 }, /* F1 */
591 { 0x00, 0x00, 0 }, /* F2 */
592 { 0x00, 0x00, 0 }, /* F3 */
593 { 0x00, 0x00, 0 }, /* F4 */
594 { 0x00, 0x00, 0 }, /* F5 */
595 { 0x00, 0x00, 0 }, /* F6 */
596 { 0x00, 0x00, 0 }, /* F7 */
597 { 0x00, 0x00, 0 }, /* F8 */
598 { 0x00, 0x00, 0 }, /* F9 */
599 { 0x00, 0x00, 0 }, /* FA */
600 { 0x00, 0x00, 0 }, /* FB */
601 { 0x00, 0x00, 0 }, /* FC */
602 { 0x00, 0x00, 0 }, /* FD */
603 { 0x00, 0x00, 0 }, /* FE */
604 { 0xFF, 0x00, 1 }, /* FF */
605};
606
607static int max98088_volatile_register(unsigned int reg)
608{
609 return max98088_access[reg].vol;
610}
611
612
613/*
614 * Load equalizer DSP coefficient configurations registers
615 */
616static void m98088_eq_band(struct snd_soc_codec *codec, unsigned int dai,
617 unsigned int band, u16 *coefs)
618{
619 unsigned int eq_reg;
620 unsigned int i;
621
622 BUG_ON(band > 4);
623 BUG_ON(dai > 1);
624
625 /* Load the base register address */
626 eq_reg = dai ? M98088_REG_84_DAI2_EQ_BASE : M98088_REG_52_DAI1_EQ_BASE;
627
628 /* Add the band address offset, note adjustment for word address */
629 eq_reg += band * (M98088_COEFS_PER_BAND << 1);
630
631 /* Step through the registers and coefs */
632 for (i = 0; i < M98088_COEFS_PER_BAND; i++) {
633 snd_soc_write(codec, eq_reg++, M98088_BYTE1(coefs[i]));
634 snd_soc_write(codec, eq_reg++, M98088_BYTE0(coefs[i]));
635 }
636}
637
638/*
639 * Excursion limiter modes
640 */
641static const char *max98088_exmode_texts[] = {
642 "Off", "100Hz", "400Hz", "600Hz", "800Hz", "1000Hz", "200-400Hz",
643 "400-600Hz", "400-800Hz",
644};
645
646static const unsigned int max98088_exmode_values[] = {
647 0x00, 0x43, 0x10, 0x20, 0x30, 0x40, 0x11, 0x22, 0x32
648};
649
650static const struct soc_enum max98088_exmode_enum =
651 SOC_VALUE_ENUM_SINGLE(M98088_REG_41_SPKDHP, 0, 127,
652 ARRAY_SIZE(max98088_exmode_texts),
653 max98088_exmode_texts,
654 max98088_exmode_values);
655static const struct snd_kcontrol_new max98088_exmode_controls =
656 SOC_DAPM_VALUE_ENUM("Route", max98088_exmode_enum);
657
658static const char *max98088_ex_thresh[] = { /* volts PP */
659 "0.6", "1.2", "1.8", "2.4", "3.0", "3.6", "4.2", "4.8"};
660static const struct soc_enum max98088_ex_thresh_enum[] = {
661 SOC_ENUM_SINGLE(M98088_REG_42_SPKDHP_THRESH, 0, 8,
662 max98088_ex_thresh),
663};
664
665static const char *max98088_fltr_mode[] = {"Voice", "Music" };
666static const struct soc_enum max98088_filter_mode_enum[] = {
667 SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 7, 2, max98088_fltr_mode),
668};
669
670static const char *max98088_extmic_text[] = { "None", "MIC1", "MIC2" };
671
672static const struct soc_enum max98088_extmic_enum =
673 SOC_ENUM_SINGLE(M98088_REG_48_CFG_MIC, 0, 3, max98088_extmic_text);
674
675static const struct snd_kcontrol_new max98088_extmic_mux =
676 SOC_DAPM_ENUM("External MIC Mux", max98088_extmic_enum);
677
678static const char *max98088_dai1_fltr[] = {
679 "Off", "fc=258/fs=16k", "fc=500/fs=16k",
680 "fc=258/fs=8k", "fc=500/fs=8k", "fc=200"};
681static const struct soc_enum max98088_dai1_dac_filter_enum[] = {
682 SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 0, 6, max98088_dai1_fltr),
683};
684static const struct soc_enum max98088_dai1_adc_filter_enum[] = {
685 SOC_ENUM_SINGLE(M98088_REG_18_DAI1_FILTERS, 4, 6, max98088_dai1_fltr),
686};
687
688static int max98088_mic1pre_set(struct snd_kcontrol *kcontrol,
689 struct snd_ctl_elem_value *ucontrol)
690{
691 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
692 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
693 unsigned int sel = ucontrol->value.integer.value[0];
694
695 max98088->mic1pre = sel;
696 snd_soc_update_bits(codec, M98088_REG_35_LVL_MIC1, M98088_MICPRE_MASK,
697 (1+sel)<<M98088_MICPRE_SHIFT);
698
699 return 0;
700}
701
702static int max98088_mic1pre_get(struct snd_kcontrol *kcontrol,
703 struct snd_ctl_elem_value *ucontrol)
704{
705 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
706 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
707
708 ucontrol->value.integer.value[0] = max98088->mic1pre;
709 return 0;
710}
711
712static int max98088_mic2pre_set(struct snd_kcontrol *kcontrol,
713 struct snd_ctl_elem_value *ucontrol)
714{
715 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
716 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
717 unsigned int sel = ucontrol->value.integer.value[0];
718
719 max98088->mic2pre = sel;
720 snd_soc_update_bits(codec, M98088_REG_36_LVL_MIC2, M98088_MICPRE_MASK,
721 (1+sel)<<M98088_MICPRE_SHIFT);
722
723 return 0;
724}
725
726static int max98088_mic2pre_get(struct snd_kcontrol *kcontrol,
727 struct snd_ctl_elem_value *ucontrol)
728{
729 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
730 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
731
732 ucontrol->value.integer.value[0] = max98088->mic2pre;
733 return 0;
734}
735
736static const unsigned int max98088_micboost_tlv[] = {
737 TLV_DB_RANGE_HEAD(2),
738 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
739 2, 2, TLV_DB_SCALE_ITEM(3000, 0, 0),
740};
741
742static const struct snd_kcontrol_new max98088_snd_controls[] = {
743
744 SOC_DOUBLE_R("Headphone Volume", M98088_REG_39_LVL_HP_L,
745 M98088_REG_3A_LVL_HP_R, 0, 31, 0),
746 SOC_DOUBLE_R("Speaker Volume", M98088_REG_3D_LVL_SPK_L,
747 M98088_REG_3E_LVL_SPK_R, 0, 31, 0),
748 SOC_DOUBLE_R("Receiver Volume", M98088_REG_3B_LVL_REC_L,
749 M98088_REG_3C_LVL_REC_R, 0, 31, 0),
750
751 SOC_DOUBLE_R("Headphone Switch", M98088_REG_39_LVL_HP_L,
752 M98088_REG_3A_LVL_HP_R, 7, 1, 1),
753 SOC_DOUBLE_R("Speaker Switch", M98088_REG_3D_LVL_SPK_L,
754 M98088_REG_3E_LVL_SPK_R, 7, 1, 1),
755 SOC_DOUBLE_R("Receiver Switch", M98088_REG_3B_LVL_REC_L,
756 M98088_REG_3C_LVL_REC_R, 7, 1, 1),
757
758 SOC_SINGLE("MIC1 Volume", M98088_REG_35_LVL_MIC1, 0, 31, 1),
759 SOC_SINGLE("MIC2 Volume", M98088_REG_36_LVL_MIC2, 0, 31, 1),
760
761 SOC_SINGLE_EXT_TLV("MIC1 Boost Volume",
762 M98088_REG_35_LVL_MIC1, 5, 2, 0,
763 max98088_mic1pre_get, max98088_mic1pre_set,
764 max98088_micboost_tlv),
765 SOC_SINGLE_EXT_TLV("MIC2 Boost Volume",
766 M98088_REG_36_LVL_MIC2, 5, 2, 0,
767 max98088_mic2pre_get, max98088_mic2pre_set,
768 max98088_micboost_tlv),
769
770 SOC_SINGLE("INA Volume", M98088_REG_37_LVL_INA, 0, 7, 1),
771 SOC_SINGLE("INB Volume", M98088_REG_38_LVL_INB, 0, 7, 1),
772
773 SOC_SINGLE("ADCL Volume", M98088_REG_33_LVL_ADC_L, 0, 15, 0),
774 SOC_SINGLE("ADCR Volume", M98088_REG_34_LVL_ADC_R, 0, 15, 0),
775
776 SOC_SINGLE("ADCL Boost Volume", M98088_REG_33_LVL_ADC_L, 4, 3, 0),
777 SOC_SINGLE("ADCR Boost Volume", M98088_REG_34_LVL_ADC_R, 4, 3, 0),
778
779 SOC_SINGLE("EQ1 Switch", M98088_REG_49_CFG_LEVEL, 0, 1, 0),
780 SOC_SINGLE("EQ2 Switch", M98088_REG_49_CFG_LEVEL, 1, 1, 0),
781
782 SOC_ENUM("EX Limiter Threshold", max98088_ex_thresh_enum),
783
784 SOC_ENUM("DAI1 Filter Mode", max98088_filter_mode_enum),
785 SOC_ENUM("DAI1 DAC Filter", max98088_dai1_dac_filter_enum),
786 SOC_ENUM("DAI1 ADC Filter", max98088_dai1_adc_filter_enum),
787 SOC_SINGLE("DAI2 DC Block Switch", M98088_REG_20_DAI2_FILTERS,
788 0, 1, 0),
789
790 SOC_SINGLE("ALC Switch", M98088_REG_43_SPKALC_COMP, 7, 1, 0),
791 SOC_SINGLE("ALC Threshold", M98088_REG_43_SPKALC_COMP, 0, 7, 0),
792 SOC_SINGLE("ALC Multiband", M98088_REG_43_SPKALC_COMP, 3, 1, 0),
793 SOC_SINGLE("ALC Release Time", M98088_REG_43_SPKALC_COMP, 4, 7, 0),
794
795 SOC_SINGLE("PWR Limiter Threshold", M98088_REG_44_PWRLMT_CFG,
796 4, 15, 0),
797 SOC_SINGLE("PWR Limiter Weight", M98088_REG_44_PWRLMT_CFG, 0, 7, 0),
798 SOC_SINGLE("PWR Limiter Time1", M98088_REG_45_PWRLMT_TIME, 0, 15, 0),
799 SOC_SINGLE("PWR Limiter Time2", M98088_REG_45_PWRLMT_TIME, 4, 15, 0),
800
801 SOC_SINGLE("THD Limiter Threshold", M98088_REG_46_THDLMT_CFG, 4, 15, 0),
802 SOC_SINGLE("THD Limiter Time", M98088_REG_46_THDLMT_CFG, 0, 7, 0),
803};
804
805/* Left speaker mixer switch */
806static const struct snd_kcontrol_new max98088_left_speaker_mixer_controls[] = {
807 SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
808 SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
809 SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 7, 1, 0),
810 SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 0, 1, 0),
811 SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 5, 1, 0),
812 SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 6, 1, 0),
813 SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 1, 1, 0),
814 SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 2, 1, 0),
815 SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2B_MIX_SPK_LEFT, 3, 1, 0),
816 SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2B_MIX_SPK_LEFT, 4, 1, 0),
817};
818
819/* Right speaker mixer switch */
820static const struct snd_kcontrol_new max98088_right_speaker_mixer_controls[] = {
821 SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
822 SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
823 SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 7, 1, 0),
824 SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 0, 1, 0),
825 SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 5, 1, 0),
826 SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 6, 1, 0),
827 SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 1, 1, 0),
828 SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 2, 1, 0),
829 SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 3, 1, 0),
830 SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_2C_MIX_SPK_RIGHT, 4, 1, 0),
831};
832
833/* Left headphone mixer switch */
834static const struct snd_kcontrol_new max98088_left_hp_mixer_controls[] = {
835 SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
836 SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
837 SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 7, 1, 0),
838 SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_25_MIX_HP_LEFT, 0, 1, 0),
839 SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_25_MIX_HP_LEFT, 5, 1, 0),
840 SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_25_MIX_HP_LEFT, 6, 1, 0),
841 SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_25_MIX_HP_LEFT, 1, 1, 0),
842 SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_25_MIX_HP_LEFT, 2, 1, 0),
843 SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_25_MIX_HP_LEFT, 3, 1, 0),
844 SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_25_MIX_HP_LEFT, 4, 1, 0),
845};
846
847/* Right headphone mixer switch */
848static const struct snd_kcontrol_new max98088_right_hp_mixer_controls[] = {
849 SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
850 SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
851 SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 7, 1, 0),
852 SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 0, 1, 0),
853 SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_26_MIX_HP_RIGHT, 5, 1, 0),
854 SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_26_MIX_HP_RIGHT, 6, 1, 0),
855 SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_26_MIX_HP_RIGHT, 1, 1, 0),
856 SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_26_MIX_HP_RIGHT, 2, 1, 0),
857 SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_26_MIX_HP_RIGHT, 3, 1, 0),
858 SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_26_MIX_HP_RIGHT, 4, 1, 0),
859};
860
861/* Left earpiece/receiver mixer switch */
862static const struct snd_kcontrol_new max98088_left_rec_mixer_controls[] = {
863 SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
864 SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
865 SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 7, 1, 0),
866 SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_28_MIX_REC_LEFT, 0, 1, 0),
867 SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_28_MIX_REC_LEFT, 5, 1, 0),
868 SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_28_MIX_REC_LEFT, 6, 1, 0),
869 SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_28_MIX_REC_LEFT, 1, 1, 0),
870 SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_28_MIX_REC_LEFT, 2, 1, 0),
871 SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_28_MIX_REC_LEFT, 3, 1, 0),
872 SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_28_MIX_REC_LEFT, 4, 1, 0),
873};
874
875/* Right earpiece/receiver mixer switch */
876static const struct snd_kcontrol_new max98088_right_rec_mixer_controls[] = {
877 SOC_DAPM_SINGLE("Left DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
878 SOC_DAPM_SINGLE("Right DAC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
879 SOC_DAPM_SINGLE("Left DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 7, 1, 0),
880 SOC_DAPM_SINGLE("Right DAC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 0, 1, 0),
881 SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_29_MIX_REC_RIGHT, 5, 1, 0),
882 SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_29_MIX_REC_RIGHT, 6, 1, 0),
883 SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_29_MIX_REC_RIGHT, 1, 1, 0),
884 SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_29_MIX_REC_RIGHT, 2, 1, 0),
885 SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_29_MIX_REC_RIGHT, 3, 1, 0),
886 SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_29_MIX_REC_RIGHT, 4, 1, 0),
887};
888
889/* Left ADC mixer switch */
890static const struct snd_kcontrol_new max98088_left_ADC_mixer_controls[] = {
891 SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_23_MIX_ADC_LEFT, 7, 1, 0),
892 SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_23_MIX_ADC_LEFT, 6, 1, 0),
893 SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_23_MIX_ADC_LEFT, 3, 1, 0),
894 SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_23_MIX_ADC_LEFT, 2, 1, 0),
895 SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_23_MIX_ADC_LEFT, 1, 1, 0),
896 SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_23_MIX_ADC_LEFT, 0, 1, 0),
897};
898
899/* Right ADC mixer switch */
900static const struct snd_kcontrol_new max98088_right_ADC_mixer_controls[] = {
901 SOC_DAPM_SINGLE("MIC1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 7, 1, 0),
902 SOC_DAPM_SINGLE("MIC2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 6, 1, 0),
903 SOC_DAPM_SINGLE("INA1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 3, 1, 0),
904 SOC_DAPM_SINGLE("INA2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 2, 1, 0),
905 SOC_DAPM_SINGLE("INB1 Switch", M98088_REG_24_MIX_ADC_RIGHT, 1, 1, 0),
906 SOC_DAPM_SINGLE("INB2 Switch", M98088_REG_24_MIX_ADC_RIGHT, 0, 1, 0),
907};
908
909static int max98088_mic_event(struct snd_soc_dapm_widget *w,
910 struct snd_kcontrol *kcontrol, int event)
911{
912 struct snd_soc_codec *codec = w->codec;
913 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
914
915 switch (event) {
916 case SND_SOC_DAPM_POST_PMU:
917 if (w->reg == M98088_REG_35_LVL_MIC1) {
918 snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK,
919 (1+max98088->mic1pre)<<M98088_MICPRE_SHIFT);
920 } else {
921 snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK,
922 (1+max98088->mic2pre)<<M98088_MICPRE_SHIFT);
923 }
924 break;
925 case SND_SOC_DAPM_POST_PMD:
926 snd_soc_update_bits(codec, w->reg, M98088_MICPRE_MASK, 0);
927 break;
928 default:
929 return -EINVAL;
930 }
931
932 return 0;
933}
934
935/*
936 * The line inputs are 2-channel stereo inputs with the left
937 * and right channels sharing a common PGA power control signal.
938 */
939static int max98088_line_pga(struct snd_soc_dapm_widget *w,
940 int event, int line, u8 channel)
941{
942 struct snd_soc_codec *codec = w->codec;
943 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
944 u8 *state;
945
946 BUG_ON(!((channel == 1) || (channel == 2)));
947
948 switch (line) {
949 case LINE_INA:
950 state = &max98088->ina_state;
951 break;
952 case LINE_INB:
953 state = &max98088->inb_state;
954 break;
955 default:
956 return -EINVAL;
957 }
958
959 switch (event) {
960 case SND_SOC_DAPM_POST_PMU:
961 *state |= channel;
962 snd_soc_update_bits(codec, w->reg,
963 (1 << w->shift), (1 << w->shift));
964 break;
965 case SND_SOC_DAPM_POST_PMD:
966 *state &= ~channel;
967 if (*state == 0) {
968 snd_soc_update_bits(codec, w->reg,
969 (1 << w->shift), 0);
970 }
971 break;
972 default:
973 return -EINVAL;
974 }
975
976 return 0;
977}
978
979static int max98088_pga_ina1_event(struct snd_soc_dapm_widget *w,
980 struct snd_kcontrol *k, int event)
981{
982 return max98088_line_pga(w, event, LINE_INA, 1);
983}
984
985static int max98088_pga_ina2_event(struct snd_soc_dapm_widget *w,
986 struct snd_kcontrol *k, int event)
987{
988 return max98088_line_pga(w, event, LINE_INA, 2);
989}
990
991static int max98088_pga_inb1_event(struct snd_soc_dapm_widget *w,
992 struct snd_kcontrol *k, int event)
993{
994 return max98088_line_pga(w, event, LINE_INB, 1);
995}
996
997static int max98088_pga_inb2_event(struct snd_soc_dapm_widget *w,
998 struct snd_kcontrol *k, int event)
999{
1000 return max98088_line_pga(w, event, LINE_INB, 2);
1001}
1002
1003static const struct snd_soc_dapm_widget max98088_dapm_widgets[] = {
1004
1005 SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 1, 0),
1006 SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", M98088_REG_4C_PWR_EN_IN, 0, 0),
1007
1008 SND_SOC_DAPM_DAC("DACL1", "HiFi Playback",
1009 M98088_REG_4D_PWR_EN_OUT, 1, 0),
1010 SND_SOC_DAPM_DAC("DACR1", "HiFi Playback",
1011 M98088_REG_4D_PWR_EN_OUT, 0, 0),
1012 SND_SOC_DAPM_DAC("DACL2", "Aux Playback",
1013 M98088_REG_4D_PWR_EN_OUT, 1, 0),
1014 SND_SOC_DAPM_DAC("DACR2", "Aux Playback",
1015 M98088_REG_4D_PWR_EN_OUT, 0, 0),
1016
1017 SND_SOC_DAPM_PGA("HP Left Out", M98088_REG_4D_PWR_EN_OUT,
1018 7, 0, NULL, 0),
1019 SND_SOC_DAPM_PGA("HP Right Out", M98088_REG_4D_PWR_EN_OUT,
1020 6, 0, NULL, 0),
1021
1022 SND_SOC_DAPM_PGA("SPK Left Out", M98088_REG_4D_PWR_EN_OUT,
1023 5, 0, NULL, 0),
1024 SND_SOC_DAPM_PGA("SPK Right Out", M98088_REG_4D_PWR_EN_OUT,
1025 4, 0, NULL, 0),
1026
1027 SND_SOC_DAPM_PGA("REC Left Out", M98088_REG_4D_PWR_EN_OUT,
1028 3, 0, NULL, 0),
1029 SND_SOC_DAPM_PGA("REC Right Out", M98088_REG_4D_PWR_EN_OUT,
1030 2, 0, NULL, 0),
1031
1032 SND_SOC_DAPM_MUX("External MIC", SND_SOC_NOPM, 0, 0,
1033 &max98088_extmic_mux),
1034
1035 SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
1036 &max98088_left_hp_mixer_controls[0],
1037 ARRAY_SIZE(max98088_left_hp_mixer_controls)),
1038
1039 SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0,
1040 &max98088_right_hp_mixer_controls[0],
1041 ARRAY_SIZE(max98088_right_hp_mixer_controls)),
1042
1043 SND_SOC_DAPM_MIXER("Left SPK Mixer", SND_SOC_NOPM, 0, 0,
1044 &max98088_left_speaker_mixer_controls[0],
1045 ARRAY_SIZE(max98088_left_speaker_mixer_controls)),
1046
1047 SND_SOC_DAPM_MIXER("Right SPK Mixer", SND_SOC_NOPM, 0, 0,
1048 &max98088_right_speaker_mixer_controls[0],
1049 ARRAY_SIZE(max98088_right_speaker_mixer_controls)),
1050
1051 SND_SOC_DAPM_MIXER("Left REC Mixer", SND_SOC_NOPM, 0, 0,
1052 &max98088_left_rec_mixer_controls[0],
1053 ARRAY_SIZE(max98088_left_rec_mixer_controls)),
1054
1055 SND_SOC_DAPM_MIXER("Right REC Mixer", SND_SOC_NOPM, 0, 0,
1056 &max98088_right_rec_mixer_controls[0],
1057 ARRAY_SIZE(max98088_right_rec_mixer_controls)),
1058
1059 SND_SOC_DAPM_MIXER("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
1060 &max98088_left_ADC_mixer_controls[0],
1061 ARRAY_SIZE(max98088_left_ADC_mixer_controls)),
1062
1063 SND_SOC_DAPM_MIXER("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
1064 &max98088_right_ADC_mixer_controls[0],
1065 ARRAY_SIZE(max98088_right_ADC_mixer_controls)),
1066
1067 SND_SOC_DAPM_PGA_E("MIC1 Input", M98088_REG_35_LVL_MIC1,
1068 5, 0, NULL, 0, max98088_mic_event,
1069 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1070
1071 SND_SOC_DAPM_PGA_E("MIC2 Input", M98088_REG_36_LVL_MIC2,
1072 5, 0, NULL, 0, max98088_mic_event,
1073 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1074
1075 SND_SOC_DAPM_PGA_E("INA1 Input", M98088_REG_4C_PWR_EN_IN,
1076 7, 0, NULL, 0, max98088_pga_ina1_event,
1077 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1078
1079 SND_SOC_DAPM_PGA_E("INA2 Input", M98088_REG_4C_PWR_EN_IN,
1080 7, 0, NULL, 0, max98088_pga_ina2_event,
1081 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1082
1083 SND_SOC_DAPM_PGA_E("INB1 Input", M98088_REG_4C_PWR_EN_IN,
1084 6, 0, NULL, 0, max98088_pga_inb1_event,
1085 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1086
1087 SND_SOC_DAPM_PGA_E("INB2 Input", M98088_REG_4C_PWR_EN_IN,
1088 6, 0, NULL, 0, max98088_pga_inb2_event,
1089 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
1090
1091 SND_SOC_DAPM_MICBIAS("MICBIAS", M98088_REG_4C_PWR_EN_IN, 3, 0),
1092
1093 SND_SOC_DAPM_MUX("EX Limiter Mode", SND_SOC_NOPM, 0, 0,
1094 &max98088_exmode_controls),
1095
1096 SND_SOC_DAPM_OUTPUT("HPL"),
1097 SND_SOC_DAPM_OUTPUT("HPR"),
1098 SND_SOC_DAPM_OUTPUT("SPKL"),
1099 SND_SOC_DAPM_OUTPUT("SPKR"),
1100 SND_SOC_DAPM_OUTPUT("RECL"),
1101 SND_SOC_DAPM_OUTPUT("RECR"),
1102
1103 SND_SOC_DAPM_INPUT("MIC1"),
1104 SND_SOC_DAPM_INPUT("MIC2"),
1105 SND_SOC_DAPM_INPUT("INA1"),
1106 SND_SOC_DAPM_INPUT("INA2"),
1107 SND_SOC_DAPM_INPUT("INB1"),
1108 SND_SOC_DAPM_INPUT("INB2"),
1109};
1110
1111static const struct snd_soc_dapm_route audio_map[] = {
1112 /* Left headphone output mixer */
1113 {"Left HP Mixer", "Left DAC1 Switch", "DACL1"},
1114 {"Left HP Mixer", "Left DAC2 Switch", "DACL2"},
1115 {"Left HP Mixer", "Right DAC1 Switch", "DACR1"},
1116 {"Left HP Mixer", "Right DAC2 Switch", "DACR2"},
1117 {"Left HP Mixer", "MIC1 Switch", "MIC1 Input"},
1118 {"Left HP Mixer", "MIC2 Switch", "MIC2 Input"},
1119 {"Left HP Mixer", "INA1 Switch", "INA1 Input"},
1120 {"Left HP Mixer", "INA2 Switch", "INA2 Input"},
1121 {"Left HP Mixer", "INB1 Switch", "INB1 Input"},
1122 {"Left HP Mixer", "INB2 Switch", "INB2 Input"},
1123
1124 /* Right headphone output mixer */
1125 {"Right HP Mixer", "Left DAC1 Switch", "DACL1"},
1126 {"Right HP Mixer", "Left DAC2 Switch", "DACL2" },
1127 {"Right HP Mixer", "Right DAC1 Switch", "DACR1"},
1128 {"Right HP Mixer", "Right DAC2 Switch", "DACR2"},
1129 {"Right HP Mixer", "MIC1 Switch", "MIC1 Input"},
1130 {"Right HP Mixer", "MIC2 Switch", "MIC2 Input"},
1131 {"Right HP Mixer", "INA1 Switch", "INA1 Input"},
1132 {"Right HP Mixer", "INA2 Switch", "INA2 Input"},
1133 {"Right HP Mixer", "INB1 Switch", "INB1 Input"},
1134 {"Right HP Mixer", "INB2 Switch", "INB2 Input"},
1135
1136 /* Left speaker output mixer */
1137 {"Left SPK Mixer", "Left DAC1 Switch", "DACL1"},
1138 {"Left SPK Mixer", "Left DAC2 Switch", "DACL2"},
1139 {"Left SPK Mixer", "Right DAC1 Switch", "DACR1"},
1140 {"Left SPK Mixer", "Right DAC2 Switch", "DACR2"},
1141 {"Left SPK Mixer", "MIC1 Switch", "MIC1 Input"},
1142 {"Left SPK Mixer", "MIC2 Switch", "MIC2 Input"},
1143 {"Left SPK Mixer", "INA1 Switch", "INA1 Input"},
1144 {"Left SPK Mixer", "INA2 Switch", "INA2 Input"},
1145 {"Left SPK Mixer", "INB1 Switch", "INB1 Input"},
1146 {"Left SPK Mixer", "INB2 Switch", "INB2 Input"},
1147
1148 /* Right speaker output mixer */
1149 {"Right SPK Mixer", "Left DAC1 Switch", "DACL1"},
1150 {"Right SPK Mixer", "Left DAC2 Switch", "DACL2"},
1151 {"Right SPK Mixer", "Right DAC1 Switch", "DACR1"},
1152 {"Right SPK Mixer", "Right DAC2 Switch", "DACR2"},
1153 {"Right SPK Mixer", "MIC1 Switch", "MIC1 Input"},
1154 {"Right SPK Mixer", "MIC2 Switch", "MIC2 Input"},
1155 {"Right SPK Mixer", "INA1 Switch", "INA1 Input"},
1156 {"Right SPK Mixer", "INA2 Switch", "INA2 Input"},
1157 {"Right SPK Mixer", "INB1 Switch", "INB1 Input"},
1158 {"Right SPK Mixer", "INB2 Switch", "INB2 Input"},
1159
1160 /* Earpiece/Receiver output mixer */
1161 {"Left REC Mixer", "Left DAC1 Switch", "DACL1"},
1162 {"Left REC Mixer", "Left DAC2 Switch", "DACL2"},
1163 {"Left REC Mixer", "Right DAC1 Switch", "DACR1"},
1164 {"Left REC Mixer", "Right DAC2 Switch", "DACR2"},
1165 {"Left REC Mixer", "MIC1 Switch", "MIC1 Input"},
1166 {"Left REC Mixer", "MIC2 Switch", "MIC2 Input"},
1167 {"Left REC Mixer", "INA1 Switch", "INA1 Input"},
1168 {"Left REC Mixer", "INA2 Switch", "INA2 Input"},
1169 {"Left REC Mixer", "INB1 Switch", "INB1 Input"},
1170 {"Left REC Mixer", "INB2 Switch", "INB2 Input"},
1171
1172 /* Earpiece/Receiver output mixer */
1173 {"Right REC Mixer", "Left DAC1 Switch", "DACL1"},
1174 {"Right REC Mixer", "Left DAC2 Switch", "DACL2"},
1175 {"Right REC Mixer", "Right DAC1 Switch", "DACR1"},
1176 {"Right REC Mixer", "Right DAC2 Switch", "DACR2"},
1177 {"Right REC Mixer", "MIC1 Switch", "MIC1 Input"},
1178 {"Right REC Mixer", "MIC2 Switch", "MIC2 Input"},
1179 {"Right REC Mixer", "INA1 Switch", "INA1 Input"},
1180 {"Right REC Mixer", "INA2 Switch", "INA2 Input"},
1181 {"Right REC Mixer", "INB1 Switch", "INB1 Input"},
1182 {"Right REC Mixer", "INB2 Switch", "INB2 Input"},
1183
1184 {"HP Left Out", NULL, "Left HP Mixer"},
1185 {"HP Right Out", NULL, "Right HP Mixer"},
1186 {"SPK Left Out", NULL, "Left SPK Mixer"},
1187 {"SPK Right Out", NULL, "Right SPK Mixer"},
1188 {"REC Left Out", NULL, "Left REC Mixer"},
1189 {"REC Right Out", NULL, "Right REC Mixer"},
1190
1191 {"HPL", NULL, "HP Left Out"},
1192 {"HPR", NULL, "HP Right Out"},
1193 {"SPKL", NULL, "SPK Left Out"},
1194 {"SPKR", NULL, "SPK Right Out"},
1195 {"RECL", NULL, "REC Left Out"},
1196 {"RECR", NULL, "REC Right Out"},
1197
1198 /* Left ADC input mixer */
1199 {"Left ADC Mixer", "MIC1 Switch", "MIC1 Input"},
1200 {"Left ADC Mixer", "MIC2 Switch", "MIC2 Input"},
1201 {"Left ADC Mixer", "INA1 Switch", "INA1 Input"},
1202 {"Left ADC Mixer", "INA2 Switch", "INA2 Input"},
1203 {"Left ADC Mixer", "INB1 Switch", "INB1 Input"},
1204 {"Left ADC Mixer", "INB2 Switch", "INB2 Input"},
1205
1206 /* Right ADC input mixer */
1207 {"Right ADC Mixer", "MIC1 Switch", "MIC1 Input"},
1208 {"Right ADC Mixer", "MIC2 Switch", "MIC2 Input"},
1209 {"Right ADC Mixer", "INA1 Switch", "INA1 Input"},
1210 {"Right ADC Mixer", "INA2 Switch", "INA2 Input"},
1211 {"Right ADC Mixer", "INB1 Switch", "INB1 Input"},
1212 {"Right ADC Mixer", "INB2 Switch", "INB2 Input"},
1213
1214 /* Inputs */
1215 {"ADCL", NULL, "Left ADC Mixer"},
1216 {"ADCR", NULL, "Right ADC Mixer"},
1217 {"INA1 Input", NULL, "INA1"},
1218 {"INA2 Input", NULL, "INA2"},
1219 {"INB1 Input", NULL, "INB1"},
1220 {"INB2 Input", NULL, "INB2"},
1221 {"MIC1 Input", NULL, "MIC1"},
1222 {"MIC2 Input", NULL, "MIC2"},
1223};
1224
1225static int max98088_add_widgets(struct snd_soc_codec *codec)
1226{
1227 snd_soc_dapm_new_controls(codec, max98088_dapm_widgets,
1228 ARRAY_SIZE(max98088_dapm_widgets));
1229
1230 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
1231
1232 snd_soc_add_controls(codec, max98088_snd_controls,
1233 ARRAY_SIZE(max98088_snd_controls));
1234
1235 snd_soc_dapm_new_widgets(codec);
1236 return 0;
1237}
1238
1239/* codec mclk clock divider coefficients */
1240static const struct {
1241 u32 rate;
1242 u8 sr;
1243} rate_table[] = {
1244 {8000, 0x10},
1245 {11025, 0x20},
1246 {16000, 0x30},
1247 {22050, 0x40},
1248 {24000, 0x50},
1249 {32000, 0x60},
1250 {44100, 0x70},
1251 {48000, 0x80},
1252 {88200, 0x90},
1253 {96000, 0xA0},
1254};
1255
1256static inline int rate_value(int rate, u8 *value)
1257{
1258 int i;
1259
1260 for (i = 0; i < ARRAY_SIZE(rate_table); i++) {
1261 if (rate_table[i].rate >= rate) {
1262 *value = rate_table[i].sr;
1263 return 0;
1264 }
1265 }
1266 *value = rate_table[0].sr;
1267 return -EINVAL;
1268}
1269
1270static int max98088_dai1_hw_params(struct snd_pcm_substream *substream,
1271 struct snd_pcm_hw_params *params,
1272 struct snd_soc_dai *dai)
1273{
1274 struct snd_soc_codec *codec = dai->codec;
1275 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1276 struct max98088_cdata *cdata;
1277 unsigned long long ni;
1278 unsigned int rate;
1279 u8 regval;
1280
1281 cdata = &max98088->dai[0];
1282
1283 rate = params_rate(params);
1284
1285 switch (params_format(params)) {
1286 case SNDRV_PCM_FORMAT_S16_LE:
1287 snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
1288 M98088_DAI_WS, 0);
1289 break;
1290 case SNDRV_PCM_FORMAT_S24_LE:
1291 snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
1292 M98088_DAI_WS, M98088_DAI_WS);
1293 break;
1294 default:
1295 return -EINVAL;
1296 }
1297
1298 snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0);
1299
1300 if (rate_value(rate, &regval))
1301 return -EINVAL;
1302
1303 snd_soc_update_bits(codec, M98088_REG_11_DAI1_CLKMODE,
1304 M98088_CLKMODE_MASK, regval);
1305 cdata->rate = rate;
1306
1307 /* Configure NI when operating as master */
1308 if (snd_soc_read(codec, M98088_REG_14_DAI1_FORMAT)
1309 & M98088_DAI_MAS) {
1310 if (max98088->sysclk == 0) {
1311 dev_err(codec->dev, "Invalid system clock frequency\n");
1312 return -EINVAL;
1313 }
1314 ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
1315 * (unsigned long long int)rate;
1316 do_div(ni, (unsigned long long int)max98088->sysclk);
1317 snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI,
1318 (ni >> 8) & 0x7F);
1319 snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO,
1320 ni & 0xFF);
1321 }
1322
1323 /* Update sample rate mode */
1324 if (rate < 50000)
1325 snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS,
1326 M98088_DAI_DHF, 0);
1327 else
1328 snd_soc_update_bits(codec, M98088_REG_18_DAI1_FILTERS,
1329 M98088_DAI_DHF, M98088_DAI_DHF);
1330
1331 snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN,
1332 M98088_SHDNRUN);
1333
1334 return 0;
1335}
1336
1337static int max98088_dai2_hw_params(struct snd_pcm_substream *substream,
1338 struct snd_pcm_hw_params *params,
1339 struct snd_soc_dai *dai)
1340{
1341 struct snd_soc_codec *codec = dai->codec;
1342 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1343 struct max98088_cdata *cdata;
1344 unsigned long long ni;
1345 unsigned int rate;
1346 u8 regval;
1347
1348 cdata = &max98088->dai[1];
1349
1350 rate = params_rate(params);
1351
1352 switch (params_format(params)) {
1353 case SNDRV_PCM_FORMAT_S16_LE:
1354 snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
1355 M98088_DAI_WS, 0);
1356 break;
1357 case SNDRV_PCM_FORMAT_S24_LE:
1358 snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
1359 M98088_DAI_WS, M98088_DAI_WS);
1360 break;
1361 default:
1362 return -EINVAL;
1363 }
1364
1365 snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN, 0);
1366
1367 if (rate_value(rate, &regval))
1368 return -EINVAL;
1369
1370 snd_soc_update_bits(codec, M98088_REG_19_DAI2_CLKMODE,
1371 M98088_CLKMODE_MASK, regval);
1372 cdata->rate = rate;
1373
1374 /* Configure NI when operating as master */
1375 if (snd_soc_read(codec, M98088_REG_1C_DAI2_FORMAT)
1376 & M98088_DAI_MAS) {
1377 if (max98088->sysclk == 0) {
1378 dev_err(codec->dev, "Invalid system clock frequency\n");
1379 return -EINVAL;
1380 }
1381 ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
1382 * (unsigned long long int)rate;
1383 do_div(ni, (unsigned long long int)max98088->sysclk);
1384 snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI,
1385 (ni >> 8) & 0x7F);
1386 snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO,
1387 ni & 0xFF);
1388 }
1389
1390 /* Update sample rate mode */
1391 if (rate < 50000)
1392 snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS,
1393 M98088_DAI_DHF, 0);
1394 else
1395 snd_soc_update_bits(codec, M98088_REG_20_DAI2_FILTERS,
1396 M98088_DAI_DHF, M98088_DAI_DHF);
1397
1398 snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS, M98088_SHDNRUN,
1399 M98088_SHDNRUN);
1400
1401 return 0;
1402}
1403
1404static int max98088_dai_set_sysclk(struct snd_soc_dai *dai,
1405 int clk_id, unsigned int freq, int dir)
1406{
1407 struct snd_soc_codec *codec = dai->codec;
1408 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1409
1410 /* Requested clock frequency is already setup */
1411 if (freq == max98088->sysclk)
1412 return 0;
1413
1414 max98088->sysclk = freq; /* remember current sysclk */
1415
1416 /* Setup clocks for slave mode, and using the PLL
1417 * PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
1418 * 0x02 (when master clk is 20MHz to 30MHz)..
1419 */
1420 if ((freq >= 10000000) && (freq < 20000000)) {
1421 snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x10);
1422 } else if ((freq >= 20000000) && (freq < 30000000)) {
1423 snd_soc_write(codec, M98088_REG_10_SYS_CLK, 0x20);
1424 } else {
1425 dev_err(codec->dev, "Invalid master clock frequency\n");
1426 return -EINVAL;
1427 }
1428
1429 if (snd_soc_read(codec, M98088_REG_51_PWR_SYS) & M98088_SHDNRUN) {
1430 snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS,
1431 M98088_SHDNRUN, 0);
1432 snd_soc_update_bits(codec, M98088_REG_51_PWR_SYS,
1433 M98088_SHDNRUN, M98088_SHDNRUN);
1434 }
1435
1436 dev_dbg(dai->dev, "Clock source is %d at %uHz\n", clk_id, freq);
1437
1438 max98088->sysclk = freq;
1439 return 0;
1440}
1441
1442static int max98088_dai1_set_fmt(struct snd_soc_dai *codec_dai,
1443 unsigned int fmt)
1444{
1445 struct snd_soc_codec *codec = codec_dai->codec;
1446 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1447 struct max98088_cdata *cdata;
1448 u8 reg15val;
1449 u8 reg14val = 0;
1450
1451 cdata = &max98088->dai[0];
1452
1453 if (fmt != cdata->fmt) {
1454 cdata->fmt = fmt;
1455
1456 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1457 case SND_SOC_DAIFMT_CBS_CFS:
1458 /* Slave mode PLL */
1459 snd_soc_write(codec, M98088_REG_12_DAI1_CLKCFG_HI,
1460 0x80);
1461 snd_soc_write(codec, M98088_REG_13_DAI1_CLKCFG_LO,
1462 0x00);
1463 break;
1464 case SND_SOC_DAIFMT_CBM_CFM:
1465 /* Set to master mode */
1466 reg14val |= M98088_DAI_MAS;
1467 break;
1468 case SND_SOC_DAIFMT_CBS_CFM:
1469 case SND_SOC_DAIFMT_CBM_CFS:
1470 default:
1471 dev_err(codec->dev, "Clock mode unsupported");
1472 return -EINVAL;
1473 }
1474
1475 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1476 case SND_SOC_DAIFMT_I2S:
1477 reg14val |= M98088_DAI_DLY;
1478 break;
1479 case SND_SOC_DAIFMT_LEFT_J:
1480 break;
1481 default:
1482 return -EINVAL;
1483 }
1484
1485 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1486 case SND_SOC_DAIFMT_NB_NF:
1487 break;
1488 case SND_SOC_DAIFMT_NB_IF:
1489 reg14val |= M98088_DAI_WCI;
1490 break;
1491 case SND_SOC_DAIFMT_IB_NF:
1492 reg14val |= M98088_DAI_BCI;
1493 break;
1494 case SND_SOC_DAIFMT_IB_IF:
1495 reg14val |= M98088_DAI_BCI|M98088_DAI_WCI;
1496 break;
1497 default:
1498 return -EINVAL;
1499 }
1500
1501 snd_soc_update_bits(codec, M98088_REG_14_DAI1_FORMAT,
1502 M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI |
1503 M98088_DAI_WCI, reg14val);
1504
1505 reg15val = M98088_DAI_BSEL64;
1506 if (max98088->digmic)
1507 reg15val |= M98088_DAI_OSR64;
1508 snd_soc_write(codec, M98088_REG_15_DAI1_CLOCK, reg15val);
1509 }
1510
1511 return 0;
1512}
1513
1514static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai,
1515 unsigned int fmt)
1516{
1517 struct snd_soc_codec *codec = codec_dai->codec;
1518 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1519 struct max98088_cdata *cdata;
1520 u8 reg1Cval = 0;
1521
1522 cdata = &max98088->dai[1];
1523
1524 if (fmt != cdata->fmt) {
1525 cdata->fmt = fmt;
1526
1527 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1528 case SND_SOC_DAIFMT_CBS_CFS:
1529 /* Slave mode PLL */
1530 snd_soc_write(codec, M98088_REG_1A_DAI2_CLKCFG_HI,
1531 0x80);
1532 snd_soc_write(codec, M98088_REG_1B_DAI2_CLKCFG_LO,
1533 0x00);
1534 break;
1535 case SND_SOC_DAIFMT_CBM_CFM:
1536 /* Set to master mode */
1537 reg1Cval |= M98088_DAI_MAS;
1538 break;
1539 case SND_SOC_DAIFMT_CBS_CFM:
1540 case SND_SOC_DAIFMT_CBM_CFS:
1541 default:
1542 dev_err(codec->dev, "Clock mode unsupported");
1543 return -EINVAL;
1544 }
1545
1546 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
1547 case SND_SOC_DAIFMT_I2S:
1548 reg1Cval |= M98088_DAI_DLY;
1549 break;
1550 case SND_SOC_DAIFMT_LEFT_J:
1551 break;
1552 default:
1553 return -EINVAL;
1554 }
1555
1556 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
1557 case SND_SOC_DAIFMT_NB_NF:
1558 break;
1559 case SND_SOC_DAIFMT_NB_IF:
1560 reg1Cval |= M98088_DAI_WCI;
1561 break;
1562 case SND_SOC_DAIFMT_IB_NF:
1563 reg1Cval |= M98088_DAI_BCI;
1564 break;
1565 case SND_SOC_DAIFMT_IB_IF:
1566 reg1Cval |= M98088_DAI_BCI|M98088_DAI_WCI;
1567 break;
1568 default:
1569 return -EINVAL;
1570 }
1571
1572 snd_soc_update_bits(codec, M98088_REG_1C_DAI2_FORMAT,
1573 M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI |
1574 M98088_DAI_WCI, reg1Cval);
1575
1576 snd_soc_write(codec, M98088_REG_1D_DAI2_CLOCK,
1577 M98088_DAI_BSEL64);
1578 }
1579
1580 return 0;
1581}
1582
1583static void max98088_sync_cache(struct snd_soc_codec *codec)
1584{
1585 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1586 int i;
1587
1588 if (!codec->cache_sync)
1589 return;
1590
1591 codec->cache_only = 0;
1592
1593 /* write back cached values if they're writeable and
1594 * different from the hardware default.
1595 */
1596 for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) {
1597 if (!max98088_access[i].writable)
1598 continue;
1599
1600 if (max98088->reg_cache[i] == max98088_reg[i])
1601 continue;
1602
1603 snd_soc_write(codec, i, max98088->reg_cache[i]);
1604 }
1605
1606 codec->cache_sync = 0;
1607}
1608
1609static int max98088_set_bias_level(struct snd_soc_codec *codec,
1610 enum snd_soc_bias_level level)
1611{
1612 switch (level) {
1613 case SND_SOC_BIAS_ON:
1614 break;
1615
1616 case SND_SOC_BIAS_PREPARE:
1617 break;
1618
1619 case SND_SOC_BIAS_STANDBY:
1620 if (codec->bias_level == SND_SOC_BIAS_OFF)
1621 max98088_sync_cache(codec);
1622
1623 snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
1624 M98088_MBEN, M98088_MBEN);
1625 break;
1626
1627 case SND_SOC_BIAS_OFF:
1628 snd_soc_update_bits(codec, M98088_REG_4C_PWR_EN_IN,
1629 M98088_MBEN, 0);
1630 codec->cache_sync = 1;
1631 break;
1632 }
1633 codec->bias_level = level;
1634 return 0;
1635}
1636
1637#define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
1638#define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
1639
1640static struct snd_soc_dai_ops max98088_dai1_ops = {
1641 .set_sysclk = max98088_dai_set_sysclk,
1642 .set_fmt = max98088_dai1_set_fmt,
1643 .hw_params = max98088_dai1_hw_params,
1644};
1645
1646static struct snd_soc_dai_ops max98088_dai2_ops = {
1647 .set_sysclk = max98088_dai_set_sysclk,
1648 .set_fmt = max98088_dai2_set_fmt,
1649 .hw_params = max98088_dai2_hw_params,
1650};
1651
1652static struct snd_soc_dai_driver max98088_dai[] = {
1653{
1654 .name = "HiFi",
1655 .playback = {
1656 .stream_name = "HiFi Playback",
1657 .channels_min = 1,
1658 .channels_max = 2,
1659 .rates = MAX98088_RATES,
1660 .formats = MAX98088_FORMATS,
1661 },
1662 .capture = {
1663 .stream_name = "HiFi Capture",
1664 .channels_min = 1,
1665 .channels_max = 2,
1666 .rates = MAX98088_RATES,
1667 .formats = MAX98088_FORMATS,
1668 },
1669 .ops = &max98088_dai1_ops,
1670},
1671{
1672 .name = "Aux",
1673 .playback = {
1674 .stream_name = "Aux Playback",
1675 .channels_min = 1,
1676 .channels_max = 2,
1677 .rates = MAX98088_RATES,
1678 .formats = MAX98088_FORMATS,
1679 },
1680 .ops = &max98088_dai2_ops,
1681}
1682};
1683
1684static int max98088_get_channel(const char *name)
1685{
1686 if (strcmp(name, "EQ1 Mode") == 0)
1687 return 0;
1688 if (strcmp(name, "EQ2 Mode") == 0)
1689 return 1;
1690 return -EINVAL;
1691}
1692
1693static void max98088_setup_eq1(struct snd_soc_codec *codec)
1694{
1695 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1696 struct max98088_pdata *pdata = max98088->pdata;
1697 struct max98088_eq_cfg *coef_set;
1698 int best, best_val, save, i, sel, fs;
1699 struct max98088_cdata *cdata;
1700
1701 cdata = &max98088->dai[0];
1702
1703 if (!pdata || !max98088->eq_textcnt)
1704 return;
1705
1706 /* Find the selected configuration with nearest sample rate */
1707 fs = cdata->rate;
1708 sel = cdata->eq_sel;
1709
1710 best = 0;
1711 best_val = INT_MAX;
1712 for (i = 0; i < pdata->eq_cfgcnt; i++) {
1713 if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 &&
1714 abs(pdata->eq_cfg[i].rate - fs) < best_val) {
1715 best = i;
1716 best_val = abs(pdata->eq_cfg[i].rate - fs);
1717 }
1718 }
1719
1720 dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n",
1721 pdata->eq_cfg[best].name,
1722 pdata->eq_cfg[best].rate, fs);
1723
1724 /* Disable EQ while configuring, and save current on/off state */
1725 save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL);
1726 snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, 0);
1727
1728 coef_set = &pdata->eq_cfg[sel];
1729
1730 m98088_eq_band(codec, 0, 0, coef_set->band1);
1731 m98088_eq_band(codec, 0, 1, coef_set->band2);
1732 m98088_eq_band(codec, 0, 2, coef_set->band3);
1733 m98088_eq_band(codec, 0, 3, coef_set->band4);
1734 m98088_eq_band(codec, 0, 4, coef_set->band5);
1735
1736 /* Restore the original on/off state */
1737 snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ1EN, save);
1738}
1739
1740static void max98088_setup_eq2(struct snd_soc_codec *codec)
1741{
1742 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1743 struct max98088_pdata *pdata = max98088->pdata;
1744 struct max98088_eq_cfg *coef_set;
1745 int best, best_val, save, i, sel, fs;
1746 struct max98088_cdata *cdata;
1747
1748 cdata = &max98088->dai[1];
1749
1750 if (!pdata || !max98088->eq_textcnt)
1751 return;
1752
1753 /* Find the selected configuration with nearest sample rate */
1754 fs = cdata->rate;
1755
1756 sel = cdata->eq_sel;
1757 best = 0;
1758 best_val = INT_MAX;
1759 for (i = 0; i < pdata->eq_cfgcnt; i++) {
1760 if (strcmp(pdata->eq_cfg[i].name, max98088->eq_texts[sel]) == 0 &&
1761 abs(pdata->eq_cfg[i].rate - fs) < best_val) {
1762 best = i;
1763 best_val = abs(pdata->eq_cfg[i].rate - fs);
1764 }
1765 }
1766
1767 dev_dbg(codec->dev, "Selected %s/%dHz for %dHz sample rate\n",
1768 pdata->eq_cfg[best].name,
1769 pdata->eq_cfg[best].rate, fs);
1770
1771 /* Disable EQ while configuring, and save current on/off state */
1772 save = snd_soc_read(codec, M98088_REG_49_CFG_LEVEL);
1773 snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN, 0);
1774
1775 coef_set = &pdata->eq_cfg[sel];
1776
1777 m98088_eq_band(codec, 1, 0, coef_set->band1);
1778 m98088_eq_band(codec, 1, 1, coef_set->band2);
1779 m98088_eq_band(codec, 1, 2, coef_set->band3);
1780 m98088_eq_band(codec, 1, 3, coef_set->band4);
1781 m98088_eq_band(codec, 1, 4, coef_set->band5);
1782
1783 /* Restore the original on/off state */
1784 snd_soc_update_bits(codec, M98088_REG_49_CFG_LEVEL, M98088_EQ2EN,
1785 save);
1786}
1787
1788static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
1789 struct snd_ctl_elem_value *ucontrol)
1790{
1791 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1792 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1793 struct max98088_pdata *pdata = max98088->pdata;
1794 int channel = max98088_get_channel(kcontrol->id.name);
1795 struct max98088_cdata *cdata;
1796 int sel = ucontrol->value.integer.value[0];
1797
1798 cdata = &max98088->dai[channel];
1799
1800 if (sel >= pdata->eq_cfgcnt)
1801 return -EINVAL;
1802
1803 cdata->eq_sel = sel;
1804
1805 switch (channel) {
1806 case 0:
1807 max98088_setup_eq1(codec);
1808 break;
1809 case 1:
1810 max98088_setup_eq2(codec);
1811 break;
1812 }
1813
1814 return 0;
1815}
1816
1817static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
1818 struct snd_ctl_elem_value *ucontrol)
1819{
1820 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1821 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1822 int channel = max98088_get_channel(kcontrol->id.name);
1823 struct max98088_cdata *cdata;
1824
1825 cdata = &max98088->dai[channel];
1826 ucontrol->value.enumerated.item[0] = cdata->eq_sel;
1827 return 0;
1828}
1829
1830static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
1831{
1832 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1833 struct max98088_pdata *pdata = max98088->pdata;
1834 struct max98088_eq_cfg *cfg;
1835 unsigned int cfgcnt;
1836 int i, j;
1837 const char **t;
1838 int ret;
1839
1840 struct snd_kcontrol_new controls[] = {
1841 SOC_ENUM_EXT("EQ1 Mode",
1842 max98088->eq_enum,
1843 max98088_get_eq_enum,
1844 max98088_put_eq_enum),
1845 SOC_ENUM_EXT("EQ2 Mode",
1846 max98088->eq_enum,
1847 max98088_get_eq_enum,
1848 max98088_put_eq_enum),
1849 };
1850
1851 cfg = pdata->eq_cfg;
1852 cfgcnt = pdata->eq_cfgcnt;
1853
1854 /* Setup an array of texts for the equalizer enum.
1855 * This is based on Mark Brown's equalizer driver code.
1856 */
1857 max98088->eq_textcnt = 0;
1858 max98088->eq_texts = NULL;
1859 for (i = 0; i < cfgcnt; i++) {
1860 for (j = 0; j < max98088->eq_textcnt; j++) {
1861 if (strcmp(cfg[i].name, max98088->eq_texts[j]) == 0)
1862 break;
1863 }
1864
1865 if (j != max98088->eq_textcnt)
1866 continue;
1867
1868 /* Expand the array */
1869 t = krealloc(max98088->eq_texts,
1870 sizeof(char *) * (max98088->eq_textcnt + 1),
1871 GFP_KERNEL);
1872 if (t == NULL)
1873 continue;
1874
1875 /* Store the new entry */
1876 t[max98088->eq_textcnt] = cfg[i].name;
1877 max98088->eq_textcnt++;
1878 max98088->eq_texts = t;
1879 }
1880
1881 /* Now point the soc_enum to .texts array items */
1882 max98088->eq_enum.texts = max98088->eq_texts;
1883 max98088->eq_enum.max = max98088->eq_textcnt;
1884
1885 ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
1886 if (ret != 0)
1887 dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
1888}
1889
1890static void max98088_handle_pdata(struct snd_soc_codec *codec)
1891{
1892 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1893 struct max98088_pdata *pdata = max98088->pdata;
1894 u8 regval = 0;
1895
1896 if (!pdata) {
1897 dev_dbg(codec->dev, "No platform data\n");
1898 return;
1899 }
1900
1901 /* Configure mic for analog/digital mic mode */
1902 if (pdata->digmic_left_mode)
1903 regval |= M98088_DIGMIC_L;
1904
1905 if (pdata->digmic_right_mode)
1906 regval |= M98088_DIGMIC_R;
1907
1908 max98088->digmic = (regval ? 1 : 0);
1909
1910 snd_soc_write(codec, M98088_REG_48_CFG_MIC, regval);
1911
1912 /* Configure receiver output */
1913 regval = ((pdata->receiver_mode) ? M98088_REC_LINEMODE : 0);
1914 snd_soc_update_bits(codec, M98088_REG_2A_MIC_REC_CNTL,
1915 M98088_REC_LINEMODE_MASK, regval);
1916
1917 /* Configure equalizers */
1918 if (pdata->eq_cfgcnt)
1919 max98088_handle_eq_pdata(codec);
1920}
1921
1922#ifdef CONFIG_PM
1923static int max98088_suspend(struct snd_soc_codec *codec, pm_message_t state)
1924{
1925 max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
1926
1927 return 0;
1928}
1929
1930static int max98088_resume(struct snd_soc_codec *codec)
1931{
1932 max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1933
1934 return 0;
1935}
1936#else
1937#define max98088_suspend NULL
1938#define max98088_resume NULL
1939#endif
1940
1941static int max98088_probe(struct snd_soc_codec *codec)
1942{
1943 struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
1944 struct max98088_cdata *cdata;
1945 int ret = 0;
1946
1947 codec->cache_sync = 1;
1948 memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));
1949
1950 ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
1951 if (ret != 0) {
1952 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1953 return ret;
1954 }
1955
1956 /* initalize private data */
1957
1958 max98088->sysclk = (unsigned)-1;
1959 max98088->eq_textcnt = 0;
1960
1961 cdata = &max98088->dai[0];
1962 cdata->rate = (unsigned)-1;
1963 cdata->fmt = (unsigned)-1;
1964 cdata->eq_sel = 0;
1965
1966 cdata = &max98088->dai[1];
1967 cdata->rate = (unsigned)-1;
1968 cdata->fmt = (unsigned)-1;
1969 cdata->eq_sel = 0;
1970
1971 max98088->ina_state = 0;
1972 max98088->inb_state = 0;
1973 max98088->ex_mode = 0;
1974 max98088->digmic = 0;
1975 max98088->mic1pre = 0;
1976 max98088->mic2pre = 0;
1977
1978 ret = snd_soc_read(codec, M98088_REG_FF_REV_ID);
1979 if (ret < 0) {
1980 dev_err(codec->dev, "Failed to read device revision: %d\n",
1981 ret);
1982 goto err_access;
1983 }
1984 dev_info(codec->dev, "revision %c\n", ret + 'A');
1985
1986 snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV);
1987
1988 /* initialize registers cache to hardware default */
1989 max98088_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1990
1991 snd_soc_write(codec, M98088_REG_0F_IRQ_ENABLE, 0x00);
1992
1993 snd_soc_write(codec, M98088_REG_22_MIX_DAC,
1994 M98088_DAI1L_TO_DACL|M98088_DAI2L_TO_DACL|
1995 M98088_DAI1R_TO_DACR|M98088_DAI2R_TO_DACR);
1996
1997 snd_soc_write(codec, M98088_REG_4E_BIAS_CNTL, 0xF0);
1998 snd_soc_write(codec, M98088_REG_50_DAC_BIAS2, 0x0F);
1999
2000 snd_soc_write(codec, M98088_REG_16_DAI1_IOCFG,
2001 M98088_S1NORMAL|M98088_SDATA);
2002
2003 snd_soc_write(codec, M98088_REG_1E_DAI2_IOCFG,
2004 M98088_S2NORMAL|M98088_SDATA);
2005
2006 max98088_handle_pdata(codec);
2007
2008 max98088_add_widgets(codec);
2009
2010err_access:
2011 return ret;
2012}
2013
2014static int max98088_remove(struct snd_soc_codec *codec)
2015{
2016 max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
2017
2018 return 0;
2019}
2020
2021static struct snd_soc_codec_driver soc_codec_dev_max98088 = {
2022 .probe = max98088_probe,
2023 .remove = max98088_remove,
2024 .suspend = max98088_suspend,
2025 .resume = max98088_resume,
2026 .set_bias_level = max98088_set_bias_level,
2027 .reg_cache_size = ARRAY_SIZE(max98088_reg),
2028 .reg_word_size = sizeof(u8),
2029 .reg_cache_default = max98088_reg,
2030 .volatile_register = max98088_volatile_register,
2031};
2032
2033static int max98088_i2c_probe(struct i2c_client *i2c,
2034 const struct i2c_device_id *id)
2035{
2036 struct max98088_priv *max98088;
2037 int ret;
2038
2039 max98088 = kzalloc(sizeof(struct max98088_priv), GFP_KERNEL);
2040 if (max98088 == NULL)
2041 return -ENOMEM;
2042
2043 i2c_set_clientdata(i2c, max98088);
2044 max98088->control_data = i2c;
2045 max98088->pdata = i2c->dev.platform_data;
2046
2047 ret = snd_soc_register_codec(&i2c->dev,
2048 &soc_codec_dev_max98088, &max98088_dai[0], 2);
2049 if (ret < 0)
2050 kfree(max98088);
2051 return ret;
2052}
2053
2054static int max98088_i2c_remove(struct i2c_client *client)
2055{
2056 snd_soc_unregister_codec(&client->dev);
2057 kfree(i2c_get_clientdata(client));
2058 return 0;
2059}
2060
2061static const struct i2c_device_id max98088_i2c_id[] = {
2062 { "max98088", 0 },
2063 { }
2064};
2065MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
2066
2067static struct i2c_driver max98088_i2c_driver = {
2068 .driver = {
2069 .name = "max98088",
2070 .owner = THIS_MODULE,
2071 },
2072 .probe = max98088_i2c_probe,
2073 .remove = __devexit_p(max98088_i2c_remove),
2074 .id_table = max98088_i2c_id,
2075};
2076
2077static int __init max98088_init(void)
2078{
2079 int ret;
2080
2081 ret = i2c_add_driver(&max98088_i2c_driver);
2082 if (ret)
2083 pr_err("Failed to register max98088 I2C driver: %d\n", ret);
2084
2085 return ret;
2086}
2087module_init(max98088_init);
2088
2089static void __exit max98088_exit(void)
2090{
2091 i2c_del_driver(&max98088_i2c_driver);
2092}
2093module_exit(max98088_exit);
2094
2095MODULE_DESCRIPTION("ALSA SoC MAX98088 driver");
2096MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin");
2097MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/max98088.h b/sound/soc/codecs/max98088.h
new file mode 100644
index 000000000000..56554c797fef
--- /dev/null
+++ b/sound/soc/codecs/max98088.h
@@ -0,0 +1,193 @@
1/*
2 * max98088.h -- MAX98088 ALSA SoC Audio driver
3 *
4 * Copyright 2010 Maxim Integrated Products
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef _MAX98088_H
12#define _MAX98088_H
13
14/*
15 * MAX98088 Registers Definition
16 */
17#define M98088_REG_00_IRQ_STATUS 0x00
18#define M98088_REG_01_MIC_STATUS 0x01
19#define M98088_REG_02_JACK_STAUS 0x02
20#define M98088_REG_03_BATTERY_VOLTAGE 0x03
21#define M98088_REG_0F_IRQ_ENABLE 0x0F
22#define M98088_REG_10_SYS_CLK 0x10
23#define M98088_REG_11_DAI1_CLKMODE 0x11
24#define M98088_REG_12_DAI1_CLKCFG_HI 0x12
25#define M98088_REG_13_DAI1_CLKCFG_LO 0x13
26#define M98088_REG_14_DAI1_FORMAT 0x14
27#define M98088_REG_15_DAI1_CLOCK 0x15
28#define M98088_REG_16_DAI1_IOCFG 0x16
29#define M98088_REG_17_DAI1_TDM 0x17
30#define M98088_REG_18_DAI1_FILTERS 0x18
31#define M98088_REG_19_DAI2_CLKMODE 0x19
32#define M98088_REG_1A_DAI2_CLKCFG_HI 0x1A
33#define M98088_REG_1B_DAI2_CLKCFG_LO 0x1B
34#define M98088_REG_1C_DAI2_FORMAT 0x1C
35#define M98088_REG_1D_DAI2_CLOCK 0x1D
36#define M98088_REG_1E_DAI2_IOCFG 0x1E
37#define M98088_REG_1F_DAI2_TDM 0x1F
38#define M98088_REG_20_DAI2_FILTERS 0x20
39#define M98088_REG_21_SRC 0x21
40#define M98088_REG_22_MIX_DAC 0x22
41#define M98088_REG_23_MIX_ADC_LEFT 0x23
42#define M98088_REG_24_MIX_ADC_RIGHT 0x24
43#define M98088_REG_25_MIX_HP_LEFT 0x25
44#define M98088_REG_26_MIX_HP_RIGHT 0x26
45#define M98088_REG_27_MIX_HP_CNTL 0x27
46#define M98088_REG_28_MIX_REC_LEFT 0x28
47#define M98088_REG_29_MIX_REC_RIGHT 0x29
48#define M98088_REG_2A_MIC_REC_CNTL 0x2A
49#define M98088_REG_2B_MIX_SPK_LEFT 0x2B
50#define M98088_REG_2C_MIX_SPK_RIGHT 0x2C
51#define M98088_REG_2D_MIX_SPK_CNTL 0x2D
52#define M98088_REG_2E_LVL_SIDETONE 0x2E
53#define M98088_REG_2F_LVL_DAI1_PLAY 0x2F
54#define M98088_REG_30_LVL_DAI1_PLAY_EQ 0x30
55#define M98088_REG_31_LVL_DAI2_PLAY 0x31
56#define M98088_REG_32_LVL_DAI2_PLAY_EQ 0x32
57#define M98088_REG_33_LVL_ADC_L 0x33
58#define M98088_REG_34_LVL_ADC_R 0x34
59#define M98088_REG_35_LVL_MIC1 0x35
60#define M98088_REG_36_LVL_MIC2 0x36
61#define M98088_REG_37_LVL_INA 0x37
62#define M98088_REG_38_LVL_INB 0x38
63#define M98088_REG_39_LVL_HP_L 0x39
64#define M98088_REG_3A_LVL_HP_R 0x3A
65#define M98088_REG_3B_LVL_REC_L 0x3B
66#define M98088_REG_3C_LVL_REC_R 0x3C
67#define M98088_REG_3D_LVL_SPK_L 0x3D
68#define M98088_REG_3E_LVL_SPK_R 0x3E
69#define M98088_REG_3F_MICAGC_CFG 0x3F
70#define M98088_REG_40_MICAGC_THRESH 0x40
71#define M98088_REG_41_SPKDHP 0x41
72#define M98088_REG_42_SPKDHP_THRESH 0x42
73#define M98088_REG_43_SPKALC_COMP 0x43
74#define M98088_REG_44_PWRLMT_CFG 0x44
75#define M98088_REG_45_PWRLMT_TIME 0x45
76#define M98088_REG_46_THDLMT_CFG 0x46
77#define M98088_REG_47_CFG_AUDIO_IN 0x47
78#define M98088_REG_48_CFG_MIC 0x48
79#define M98088_REG_49_CFG_LEVEL 0x49
80#define M98088_REG_4A_CFG_BYPASS 0x4A
81#define M98088_REG_4B_CFG_JACKDET 0x4B
82#define M98088_REG_4C_PWR_EN_IN 0x4C
83#define M98088_REG_4D_PWR_EN_OUT 0x4D
84#define M98088_REG_4E_BIAS_CNTL 0x4E
85#define M98088_REG_4F_DAC_BIAS1 0x4F
86#define M98088_REG_50_DAC_BIAS2 0x50
87#define M98088_REG_51_PWR_SYS 0x51
88#define M98088_REG_52_DAI1_EQ_BASE 0x52
89#define M98088_REG_84_DAI2_EQ_BASE 0x84
90#define M98088_REG_B6_DAI1_BIQUAD_BASE 0xB6
91#define M98088_REG_C0_DAI2_BIQUAD_BASE 0xC0
92#define M98088_REG_FF_REV_ID 0xFF
93
94#define M98088_REG_CNT (0xFF+1)
95
96/* MAX98088 Registers Bit Fields */
97
98/* M98088_REG_11_DAI1_CLKMODE, M98088_REG_19_DAI2_CLKMODE */
99 #define M98088_CLKMODE_MASK 0xFF
100
101/* M98088_REG_14_DAI1_FORMAT, M98088_REG_1C_DAI2_FORMAT */
102 #define M98088_DAI_MAS (1<<7)
103 #define M98088_DAI_WCI (1<<6)
104 #define M98088_DAI_BCI (1<<5)
105 #define M98088_DAI_DLY (1<<4)
106 #define M98088_DAI_TDM (1<<2)
107 #define M98088_DAI_FSW (1<<1)
108 #define M98088_DAI_WS (1<<0)
109
110/* M98088_REG_15_DAI1_CLOCK, M98088_REG_1D_DAI2_CLOCK */
111 #define M98088_DAI_BSEL64 (1<<0)
112 #define M98088_DAI_OSR64 (1<<6)
113
114/* M98088_REG_16_DAI1_IOCFG, M98088_REG_1E_DAI2_IOCFG */
115 #define M98088_S1NORMAL (1<<6)
116 #define M98088_S2NORMAL (2<<6)
117 #define M98088_SDATA (3<<0)
118
119/* M98088_REG_18_DAI1_FILTERS, M98088_REG_20_DAI2_FILTERS */
120 #define M98088_DAI_DHF (1<<3)
121
122/* M98088_REG_22_MIX_DAC */
123 #define M98088_DAI1L_TO_DACL (1<<7)
124 #define M98088_DAI1R_TO_DACL (1<<6)
125 #define M98088_DAI2L_TO_DACL (1<<5)
126 #define M98088_DAI2R_TO_DACL (1<<4)
127 #define M98088_DAI1L_TO_DACR (1<<3)
128 #define M98088_DAI1R_TO_DACR (1<<2)
129 #define M98088_DAI2L_TO_DACR (1<<1)
130 #define M98088_DAI2R_TO_DACR (1<<0)
131
132/* M98088_REG_2A_MIC_REC_CNTL */
133 #define M98088_REC_LINEMODE (1<<7)
134 #define M98088_REC_LINEMODE_MASK (1<<7)
135
136/* M98088_REG_35_LVL_MIC1, M98088_REG_36_LVL_MIC2 */
137 #define M98088_MICPRE_MASK (3<<5)
138 #define M98088_MICPRE_SHIFT 5
139
140/* M98088_REG_3A_LVL_HP_R */
141 #define M98088_HP_MUTE (1<<7)
142
143/* M98088_REG_3C_LVL_REC_R */
144 #define M98088_REC_MUTE (1<<7)
145
146/* M98088_REG_3E_LVL_SPK_R */
147 #define M98088_SP_MUTE (1<<7)
148
149/* M98088_REG_48_CFG_MIC */
150 #define M98088_EXTMIC_MASK (3<<0)
151 #define M98088_DIGMIC_L (1<<5)
152 #define M98088_DIGMIC_R (1<<4)
153
154/* M98088_REG_49_CFG_LEVEL */
155 #define M98088_VSEN (1<<6)
156 #define M98088_ZDEN (1<<5)
157 #define M98088_EQ2EN (1<<1)
158 #define M98088_EQ1EN (1<<0)
159
160/* M98088_REG_4C_PWR_EN_IN */
161 #define M98088_INAEN (1<<7)
162 #define M98088_INBEN (1<<6)
163 #define M98088_MBEN (1<<3)
164 #define M98088_ADLEN (1<<1)
165 #define M98088_ADREN (1<<0)
166
167/* M98088_REG_4D_PWR_EN_OUT */
168 #define M98088_HPLEN (1<<7)
169 #define M98088_HPREN (1<<6)
170 #define M98088_HPEN ((1<<7)|(1<<6))
171 #define M98088_SPLEN (1<<5)
172 #define M98088_SPREN (1<<4)
173 #define M98088_RECEN (1<<3)
174 #define M98088_DALEN (1<<1)
175 #define M98088_DAREN (1<<0)
176
177/* M98088_REG_51_PWR_SYS */
178 #define M98088_SHDNRUN (1<<7)
179 #define M98088_PERFMODE (1<<3)
180 #define M98088_HPPLYBACK (1<<2)
181 #define M98088_PWRSV8K (1<<1)
182 #define M98088_PWRSV (1<<0)
183
184/* Line inputs */
185#define LINE_INA 0
186#define LINE_INB 1
187
188#define M98088_COEFS_PER_BAND 5
189
190#define M98088_BYTE1(w) ((w >> 8) & 0xff)
191#define M98088_BYTE0(w) (w & 0xff)
192
193#endif
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index 5a5f187a2657..bd8f26e41602 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -32,8 +32,8 @@
32#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ 32#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
33 SNDRV_PCM_RATE_48000) 33 SNDRV_PCM_RATE_48000)
34 34
35struct snd_soc_dai pcm3008_dai = { 35static struct snd_soc_dai_driver pcm3008_dai = {
36 .name = "PCM3008 HiFi", 36 .name = "pcm3008-hifi",
37 .playback = { 37 .playback = {
38 .stream_name = "PCM3008 Playback", 38 .stream_name = "PCM3008 Playback",
39 .channels_min = 1, 39 .channels_min = 1,
@@ -49,7 +49,6 @@ struct snd_soc_dai pcm3008_dai = {
49 .formats = SNDRV_PCM_FMTBIT_S16_LE, 49 .formats = SNDRV_PCM_FMTBIT_S16_LE,
50 }, 50 },
51}; 51};
52EXPORT_SYMBOL_GPL(pcm3008_dai);
53 52
54static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) 53static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
55{ 54{
@@ -59,38 +58,13 @@ static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
59 gpio_free(setup->pdda_pin); 58 gpio_free(setup->pdda_pin);
60} 59}
61 60
62static int pcm3008_soc_probe(struct platform_device *pdev) 61static int pcm3008_soc_probe(struct snd_soc_codec *codec)
63{ 62{
64 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 63 struct pcm3008_setup_data *setup = codec->dev->platform_data;
65 struct snd_soc_codec *codec;
66 struct pcm3008_setup_data *setup = socdev->codec_data;
67 int ret = 0; 64 int ret = 0;
68 65
69 printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); 66 printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
70 67
71 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
72 if (!socdev->card->codec)
73 return -ENOMEM;
74
75 codec = socdev->card->codec;
76 mutex_init(&codec->mutex);
77
78 codec->name = "PCM3008";
79 codec->owner = THIS_MODULE;
80 codec->dai = &pcm3008_dai;
81 codec->num_dai = 1;
82 codec->write = NULL;
83 codec->read = NULL;
84 INIT_LIST_HEAD(&codec->dapm_widgets);
85 INIT_LIST_HEAD(&codec->dapm_paths);
86
87 /* Register PCMs. */
88 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
89 if (ret < 0) {
90 printk(KERN_ERR "pcm3008: failed to create pcms\n");
91 goto pcm_err;
92 }
93
94 /* DEM1 DEM0 DE-EMPHASIS_MODE 68 /* DEM1 DEM0 DE-EMPHASIS_MODE
95 * Low Low De-emphasis 44.1 kHz ON 69 * Low Low De-emphasis 44.1 kHz ON
96 * Low High De-emphasis OFF 70 * Low High De-emphasis OFF
@@ -130,33 +104,22 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
130 104
131gpio_err: 105gpio_err:
132 pcm3008_gpio_free(setup); 106 pcm3008_gpio_free(setup);
133pcm_err:
134 kfree(socdev->card->codec);
135 107
136 return ret; 108 return ret;
137} 109}
138 110
139static int pcm3008_soc_remove(struct platform_device *pdev) 111static int pcm3008_soc_remove(struct snd_soc_codec *codec)
140{ 112{
141 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 113 struct pcm3008_setup_data *setup = codec->dev->platform_data;
142 struct snd_soc_codec *codec = socdev->card->codec;
143 struct pcm3008_setup_data *setup = socdev->codec_data;
144
145 if (!codec)
146 return 0;
147 114
148 pcm3008_gpio_free(setup); 115 pcm3008_gpio_free(setup);
149 snd_soc_free_pcms(socdev);
150 kfree(socdev->card->codec);
151
152 return 0; 116 return 0;
153} 117}
154 118
155#ifdef CONFIG_PM 119#ifdef CONFIG_PM
156static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) 120static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
157{ 121{
158 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 122 struct pcm3008_setup_data *setup = codec->dev->platform_data;
159 struct pcm3008_setup_data *setup = socdev->codec_data;
160 123
161 gpio_set_value(setup->pdad_pin, 0); 124 gpio_set_value(setup->pdad_pin, 0);
162 gpio_set_value(setup->pdda_pin, 0); 125 gpio_set_value(setup->pdda_pin, 0);
@@ -164,10 +127,9 @@ static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
164 return 0; 127 return 0;
165} 128}
166 129
167static int pcm3008_soc_resume(struct platform_device *pdev) 130static int pcm3008_soc_resume(struct snd_soc_codec *codec)
168{ 131{
169 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 132 struct pcm3008_setup_data *setup = codec->dev->platform_data;
170 struct pcm3008_setup_data *setup = socdev->codec_data;
171 133
172 gpio_set_value(setup->pdad_pin, 1); 134 gpio_set_value(setup->pdad_pin, 1);
173 gpio_set_value(setup->pdda_pin, 1); 135 gpio_set_value(setup->pdda_pin, 1);
@@ -179,23 +141,45 @@ static int pcm3008_soc_resume(struct platform_device *pdev)
179#define pcm3008_soc_resume NULL 141#define pcm3008_soc_resume NULL
180#endif 142#endif
181 143
182struct snd_soc_codec_device soc_codec_dev_pcm3008 = { 144static struct snd_soc_codec_driver soc_codec_dev_pcm3008 = {
183 .probe = pcm3008_soc_probe, 145 .probe = pcm3008_soc_probe,
184 .remove = pcm3008_soc_remove, 146 .remove = pcm3008_soc_remove,
185 .suspend = pcm3008_soc_suspend, 147 .suspend = pcm3008_soc_suspend,
186 .resume = pcm3008_soc_resume, 148 .resume = pcm3008_soc_resume,
187}; 149};
188EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008);
189 150
190static int __init pcm3008_init(void) 151static int __devinit pcm3008_codec_probe(struct platform_device *pdev)
152{
153 return snd_soc_register_codec(&pdev->dev,
154 &soc_codec_dev_pcm3008, &pcm3008_dai, 1);
155}
156
157static int __devexit pcm3008_codec_remove(struct platform_device *pdev)
158{
159 snd_soc_unregister_codec(&pdev->dev);
160 return 0;
161}
162
163MODULE_ALIAS("platform:pcm3008-codec");
164
165static struct platform_driver pcm3008_codec_driver = {
166 .probe = pcm3008_codec_probe,
167 .remove = __devexit_p(pcm3008_codec_remove),
168 .driver = {
169 .name = "pcm3008-codec",
170 .owner = THIS_MODULE,
171 },
172};
173
174static int __init pcm3008_modinit(void)
191{ 175{
192 return snd_soc_register_dai(&pcm3008_dai); 176 return platform_driver_register(&pcm3008_codec_driver);
193} 177}
194module_init(pcm3008_init); 178module_init(pcm3008_modinit);
195 179
196static void __exit pcm3008_exit(void) 180static void __exit pcm3008_exit(void)
197{ 181{
198 snd_soc_unregister_dai(&pcm3008_dai); 182 platform_driver_unregister(&pcm3008_codec_driver);
199} 183}
200module_exit(pcm3008_exit); 184module_exit(pcm3008_exit);
201 185
diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h
index d04e87d3c060..7e5489ab4812 100644
--- a/sound/soc/codecs/pcm3008.h
+++ b/sound/soc/codecs/pcm3008.h
@@ -19,7 +19,4 @@ struct pcm3008_setup_data {
19 unsigned pdda_pin; 19 unsigned pdda_pin;
20}; 20};
21 21
22extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
23extern struct snd_soc_dai pcm3008_dai;
24
25#endif 22#endif
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
index 9119836051a4..4c32b54913ad 100644
--- a/sound/soc/codecs/spdif_transciever.c
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -21,57 +21,16 @@
21#include <sound/pcm.h> 21#include <sound/pcm.h>
22#include <sound/initval.h> 22#include <sound/initval.h>
23 23
24#include "spdif_transciever.h"
25
26MODULE_LICENSE("GPL"); 24MODULE_LICENSE("GPL");
27 25
28#define STUB_RATES SNDRV_PCM_RATE_8000_96000 26#define STUB_RATES SNDRV_PCM_RATE_8000_96000
29#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE 27#define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE
30 28
31static struct snd_soc_codec *spdif_dit_codec;
32
33static int spdif_dit_codec_probe(struct platform_device *pdev)
34{
35 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
36 struct snd_soc_codec *codec;
37 int ret;
38
39 if (spdif_dit_codec == NULL) {
40 dev_err(&pdev->dev, "Codec device not registered\n");
41 return -ENODEV;
42 }
43
44 socdev->card->codec = spdif_dit_codec;
45 codec = spdif_dit_codec;
46
47 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
48 if (ret < 0) {
49 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
50 goto err_create_pcms;
51 }
52
53 return 0;
54
55err_create_pcms:
56 return ret;
57}
58
59static int spdif_dit_codec_remove(struct platform_device *pdev)
60{
61 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
62
63 snd_soc_free_pcms(socdev);
64
65 return 0;
66}
67 29
68struct snd_soc_codec_device soc_codec_dev_spdif_dit = { 30static struct snd_soc_codec_driver soc_codec_spdif_dit;
69 .probe = spdif_dit_codec_probe,
70 .remove = spdif_dit_codec_remove,
71}; EXPORT_SYMBOL_GPL(soc_codec_dev_spdif_dit);
72 31
73struct snd_soc_dai dit_stub_dai = { 32static struct snd_soc_dai_driver dit_stub_dai = {
74 .name = "DIT", 33 .name = "dit-hifi",
75 .playback = { 34 .playback = {
76 .stream_name = "Playback", 35 .stream_name = "Playback",
77 .channels_min = 1, 36 .channels_min = 1,
@@ -80,65 +39,16 @@ struct snd_soc_dai dit_stub_dai = {
80 .formats = STUB_FORMATS, 39 .formats = STUB_FORMATS,
81 }, 40 },
82}; 41};
83EXPORT_SYMBOL_GPL(dit_stub_dai);
84 42
85static int spdif_dit_probe(struct platform_device *pdev) 43static int spdif_dit_probe(struct platform_device *pdev)
86{ 44{
87 struct snd_soc_codec *codec; 45 return snd_soc_register_codec(&pdev->dev, &soc_codec_spdif_dit,
88 int ret; 46 &dit_stub_dai, 1);
89
90 if (spdif_dit_codec) {
91 dev_err(&pdev->dev, "Another Codec is registered\n");
92 ret = -EINVAL;
93 goto err_reg_codec;
94 }
95
96 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
97 if (codec == NULL)
98 return -ENOMEM;
99
100 codec->dev = &pdev->dev;
101
102 mutex_init(&codec->mutex);
103
104 INIT_LIST_HEAD(&codec->dapm_widgets);
105 INIT_LIST_HEAD(&codec->dapm_paths);
106
107 codec->name = "spdif-dit";
108 codec->owner = THIS_MODULE;
109 codec->dai = &dit_stub_dai;
110 codec->num_dai = 1;
111
112 spdif_dit_codec = codec;
113
114 ret = snd_soc_register_codec(codec);
115 if (ret < 0) {
116 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
117 goto err_reg_codec;
118 }
119
120 dit_stub_dai.dev = &pdev->dev;
121 ret = snd_soc_register_dai(&dit_stub_dai);
122 if (ret < 0) {
123 dev_err(codec->dev, "Failed to register dai: %d\n", ret);
124 goto err_reg_dai;
125 }
126
127 return 0;
128
129err_reg_dai:
130 snd_soc_unregister_codec(codec);
131err_reg_codec:
132 kfree(spdif_dit_codec);
133 return ret;
134} 47}
135 48
136static int spdif_dit_remove(struct platform_device *pdev) 49static int spdif_dit_remove(struct platform_device *pdev)
137{ 50{
138 snd_soc_unregister_dai(&dit_stub_dai); 51 snd_soc_unregister_codec(&pdev->dev);
139 snd_soc_unregister_codec(spdif_dit_codec);
140 kfree(spdif_dit_codec);
141 spdif_dit_codec = NULL;
142 return 0; 52 return 0;
143} 53}
144 54
diff --git a/sound/soc/codecs/spdif_transciever.h b/sound/soc/codecs/spdif_transciever.h
deleted file mode 100644
index 1e102124f546..000000000000
--- a/sound/soc/codecs/spdif_transciever.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * ALSA SoC DIT/DIR driver header
3 *
4 * Author: Steve Chen, <schen@mvista.com>
5 * Copyright: (C) 2008 MontaVista Software, Inc., <source@mvista.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#ifndef CODEC_STUBS_H
13#define CODEC_STUBS_H
14
15extern struct snd_soc_codec_device soc_codec_dev_spdif_dit;
16extern struct snd_soc_dai dit_stub_dai;
17
18#endif /* CODEC_STUBS_H */
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index b47ed4f6ab20..6f38d619bf8a 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -45,11 +45,11 @@
45 45
46#define SSM2602_VERSION "0.1" 46#define SSM2602_VERSION "0.1"
47 47
48struct snd_soc_codec_device soc_codec_dev_ssm2602;
49
50/* codec private data */ 48/* codec private data */
51struct ssm2602_priv { 49struct ssm2602_priv {
52 unsigned int sysclk; 50 unsigned int sysclk;
51 enum snd_soc_control_type control_type;
52 void *control_data;
53 struct snd_pcm_substream *master_substream; 53 struct snd_pcm_substream *master_substream;
54 struct snd_pcm_substream *slave_substream; 54 struct snd_pcm_substream *slave_substream;
55}; 55};
@@ -276,8 +276,7 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
276{ 276{
277 u16 srate; 277 u16 srate;
278 struct snd_soc_pcm_runtime *rtd = substream->private_data; 278 struct snd_soc_pcm_runtime *rtd = substream->private_data;
279 struct snd_soc_device *socdev = rtd->socdev; 279 struct snd_soc_codec *codec = rtd->codec;
280 struct snd_soc_codec *codec = socdev->card->codec;
281 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 280 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
282 struct i2c_client *i2c = codec->control_data; 281 struct i2c_client *i2c = codec->control_data;
283 u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; 282 u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
@@ -321,8 +320,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
321 struct snd_soc_dai *dai) 320 struct snd_soc_dai *dai)
322{ 321{
323 struct snd_soc_pcm_runtime *rtd = substream->private_data; 322 struct snd_soc_pcm_runtime *rtd = substream->private_data;
324 struct snd_soc_device *socdev = rtd->socdev; 323 struct snd_soc_codec *codec = rtd->codec;
325 struct snd_soc_codec *codec = socdev->card->codec;
326 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 324 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
327 struct i2c_client *i2c = codec->control_data; 325 struct i2c_client *i2c = codec->control_data;
328 struct snd_pcm_runtime *master_runtime; 326 struct snd_pcm_runtime *master_runtime;
@@ -360,8 +358,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
360 struct snd_soc_dai *dai) 358 struct snd_soc_dai *dai)
361{ 359{
362 struct snd_soc_pcm_runtime *rtd = substream->private_data; 360 struct snd_soc_pcm_runtime *rtd = substream->private_data;
363 struct snd_soc_device *socdev = rtd->socdev; 361 struct snd_soc_codec *codec = rtd->codec;
364 struct snd_soc_codec *codec = socdev->card->codec;
365 /* set active */ 362 /* set active */
366 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); 363 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
367 364
@@ -372,8 +369,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
372 struct snd_soc_dai *dai) 369 struct snd_soc_dai *dai)
373{ 370{
374 struct snd_soc_pcm_runtime *rtd = substream->private_data; 371 struct snd_soc_pcm_runtime *rtd = substream->private_data;
375 struct snd_soc_device *socdev = rtd->socdev; 372 struct snd_soc_codec *codec = rtd->codec;
376 struct snd_soc_codec *codec = socdev->card->codec;
377 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 373 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
378 374
379 /* deactivate */ 375 /* deactivate */
@@ -518,8 +514,8 @@ static struct snd_soc_dai_ops ssm2602_dai_ops = {
518 .set_fmt = ssm2602_set_dai_fmt, 514 .set_fmt = ssm2602_set_dai_fmt,
519}; 515};
520 516
521struct snd_soc_dai ssm2602_dai = { 517static struct snd_soc_dai_driver ssm2602_dai = {
522 .name = "SSM2602", 518 .name = "ssm2602-hifi",
523 .playback = { 519 .playback = {
524 .stream_name = "Playback", 520 .stream_name = "Playback",
525 .channels_min = 2, 521 .channels_min = 2,
@@ -534,21 +530,15 @@ struct snd_soc_dai ssm2602_dai = {
534 .formats = SSM2602_FORMATS,}, 530 .formats = SSM2602_FORMATS,},
535 .ops = &ssm2602_dai_ops, 531 .ops = &ssm2602_dai_ops,
536}; 532};
537EXPORT_SYMBOL_GPL(ssm2602_dai);
538 533
539static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) 534static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)
540{ 535{
541 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
542 struct snd_soc_codec *codec = socdev->card->codec;
543
544 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); 536 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
545 return 0; 537 return 0;
546} 538}
547 539
548static int ssm2602_resume(struct platform_device *pdev) 540static int ssm2602_resume(struct snd_soc_codec *codec)
549{ 541{
550 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
551 struct snd_soc_codec *codec = socdev->card->codec;
552 int i; 542 int i;
553 u8 data[2]; 543 u8 data[2];
554 u16 *cache = codec->reg_cache; 544 u16 *cache = codec->reg_cache;
@@ -563,36 +553,17 @@ static int ssm2602_resume(struct platform_device *pdev)
563 return 0; 553 return 0;
564} 554}
565 555
566/* 556static int ssm2602_probe(struct snd_soc_codec *codec)
567 * initialise the ssm2602 driver
568 * register the mixer and dsp interfaces with the kernel
569 */
570static int ssm2602_init(struct snd_soc_device *socdev)
571{ 557{
572 struct snd_soc_codec *codec = socdev->card->codec; 558 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
573 int reg, ret = 0; 559 int ret = 0, reg;
574 560
575 codec->name = "SSM2602"; 561 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
576 codec->owner = THIS_MODULE; 562
577 codec->read = ssm2602_read_reg_cache; 563 codec->control_data = ssm2602->control_data;
578 codec->write = ssm2602_write;
579 codec->set_bias_level = ssm2602_set_bias_level;
580 codec->dai = &ssm2602_dai;
581 codec->num_dai = 1;
582 codec->reg_cache_size = sizeof(ssm2602_reg);
583 codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg),
584 GFP_KERNEL);
585 if (codec->reg_cache == NULL)
586 return -ENOMEM;
587 564
588 ssm2602_reset(codec); 565 ssm2602_reset(codec);
589 566
590 /* register pcms */
591 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
592 if (ret < 0) {
593 pr_err("ssm2602: failed to create pcms\n");
594 goto pcm_err;
595 }
596 /*power on device*/ 567 /*power on device*/
597 ssm2602_write(codec, SSM2602_ACTIVE, 0); 568 ssm2602_write(codec, SSM2602_ACTIVE, 0);
598 /* set the update bits */ 569 /* set the update bits */
@@ -614,13 +585,27 @@ static int ssm2602_init(struct snd_soc_device *socdev)
614 ssm2602_add_widgets(codec); 585 ssm2602_add_widgets(codec);
615 586
616 return ret; 587 return ret;
588}
617 589
618pcm_err: 590/* remove everything here */
619 kfree(codec->reg_cache); 591static int ssm2602_remove(struct snd_soc_codec *codec)
620 return ret; 592{
593 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
594 return 0;
621} 595}
622 596
623static struct snd_soc_device *ssm2602_socdev; 597static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
598 .probe = ssm2602_probe,
599 .remove = ssm2602_remove,
600 .suspend = ssm2602_suspend,
601 .resume = ssm2602_resume,
602 .read = ssm2602_read_reg_cache,
603 .write = ssm2602_write,
604 .set_bias_level = ssm2602_set_bias_level,
605 .reg_cache_size = sizeof(ssm2602_reg),
606 .reg_word_size = sizeof(u16),
607 .reg_cache_default = ssm2602_reg,
608};
624 609
625#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 610#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
626/* 611/*
@@ -632,24 +617,28 @@ static struct snd_soc_device *ssm2602_socdev;
632static int ssm2602_i2c_probe(struct i2c_client *i2c, 617static int ssm2602_i2c_probe(struct i2c_client *i2c,
633 const struct i2c_device_id *id) 618 const struct i2c_device_id *id)
634{ 619{
635 struct snd_soc_device *socdev = ssm2602_socdev; 620 struct ssm2602_priv *ssm2602;
636 struct snd_soc_codec *codec = socdev->card->codec;
637 int ret; 621 int ret;
638 622
639 i2c_set_clientdata(i2c, codec); 623 ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
640 codec->control_data = i2c; 624 if (ssm2602 == NULL)
625 return -ENOMEM;
641 626
642 ret = ssm2602_init(socdev); 627 i2c_set_clientdata(i2c, ssm2602);
643 if (ret < 0) 628 ssm2602->control_data = i2c;
644 pr_err("failed to initialise SSM2602\n"); 629 ssm2602->control_type = SND_SOC_I2C;
645 630
631 ret = snd_soc_register_codec(&i2c->dev,
632 &soc_codec_dev_ssm2602, &ssm2602_dai, 1);
633 if (ret < 0)
634 kfree(ssm2602);
646 return ret; 635 return ret;
647} 636}
648 637
649static int ssm2602_i2c_remove(struct i2c_client *client) 638static int ssm2602_i2c_remove(struct i2c_client *client)
650{ 639{
651 struct snd_soc_codec *codec = i2c_get_clientdata(client); 640 snd_soc_unregister_codec(&client->dev);
652 kfree(codec->reg_cache); 641 kfree(i2c_get_clientdata(client));
653 return 0; 642 return 0;
654} 643}
655 644
@@ -658,130 +647,39 @@ static const struct i2c_device_id ssm2602_i2c_id[] = {
658 { } 647 { }
659}; 648};
660MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); 649MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
650
661/* corgi i2c codec control layer */ 651/* corgi i2c codec control layer */
662static struct i2c_driver ssm2602_i2c_driver = { 652static struct i2c_driver ssm2602_i2c_driver = {
663 .driver = { 653 .driver = {
664 .name = "SSM2602 I2C Codec", 654 .name = "ssm2602-codec",
665 .owner = THIS_MODULE, 655 .owner = THIS_MODULE,
666 }, 656 },
667 .probe = ssm2602_i2c_probe, 657 .probe = ssm2602_i2c_probe,
668 .remove = ssm2602_i2c_remove, 658 .remove = ssm2602_i2c_remove,
669 .id_table = ssm2602_i2c_id, 659 .id_table = ssm2602_i2c_id,
670}; 660};
671
672static int ssm2602_add_i2c_device(struct platform_device *pdev,
673 const struct ssm2602_setup_data *setup)
674{
675 struct i2c_board_info info;
676 struct i2c_adapter *adapter;
677 struct i2c_client *client;
678 int ret;
679
680 ret = i2c_add_driver(&ssm2602_i2c_driver);
681 if (ret != 0) {
682 dev_err(&pdev->dev, "can't add i2c driver\n");
683 return ret;
684 }
685 memset(&info, 0, sizeof(struct i2c_board_info));
686 info.addr = setup->i2c_address;
687 strlcpy(info.type, "ssm2602", I2C_NAME_SIZE);
688 adapter = i2c_get_adapter(setup->i2c_bus);
689 if (!adapter) {
690 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
691 setup->i2c_bus);
692 goto err_driver;
693 }
694 client = i2c_new_device(adapter, &info);
695 i2c_put_adapter(adapter);
696 if (!client) {
697 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
698 (unsigned int)info.addr);
699 goto err_driver;
700 }
701 return 0;
702err_driver:
703 i2c_del_driver(&ssm2602_i2c_driver);
704 return -ENODEV;
705}
706#endif 661#endif
707 662
708static int ssm2602_probe(struct platform_device *pdev) 663
664static int __init ssm2602_modinit(void)
709{ 665{
710 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
711 struct ssm2602_setup_data *setup;
712 struct snd_soc_codec *codec;
713 struct ssm2602_priv *ssm2602;
714 int ret = 0; 666 int ret = 0;
715
716 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
717
718 setup = socdev->codec_data;
719 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
720 if (codec == NULL)
721 return -ENOMEM;
722
723 ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
724 if (ssm2602 == NULL) {
725 kfree(codec);
726 return -ENOMEM;
727 }
728
729 snd_soc_codec_set_drvdata(codec, ssm2602);
730 socdev->card->codec = codec;
731 mutex_init(&codec->mutex);
732 INIT_LIST_HEAD(&codec->dapm_widgets);
733 INIT_LIST_HEAD(&codec->dapm_paths);
734
735 ssm2602_socdev = socdev;
736#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 667#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
737 if (setup->i2c_address) { 668 ret = i2c_add_driver(&ssm2602_i2c_driver);
738 codec->hw_write = (hw_write_t)i2c_master_send; 669 if (ret != 0) {
739 ret = ssm2602_add_i2c_device(pdev, setup); 670 printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n",
671 ret);
740 } 672 }
741#else
742 /* other interfaces */
743#endif 673#endif
744 return ret; 674 return ret;
745} 675}
676module_init(ssm2602_modinit);
746 677
747/* remove everything here */ 678static void __exit ssm2602_exit(void)
748static int ssm2602_remove(struct platform_device *pdev)
749{ 679{
750 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
751 struct snd_soc_codec *codec = socdev->card->codec;
752
753 if (codec->control_data)
754 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
755
756 snd_soc_free_pcms(socdev);
757 snd_soc_dapm_free(socdev);
758#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 680#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
759 i2c_unregister_device(codec->control_data);
760 i2c_del_driver(&ssm2602_i2c_driver); 681 i2c_del_driver(&ssm2602_i2c_driver);
761#endif 682#endif
762 kfree(snd_soc_codec_get_drvdata(codec));
763 kfree(codec);
764
765 return 0;
766}
767
768struct snd_soc_codec_device soc_codec_dev_ssm2602 = {
769 .probe = ssm2602_probe,
770 .remove = ssm2602_remove,
771 .suspend = ssm2602_suspend,
772 .resume = ssm2602_resume,
773};
774EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602);
775
776static int __init ssm2602_modinit(void)
777{
778 return snd_soc_register_dai(&ssm2602_dai);
779}
780module_init(ssm2602_modinit);
781
782static void __exit ssm2602_exit(void)
783{
784 snd_soc_unregister_dai(&ssm2602_dai);
785} 683}
786module_exit(ssm2602_exit); 684module_exit(ssm2602_exit);
787 685
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h
index f344e6d76e31..42a47d0f8e25 100644
--- a/sound/soc/codecs/ssm2602.h
+++ b/sound/soc/codecs/ssm2602.h
@@ -124,7 +124,4 @@ struct ssm2602_setup_data {
124 unsigned short i2c_address; 124 unsigned short i2c_address;
125}; 125};
126 126
127extern struct snd_soc_dai ssm2602_dai;
128extern struct snd_soc_codec_device soc_codec_dev_ssm2602;
129
130#endif 127#endif
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index ee86568545c2..00d67cc8e206 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -25,7 +25,6 @@
25#include <sound/pcm_params.h> 25#include <sound/pcm_params.h>
26#include <sound/soc.h> 26#include <sound/soc.h>
27#include <sound/tlv.h> 27#include <sound/tlv.h>
28#include <sound/soc-of-simple.h>
29 28
30#include "stac9766.h" 29#include "stac9766.h"
31 30
@@ -257,20 +256,15 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
257 return 0; 256 return 0;
258} 257}
259 258
260static int stac9766_codec_suspend(struct platform_device *pdev, 259static int stac9766_codec_suspend(struct snd_soc_codec *codec,
261 pm_message_t state) 260 pm_message_t state)
262{ 261{
263 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
264 struct snd_soc_codec *codec = socdev->card->codec;
265
266 stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF); 262 stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
267 return 0; 263 return 0;
268} 264}
269 265
270static int stac9766_codec_resume(struct platform_device *pdev) 266static int stac9766_codec_resume(struct snd_soc_codec *codec)
271{ 267{
272 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
273 struct snd_soc_codec *codec = socdev->card->codec;
274 u16 id, reset; 268 u16 id, reset;
275 269
276 reset = 0; 270 reset = 0;
@@ -300,10 +294,9 @@ static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
300 .prepare = ac97_digital_prepare, 294 .prepare = ac97_digital_prepare,
301}; 295};
302 296
303struct snd_soc_dai stac9766_dai[] = { 297static struct snd_soc_dai_driver stac9766_dai[] = {
304{ 298{
305 .name = "stac9766 analog", 299 .name = "stac9766-hifi-analog",
306 .id = 0,
307 .ac97_control = 1, 300 .ac97_control = 1,
308 301
309 /* stream cababilities */ 302 /* stream cababilities */
@@ -325,8 +318,7 @@ struct snd_soc_dai stac9766_dai[] = {
325 .ops = &stac9766_dai_ops_analog, 318 .ops = &stac9766_dai_ops_analog,
326}, 319},
327{ 320{
328 .name = "stac9766 IEC958", 321 .name = "stac9766-hifi-IEC958",
329 .id = 1,
330 .ac97_control = 1, 322 .ac97_control = 1,
331 323
332 /* stream cababilities */ 324 /* stream cababilities */
@@ -342,57 +334,24 @@ struct snd_soc_dai stac9766_dai[] = {
342 .ops = &stac9766_dai_ops_digital, 334 .ops = &stac9766_dai_ops_digital,
343} 335}
344}; 336};
345EXPORT_SYMBOL_GPL(stac9766_dai);
346 337
347static int stac9766_codec_probe(struct platform_device *pdev) 338static int stac9766_codec_probe(struct snd_soc_codec *codec)
348{ 339{
349 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
350 struct snd_soc_codec *codec;
351 int ret = 0; 340 int ret = 0;
352 341
353 printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); 342 printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION);
354 343
355 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
356 if (socdev->card->codec == NULL)
357 return -ENOMEM;
358 codec = socdev->card->codec;
359 mutex_init(&codec->mutex);
360
361 codec->reg_cache = kmemdup(stac9766_reg, sizeof(stac9766_reg),
362 GFP_KERNEL);
363 if (codec->reg_cache == NULL) {
364 ret = -ENOMEM;
365 goto cache_err;
366 }
367 codec->reg_cache_size = sizeof(stac9766_reg);
368 codec->reg_cache_step = 2;
369
370 codec->name = "STAC9766";
371 codec->owner = THIS_MODULE;
372 codec->dai = stac9766_dai;
373 codec->num_dai = ARRAY_SIZE(stac9766_dai);
374 codec->write = stac9766_ac97_write;
375 codec->read = stac9766_ac97_read;
376 codec->set_bias_level = stac9766_set_bias_level;
377 INIT_LIST_HEAD(&codec->dapm_widgets);
378 INIT_LIST_HEAD(&codec->dapm_paths);
379
380 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); 344 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
381 if (ret < 0) 345 if (ret < 0)
382 goto codec_err; 346 goto codec_err;
383 347
384 /* register pcms */
385 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
386 if (ret < 0)
387 goto pcm_err;
388
389 /* do a cold reset for the controller and then try 348 /* do a cold reset for the controller and then try
390 * a warm reset followed by an optional cold reset for codec */ 349 * a warm reset followed by an optional cold reset for codec */
391 stac9766_reset(codec, 0); 350 stac9766_reset(codec, 0);
392 ret = stac9766_reset(codec, 1); 351 ret = stac9766_reset(codec, 1);
393 if (ret < 0) { 352 if (ret < 0) {
394 printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n"); 353 printk(KERN_ERR "Failed to reset STAC9766: AC97 link error\n");
395 goto reset_err; 354 goto codec_err;
396 } 355 }
397 356
398 stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 357 stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -402,40 +361,63 @@ static int stac9766_codec_probe(struct platform_device *pdev)
402 361
403 return 0; 362 return 0;
404 363
405reset_err:
406 snd_soc_free_pcms(socdev);
407pcm_err:
408 snd_soc_free_ac97_codec(codec);
409codec_err: 364codec_err:
410 kfree(snd_soc_codec_get_drvdata(codec)); 365 snd_soc_free_ac97_codec(codec);
411cache_err:
412 kfree(socdev->card->codec);
413 socdev->card->codec = NULL;
414 return ret; 366 return ret;
415} 367}
416 368
417static int stac9766_codec_remove(struct platform_device *pdev) 369static int stac9766_codec_remove(struct snd_soc_codec *codec)
418{ 370{
419 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
420 struct snd_soc_codec *codec = socdev->card->codec;
421
422 if (codec == NULL)
423 return 0;
424
425 snd_soc_free_pcms(socdev);
426 snd_soc_free_ac97_codec(codec); 371 snd_soc_free_ac97_codec(codec);
427 kfree(codec->reg_cache);
428 kfree(codec);
429 return 0; 372 return 0;
430} 373}
431 374
432struct snd_soc_codec_device soc_codec_dev_stac9766 = { 375static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
376 .write = stac9766_ac97_write,
377 .read = stac9766_ac97_read,
378 .set_bias_level = stac9766_set_bias_level,
433 .probe = stac9766_codec_probe, 379 .probe = stac9766_codec_probe,
434 .remove = stac9766_codec_remove, 380 .remove = stac9766_codec_remove,
435 .suspend = stac9766_codec_suspend, 381 .suspend = stac9766_codec_suspend,
436 .resume = stac9766_codec_resume, 382 .resume = stac9766_codec_resume,
383 .reg_cache_size = sizeof(stac9766_reg),
384 .reg_word_size = sizeof(u16),
385 .reg_cache_step = 2,
386};
387
388static __devinit int stac9766_probe(struct platform_device *pdev)
389{
390 return snd_soc_register_codec(&pdev->dev,
391 &soc_codec_dev_stac9766, stac9766_dai, ARRAY_SIZE(stac9766_dai));
392}
393
394static int __devexit stac9766_remove(struct platform_device *pdev)
395{
396 snd_soc_unregister_codec(&pdev->dev);
397 return 0;
398}
399
400static struct platform_driver stac9766_codec_driver = {
401 .driver = {
402 .name = "stac9766-codec",
403 .owner = THIS_MODULE,
404 },
405
406 .probe = stac9766_probe,
407 .remove = __devexit_p(stac9766_remove),
437}; 408};
438EXPORT_SYMBOL_GPL(soc_codec_dev_stac9766); 409
410static int __init stac9766_init(void)
411{
412 return platform_driver_register(&stac9766_codec_driver);
413}
414module_init(stac9766_init);
415
416static void __exit stac9766_exit(void)
417{
418 platform_driver_unregister(&stac9766_codec_driver);
419}
420module_exit(stac9766_exit);
439 421
440MODULE_DESCRIPTION("ASoC stac9766 driver"); 422MODULE_DESCRIPTION("ASoC stac9766 driver");
441MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); 423MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
diff --git a/sound/soc/codecs/stac9766.h b/sound/soc/codecs/stac9766.h
index 65642eb8393e..c726f907e2c0 100644
--- a/sound/soc/codecs/stac9766.h
+++ b/sound/soc/codecs/stac9766.h
@@ -14,8 +14,4 @@
14#define STAC9766_DAI_AC97_ANALOG 0 14#define STAC9766_DAI_AC97_ANALOG 0
15#define STAC9766_DAI_AC97_DIGITAL 1 15#define STAC9766_DAI_AC97_DIGITAL 1
16 16
17extern struct snd_soc_dai stac9766_dai[];
18extern struct snd_soc_codec_device soc_codec_dev_stac9766;
19
20
21#endif 17#endif
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 0a4b0fef3355..e8652b1ae326 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -240,7 +240,8 @@ static const struct snd_soc_dapm_route intercon[] = {
240 240
241/* AIC23 driver data */ 241/* AIC23 driver data */
242struct aic23 { 242struct aic23 {
243 struct snd_soc_codec codec; 243 enum snd_soc_control_type control_type;
244 void *control_data;
244 int mclk; 245 int mclk;
245 int requested_adc; 246 int requested_adc;
246 int requested_dac; 247 int requested_dac;
@@ -404,11 +405,10 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
404 struct snd_soc_dai *dai) 405 struct snd_soc_dai *dai)
405{ 406{
406 struct snd_soc_pcm_runtime *rtd = substream->private_data; 407 struct snd_soc_pcm_runtime *rtd = substream->private_data;
407 struct snd_soc_device *socdev = rtd->socdev; 408 struct snd_soc_codec *codec = rtd->codec;
408 struct snd_soc_codec *codec = socdev->card->codec;
409 u16 iface_reg; 409 u16 iface_reg;
410 int ret; 410 int ret;
411 struct aic23 *aic23 = container_of(codec, struct aic23, codec); 411 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
412 u32 sample_rate_adc = aic23->requested_adc; 412 u32 sample_rate_adc = aic23->requested_adc;
413 u32 sample_rate_dac = aic23->requested_dac; 413 u32 sample_rate_dac = aic23->requested_dac;
414 u32 sample_rate = params_rate(params); 414 u32 sample_rate = params_rate(params);
@@ -452,8 +452,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
452 struct snd_soc_dai *dai) 452 struct snd_soc_dai *dai)
453{ 453{
454 struct snd_soc_pcm_runtime *rtd = substream->private_data; 454 struct snd_soc_pcm_runtime *rtd = substream->private_data;
455 struct snd_soc_device *socdev = rtd->socdev; 455 struct snd_soc_codec *codec = rtd->codec;
456 struct snd_soc_codec *codec = socdev->card->codec;
457 456
458 /* set active */ 457 /* set active */
459 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); 458 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
@@ -465,9 +464,8 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
465 struct snd_soc_dai *dai) 464 struct snd_soc_dai *dai)
466{ 465{
467 struct snd_soc_pcm_runtime *rtd = substream->private_data; 466 struct snd_soc_pcm_runtime *rtd = substream->private_data;
468 struct snd_soc_device *socdev = rtd->socdev; 467 struct snd_soc_codec *codec = rtd->codec;
469 struct snd_soc_codec *codec = socdev->card->codec; 468 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
470 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
471 469
472 /* deactivate */ 470 /* deactivate */
473 if (!codec->active) { 471 if (!codec->active) {
@@ -546,8 +544,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
546static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, 544static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
547 int clk_id, unsigned int freq, int dir) 545 int clk_id, unsigned int freq, int dir)
548{ 546{
549 struct snd_soc_codec *codec = codec_dai->codec; 547 struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai);
550 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
551 aic23->mclk = freq; 548 aic23->mclk = freq;
552 return 0; 549 return 0;
553} 550}
@@ -594,8 +591,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
594 .set_sysclk = tlv320aic23_set_dai_sysclk, 591 .set_sysclk = tlv320aic23_set_dai_sysclk,
595}; 592};
596 593
597struct snd_soc_dai tlv320aic23_dai = { 594static struct snd_soc_dai_driver tlv320aic23_dai = {
598 .name = "tlv320aic23", 595 .name = "tlv320aic23-hifi",
599 .playback = { 596 .playback = {
600 .stream_name = "Playback", 597 .stream_name = "Playback",
601 .channels_min = 2, 598 .channels_min = 2,
@@ -610,23 +607,17 @@ struct snd_soc_dai tlv320aic23_dai = {
610 .formats = AIC23_FORMATS,}, 607 .formats = AIC23_FORMATS,},
611 .ops = &tlv320aic23_dai_ops, 608 .ops = &tlv320aic23_dai_ops,
612}; 609};
613EXPORT_SYMBOL_GPL(tlv320aic23_dai);
614 610
615static int tlv320aic23_suspend(struct platform_device *pdev, 611static int tlv320aic23_suspend(struct snd_soc_codec *codec,
616 pm_message_t state) 612 pm_message_t state)
617{ 613{
618 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
619 struct snd_soc_codec *codec = socdev->card->codec;
620
621 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); 614 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
622 615
623 return 0; 616 return 0;
624} 617}
625 618
626static int tlv320aic23_resume(struct platform_device *pdev) 619static int tlv320aic23_resume(struct snd_soc_codec *codec)
627{ 620{
628 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
629 struct snd_soc_codec *codec = socdev->card->codec;
630 u16 reg; 621 u16 reg;
631 622
632 /* Sync reg_cache with the hardware */ 623 /* Sync reg_cache with the hardware */
@@ -639,39 +630,19 @@ static int tlv320aic23_resume(struct platform_device *pdev)
639 return 0; 630 return 0;
640} 631}
641 632
642/* 633static int tlv320aic23_probe(struct snd_soc_codec *codec)
643 * initialise the AIC23 driver
644 * register the mixer and dsp interfaces with the kernel
645 */
646static int tlv320aic23_init(struct snd_soc_device *socdev)
647{ 634{
648 struct snd_soc_codec *codec = socdev->card->codec; 635 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
649 int ret = 0; 636 int reg;
650 u16 reg;
651 637
652 codec->name = "tlv320aic23"; 638 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
653 codec->owner = THIS_MODULE; 639 codec->control_data = aic23->control_data;
654 codec->read = tlv320aic23_read_reg_cache; 640 codec->hw_write = (hw_write_t)i2c_master_send;
655 codec->write = tlv320aic23_write; 641 codec->hw_read = NULL;
656 codec->set_bias_level = tlv320aic23_set_bias_level;
657 codec->dai = &tlv320aic23_dai;
658 codec->num_dai = 1;
659 codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
660 codec->reg_cache =
661 kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
662 if (codec->reg_cache == NULL)
663 return -ENOMEM;
664 642
665 /* Reset codec */ 643 /* Reset codec */
666 tlv320aic23_write(codec, TLV320AIC23_RESET, 0); 644 tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
667 645
668 /* register pcms */
669 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
670 if (ret < 0) {
671 printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
672 goto pcm_err;
673 }
674
675 /* power on device */ 646 /* power on device */
676 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 647 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
677 648
@@ -707,13 +678,27 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
707 ARRAY_SIZE(tlv320aic23_snd_controls)); 678 ARRAY_SIZE(tlv320aic23_snd_controls));
708 tlv320aic23_add_widgets(codec); 679 tlv320aic23_add_widgets(codec);
709 680
710 return ret; 681 return 0;
682}
711 683
712pcm_err: 684static int tlv320aic23_remove(struct snd_soc_codec *codec)
713 kfree(codec->reg_cache); 685{
714 return ret; 686 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
687 return 0;
715} 688}
716static struct snd_soc_device *tlv320aic23_socdev; 689
690static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
691 .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg),
692 .reg_word_size = sizeof(u16),
693 .reg_cache_default = tlv320aic23_reg,
694 .probe = tlv320aic23_probe,
695 .remove = tlv320aic23_remove,
696 .suspend = tlv320aic23_suspend,
697 .resume = tlv320aic23_resume,
698 .read = tlv320aic23_read_reg_cache,
699 .write = tlv320aic23_write,
700 .set_bias_level = tlv320aic23_set_bias_level,
701};
717 702
718#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 703#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
719/* 704/*
@@ -723,31 +708,30 @@ static struct snd_soc_device *tlv320aic23_socdev;
723static int tlv320aic23_codec_probe(struct i2c_client *i2c, 708static int tlv320aic23_codec_probe(struct i2c_client *i2c,
724 const struct i2c_device_id *i2c_id) 709 const struct i2c_device_id *i2c_id)
725{ 710{
726 struct snd_soc_device *socdev = tlv320aic23_socdev; 711 struct aic23 *aic23;
727 struct snd_soc_codec *codec = socdev->card->codec;
728 int ret; 712 int ret;
729 713
730 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 714 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
731 return -EINVAL; 715 return -EINVAL;
732 716
733 i2c_set_clientdata(i2c, codec); 717 aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
734 codec->control_data = i2c; 718 if (aic23 == NULL)
719 return -ENOMEM;
735 720
736 ret = tlv320aic23_init(socdev); 721 i2c_set_clientdata(i2c, aic23);
737 if (ret < 0) { 722 aic23->control_data = i2c;
738 printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n"); 723 aic23->control_type = SND_SOC_I2C;
739 goto err;
740 }
741 return ret;
742 724
743err: 725 ret = snd_soc_register_codec(&i2c->dev,
744 kfree(codec); 726 &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
745 kfree(i2c); 727 if (ret < 0)
728 kfree(aic23);
746 return ret; 729 return ret;
747} 730}
748static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) 731static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
749{ 732{
750 put_device(&i2c->dev); 733 snd_soc_unregister_codec(&i2c->dev);
734 kfree(i2c_get_clientdata(i2c));
751 return 0; 735 return 0;
752} 736}
753 737
@@ -760,7 +744,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
760 744
761static struct i2c_driver tlv320aic23_i2c_driver = { 745static struct i2c_driver tlv320aic23_i2c_driver = {
762 .driver = { 746 .driver = {
763 .name = "tlv320aic23", 747 .name = "tlv320aic23-codec",
764 }, 748 },
765 .probe = tlv320aic23_codec_probe, 749 .probe = tlv320aic23_codec_probe,
766 .remove = __exit_p(tlv320aic23_i2c_remove), 750 .remove = __exit_p(tlv320aic23_i2c_remove),
@@ -769,71 +753,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = {
769 753
770#endif 754#endif
771 755
772static int tlv320aic23_probe(struct platform_device *pdev) 756static int __init tlv320aic23_modinit(void)
773{ 757{
774 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 758 int ret;
775 struct snd_soc_codec *codec;
776 struct aic23 *aic23;
777 int ret = 0;
778
779 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
780
781 aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
782 if (aic23 == NULL)
783 return -ENOMEM;
784 codec = &aic23->codec;
785 socdev->card->codec = codec;
786 mutex_init(&codec->mutex);
787 INIT_LIST_HEAD(&codec->dapm_widgets);
788 INIT_LIST_HEAD(&codec->dapm_paths);
789
790 tlv320aic23_socdev = socdev;
791#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 759#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
792 codec->hw_write = (hw_write_t) i2c_master_send;
793 codec->hw_read = NULL;
794 ret = i2c_add_driver(&tlv320aic23_i2c_driver); 760 ret = i2c_add_driver(&tlv320aic23_i2c_driver);
795 if (ret != 0) 761 if (ret != 0) {
796 printk(KERN_ERR "can't add i2c driver"); 762 printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n",
763 ret);
764 }
797#endif 765#endif
798 return ret; 766 return ret;
799} 767}
768module_init(tlv320aic23_modinit);
800 769
801static int tlv320aic23_remove(struct platform_device *pdev) 770static void __exit tlv320aic23_exit(void)
802{ 771{
803 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
804 struct snd_soc_codec *codec = socdev->card->codec;
805 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
806
807 if (codec->control_data)
808 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
809
810 snd_soc_free_pcms(socdev);
811 snd_soc_dapm_free(socdev);
812#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 772#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
813 i2c_del_driver(&tlv320aic23_i2c_driver); 773 i2c_del_driver(&tlv320aic23_i2c_driver);
814#endif 774#endif
815 kfree(codec->reg_cache);
816 kfree(aic23);
817
818 return 0;
819}
820struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
821 .probe = tlv320aic23_probe,
822 .remove = tlv320aic23_remove,
823 .suspend = tlv320aic23_suspend,
824 .resume = tlv320aic23_resume,
825};
826EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
827
828static int __init tlv320aic23_modinit(void)
829{
830 return snd_soc_register_dai(&tlv320aic23_dai);
831}
832module_init(tlv320aic23_modinit);
833
834static void __exit tlv320aic23_exit(void)
835{
836 snd_soc_unregister_dai(&tlv320aic23_dai);
837} 775}
838module_exit(tlv320aic23_exit); 776module_exit(tlv320aic23_exit);
839 777
diff --git a/sound/soc/codecs/tlv320aic23.h b/sound/soc/codecs/tlv320aic23.h
index 79d1faf8e570..e804120bd3da 100644
--- a/sound/soc/codecs/tlv320aic23.h
+++ b/sound/soc/codecs/tlv320aic23.h
@@ -116,7 +116,4 @@
116#define TLV320AIC23_SIDETONE_12 0x080 116#define TLV320AIC23_SIDETONE_12 0x080
117#define TLV320AIC23_SIDETONE_18 0x0c0 117#define TLV320AIC23_SIDETONE_18 0x0c0
118 118
119extern struct snd_soc_dai tlv320aic23_dai;
120extern struct snd_soc_codec_device soc_codec_dev_tlv320aic23;
121
122#endif /* _TLV320AIC23_H */ 119#endif /* _TLV320AIC23_H */
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index f0e00fd4b435..6b7d71ec0004 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -19,7 +19,6 @@
19#include <sound/pcm_params.h> 19#include <sound/pcm_params.h>
20#include <sound/soc.h> 20#include <sound/soc.h>
21#include <sound/soc-dapm.h> 21#include <sound/soc-dapm.h>
22#include <sound/soc-of-simple.h>
23#include <sound/initval.h> 22#include <sound/initval.h>
24 23
25#include "tlv320aic26.h" 24#include "tlv320aic26.h"
@@ -130,8 +129,7 @@ static int aic26_hw_params(struct snd_pcm_substream *substream,
130 struct snd_soc_dai *dai) 129 struct snd_soc_dai *dai)
131{ 130{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data; 131 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct snd_soc_device *socdev = rtd->socdev; 132 struct snd_soc_codec *codec = rtd->codec;
134 struct snd_soc_codec *codec = socdev->card->codec;
135 struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec); 133 struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
136 int fsref, divisor, wlen, pval, jval, dval, qval; 134 int fsref, divisor, wlen, pval, jval, dval, qval;
137 u16 reg; 135 u16 reg;
@@ -278,8 +276,8 @@ static struct snd_soc_dai_ops aic26_dai_ops = {
278 .set_fmt = aic26_set_fmt, 276 .set_fmt = aic26_set_fmt,
279}; 277};
280 278
281struct snd_soc_dai aic26_dai = { 279static struct snd_soc_dai_driver aic26_dai = {
282 .name = "tlv320aic26", 280 .name = "tlv320aic26-hifi",
283 .playback = { 281 .playback = {
284 .stream_name = "Playback", 282 .stream_name = "Playback",
285 .channels_min = 2, 283 .channels_min = 2,
@@ -296,7 +294,6 @@ struct snd_soc_dai aic26_dai = {
296 }, 294 },
297 .ops = &aic26_dai_ops, 295 .ops = &aic26_dai_ops,
298}; 296};
299EXPORT_SYMBOL_GPL(aic26_dai);
300 297
301/* --------------------------------------------------------------------- 298/* ---------------------------------------------------------------------
302 * ALSA controls 299 * ALSA controls
@@ -319,61 +316,6 @@ static const struct snd_kcontrol_new aic26_snd_controls[] = {
319}; 316};
320 317
321/* --------------------------------------------------------------------- 318/* ---------------------------------------------------------------------
322 * SoC CODEC portion of driver: probe and release routines
323 */
324static int aic26_probe(struct platform_device *pdev)
325{
326 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
327 struct snd_soc_codec *codec;
328 struct aic26 *aic26;
329 int ret, err;
330
331 dev_info(&pdev->dev, "Probing AIC26 SoC CODEC driver\n");
332 dev_dbg(&pdev->dev, "socdev=%p\n", socdev);
333 dev_dbg(&pdev->dev, "codec_data=%p\n", socdev->codec_data);
334
335 /* Fetch the relevant aic26 private data here (it's already been
336 * stored in the .codec pointer) */
337 aic26 = socdev->codec_data;
338 if (aic26 == NULL) {
339 dev_err(&pdev->dev, "aic26: missing codec pointer\n");
340 return -ENODEV;
341 }
342 codec = &aic26->codec;
343 socdev->card->codec = codec;
344
345 dev_dbg(&pdev->dev, "Registering PCMs, dev=%p, socdev->dev=%p\n",
346 &pdev->dev, socdev->dev);
347 /* register pcms */
348 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
349 if (ret < 0) {
350 dev_err(&pdev->dev, "aic26: failed to create pcms\n");
351 return -ENODEV;
352 }
353
354 /* register controls */
355 dev_dbg(&pdev->dev, "Registering controls\n");
356 err = snd_soc_add_controls(codec, aic26_snd_controls,
357 ARRAY_SIZE(aic26_snd_controls));
358 WARN_ON(err < 0);
359
360 return 0;
361}
362
363static int aic26_remove(struct platform_device *pdev)
364{
365 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
366 snd_soc_free_pcms(socdev);
367 return 0;
368}
369
370struct snd_soc_codec_device aic26_soc_codec_dev = {
371 .probe = aic26_probe,
372 .remove = aic26_remove,
373};
374EXPORT_SYMBOL_GPL(aic26_soc_codec_dev);
375
376/* ---------------------------------------------------------------------
377 * SPI device portion of driver: sysfs files for debugging 319 * SPI device portion of driver: sysfs files for debugging
378 */ 320 */
379 321
@@ -409,95 +351,95 @@ static ssize_t aic26_keyclick_set(struct device *dev,
409static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); 351static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
410 352
411/* --------------------------------------------------------------------- 353/* ---------------------------------------------------------------------
412 * SPI device portion of driver: probe and release routines and SPI 354 * SoC CODEC portion of driver: probe and release routines
413 * driver registration.
414 */ 355 */
415static int aic26_spi_probe(struct spi_device *spi) 356static int aic26_probe(struct snd_soc_codec *codec)
416{ 357{
417 struct aic26 *aic26; 358 struct aic26 *aic26 = snd_soc_codec_get_drvdata(codec);
418 int ret, i, reg; 359 int ret, err, i, reg;
419
420 dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
421
422 /* Allocate driver data */
423 aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
424 if (!aic26)
425 return -ENOMEM;
426
427 /* Initialize the driver data */
428 aic26->spi = spi;
429 dev_set_drvdata(&spi->dev, aic26);
430 360
431 /* Setup what we can in the codec structure so that the register 361 dev_info(codec->dev, "Probing AIC26 SoC CODEC driver\n");
432 * access functions will work as expected. More will be filled
433 * out when it is probed by the SoC CODEC part of this driver */
434 snd_soc_codec_set_drvdata(&aic26->codec, aic26);
435 aic26->codec.name = "aic26";
436 aic26->codec.owner = THIS_MODULE;
437 aic26->codec.dai = &aic26_dai;
438 aic26->codec.num_dai = 1;
439 aic26->codec.read = aic26_reg_read;
440 aic26->codec.write = aic26_reg_write;
441 aic26->master = 1;
442 mutex_init(&aic26->codec.mutex);
443 INIT_LIST_HEAD(&aic26->codec.dapm_widgets);
444 INIT_LIST_HEAD(&aic26->codec.dapm_paths);
445 aic26->codec.reg_cache_size = AIC26_NUM_REGS;
446 aic26->codec.reg_cache = aic26->reg_cache;
447
448 aic26_dai.dev = &spi->dev;
449 ret = snd_soc_register_dai(&aic26_dai);
450 if (ret != 0) {
451 dev_err(&spi->dev, "Failed to register DAI: %d\n", ret);
452 kfree(aic26);
453 return ret;
454 }
455 362
456 /* Reset the codec to power on defaults */ 363 /* Reset the codec to power on defaults */
457 aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); 364 aic26_reg_write(codec, AIC26_REG_RESET, 0xBB00);
458 365
459 /* Power up CODEC */ 366 /* Power up CODEC */
460 aic26_reg_write(&aic26->codec, AIC26_REG_POWER_CTRL, 0); 367 aic26_reg_write(codec, AIC26_REG_POWER_CTRL, 0);
461 368
462 /* Audio Control 3 (master mode, fsref rate) */ 369 /* Audio Control 3 (master mode, fsref rate) */
463 reg = aic26_reg_read(&aic26->codec, AIC26_REG_AUDIO_CTRL3); 370 reg = aic26_reg_read(codec, AIC26_REG_AUDIO_CTRL3);
464 reg &= ~0xf800; 371 reg &= ~0xf800;
465 reg |= 0x0800; /* set master mode */ 372 reg |= 0x0800; /* set master mode */
466 aic26_reg_write(&aic26->codec, AIC26_REG_AUDIO_CTRL3, reg); 373 aic26_reg_write(codec, AIC26_REG_AUDIO_CTRL3, reg);
467 374
468 /* Fill register cache */ 375 /* Fill register cache */
469 for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++) 376 for (i = 0; i < ARRAY_SIZE(aic26->reg_cache); i++)
470 aic26_reg_read(&aic26->codec, i); 377 aic26_reg_read(codec, i);
471 378
472 /* Register the sysfs files for debugging */ 379 /* Register the sysfs files for debugging */
473 /* Create SysFS files */ 380 /* Create SysFS files */
474 ret = device_create_file(&spi->dev, &dev_attr_keyclick); 381 ret = device_create_file(codec->dev, &dev_attr_keyclick);
475 if (ret) 382 if (ret)
476 dev_info(&spi->dev, "error creating sysfs files\n"); 383 dev_info(codec->dev, "error creating sysfs files\n");
477 384
478#if defined(CONFIG_SND_SOC_OF_SIMPLE) 385 /* register controls */
479 /* Tell the of_soc helper about this codec */ 386 dev_dbg(codec->dev, "Registering controls\n");
480 of_snd_soc_register_codec(&aic26_soc_codec_dev, aic26, &aic26_dai, 387 err = snd_soc_add_controls(codec, aic26_snd_controls,
481 spi->dev.archdata.of_node); 388 ARRAY_SIZE(aic26_snd_controls));
482#endif 389 WARN_ON(err < 0);
483 390
484 dev_dbg(&spi->dev, "SPI device initialized\n");
485 return 0; 391 return 0;
486} 392}
487 393
488static int aic26_spi_remove(struct spi_device *spi) 394static struct snd_soc_codec_driver aic26_soc_codec_dev = {
395 .probe = aic26_probe,
396 .read = aic26_reg_read,
397 .write = aic26_reg_write,
398 .reg_cache_size = AIC26_NUM_REGS,
399 .reg_word_size = sizeof(u16),
400};
401
402/* ---------------------------------------------------------------------
403 * SPI device portion of driver: probe and release routines and SPI
404 * driver registration.
405 */
406static int aic26_spi_probe(struct spi_device *spi)
489{ 407{
490 struct aic26 *aic26 = dev_get_drvdata(&spi->dev); 408 struct aic26 *aic26;
409 int ret;
491 410
492 snd_soc_unregister_dai(&aic26_dai); 411 dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
493 kfree(aic26); 412
413 /* Allocate driver data */
414 aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
415 if (!aic26)
416 return -ENOMEM;
494 417
418 /* Initialize the driver data */
419 aic26->spi = spi;
420 dev_set_drvdata(&spi->dev, aic26);
421 aic26->master = 1;
422
423 ret = snd_soc_register_codec(&spi->dev,
424 &aic26_soc_codec_dev, &aic26_dai, 1);
425 if (ret < 0)
426 kfree(aic26);
427 return ret;
428
429 dev_dbg(&spi->dev, "SPI device initialized\n");
430 return 0;
431}
432
433static int aic26_spi_remove(struct spi_device *spi)
434{
435 snd_soc_unregister_codec(&spi->dev);
436 kfree(spi_get_drvdata(spi));
495 return 0; 437 return 0;
496} 438}
497 439
498static struct spi_driver aic26_spi = { 440static struct spi_driver aic26_spi = {
499 .driver = { 441 .driver = {
500 .name = "tlv320aic26", 442 .name = "tlv320aic26-codec",
501 .owner = THIS_MODULE, 443 .owner = THIS_MODULE,
502 }, 444 },
503 .probe = aic26_spi_probe, 445 .probe = aic26_spi_probe,
diff --git a/sound/soc/codecs/tlv320aic26.h b/sound/soc/codecs/tlv320aic26.h
index 786ba16c945f..62b1f2261429 100644
--- a/sound/soc/codecs/tlv320aic26.h
+++ b/sound/soc/codecs/tlv320aic26.h
@@ -90,7 +90,4 @@ enum aic26_wlen {
90 AIC26_WLEN_32 = 3 << 10, 90 AIC26_WLEN_32 = 3 << 10,
91}; 91};
92 92
93extern struct snd_soc_dai aic26_dai;
94extern struct snd_soc_codec_device aic26_soc_codec_dev;
95
96#endif /* _TLV320AIC16_H_ */ 93#endif /* _TLV320AIC16_H_ */
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 71a69908ccf6..fc687790188b 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -12,11 +12,11 @@
12 * 12 *
13 * Notes: 13 * Notes:
14 * The AIC3X is a driver for a low power stereo audio 14 * The AIC3X is a driver for a low power stereo audio
15 * codecs aic31, aic32, aic33. 15 * codecs aic31, aic32, aic33, aic3007.
16 * 16 *
17 * It supports full aic33 codec functionality. 17 * It supports full aic33 codec functionality.
18 * The compatibility with aic32, aic31 is as follows: 18 * The compatibility with aic32, aic31 and aic3007 is as follows:
19 * aic32 | aic31 19 * aic32/aic3007 | aic31
20 * --------------------------------------- 20 * ---------------------------------------
21 * MONO_LOUT -> N/A | MONO_LOUT -> N/A 21 * MONO_LOUT -> N/A | MONO_LOUT -> N/A
22 * | IN1L -> LINE1L 22 * | IN1L -> LINE1L
@@ -61,13 +61,29 @@ static const char *aic3x_supply_names[AIC3X_NUM_SUPPLIES] = {
61 "DRVDD", /* ADC Analog and Output Driver Voltage */ 61 "DRVDD", /* ADC Analog and Output Driver Voltage */
62}; 62};
63 63
64struct aic3x_priv;
65
66struct aic3x_disable_nb {
67 struct notifier_block nb;
68 struct aic3x_priv *aic3x;
69};
70
64/* codec private data */ 71/* codec private data */
65struct aic3x_priv { 72struct aic3x_priv {
66 struct snd_soc_codec codec; 73 struct snd_soc_codec *codec;
67 struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; 74 struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES];
75 struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
76 enum snd_soc_control_type control_type;
77 struct aic3x_setup_data *setup;
78 void *control_data;
68 unsigned int sysclk; 79 unsigned int sysclk;
69 int master; 80 int master;
70 int gpio_reset; 81 int gpio_reset;
82 int power;
83#define AIC3X_MODEL_3X 0
84#define AIC3X_MODEL_33 1
85#define AIC3X_MODEL_3007 2
86 u16 model;
71}; 87};
72 88
73/* 89/*
@@ -106,62 +122,23 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
106}; 122};
107 123
108/* 124/*
109 * read aic3x register cache 125 * read from the aic3x register space. Only use for this function is if
126 * wanting to read volatile bits from those registers that has both read-only
127 * and read/write bits. All other cases should use snd_soc_read.
110 */ 128 */
111static inline unsigned int aic3x_read_reg_cache(struct snd_soc_codec *codec, 129static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
112 unsigned int reg) 130 u8 *value)
113{ 131{
114 u8 *cache = codec->reg_cache; 132 u8 *cache = codec->reg_cache;
115 if (reg >= AIC3X_CACHEREGNUM)
116 return -1;
117 return cache[reg];
118}
119 133
120/* 134 if (codec->cache_only)
121 * write aic3x register cache 135 return -EINVAL;
122 */
123static inline void aic3x_write_reg_cache(struct snd_soc_codec *codec,
124 u8 reg, u8 value)
125{
126 u8 *cache = codec->reg_cache;
127 if (reg >= AIC3X_CACHEREGNUM) 136 if (reg >= AIC3X_CACHEREGNUM)
128 return; 137 return -1;
129 cache[reg] = value;
130}
131
132/*
133 * write to the aic3x register space
134 */
135static int aic3x_write(struct snd_soc_codec *codec, unsigned int reg,
136 unsigned int value)
137{
138 u8 data[2];
139
140 /* data is
141 * D15..D8 aic3x register offset
142 * D7...D0 register data
143 */
144 data[0] = reg & 0xff;
145 data[1] = value & 0xff;
146
147 aic3x_write_reg_cache(codec, data[0], data[1]);
148 if (codec->hw_write(codec->control_data, data, 2) == 2)
149 return 0;
150 else
151 return -EIO;
152}
153
154/*
155 * read from the aic3x register space
156 */
157static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
158 u8 *value)
159{
160 *value = reg & 0xff;
161 138
162 value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]); 139 *value = codec->hw_read(codec, reg);
140 cache[reg] = *value;
163 141
164 aic3x_write_reg_cache(codec, reg, *value);
165 return 0; 142 return 0;
166} 143}
167 144
@@ -286,64 +263,102 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
286 SOC_DOUBLE_R_TLV("PCM Playback Volume", 263 SOC_DOUBLE_R_TLV("PCM Playback Volume",
287 LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv), 264 LDAC_VOL, RDAC_VOL, 0, 0x7f, 1, dac_tlv),
288 265
266 /*
267 * Output controls that map to output mixer switches. Note these are
268 * only for swapped L-to-R and R-to-L routes. See below stereo controls
269 * for direct L-to-L and R-to-R routes.
270 */
271 SOC_SINGLE_TLV("Left Line Mixer Line2R Bypass Volume",
272 LINE2R_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
273 SOC_SINGLE_TLV("Left Line Mixer PGAR Bypass Volume",
274 PGAR_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
275 SOC_SINGLE_TLV("Left Line Mixer DACR1 Playback Volume",
276 DACR1_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
277
278 SOC_SINGLE_TLV("Right Line Mixer Line2L Bypass Volume",
279 LINE2L_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
280 SOC_SINGLE_TLV("Right Line Mixer PGAL Bypass Volume",
281 PGAL_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
282 SOC_SINGLE_TLV("Right Line Mixer DACL1 Playback Volume",
283 DACL1_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
284
285 SOC_SINGLE_TLV("Left HP Mixer Line2R Bypass Volume",
286 LINE2R_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
287 SOC_SINGLE_TLV("Left HP Mixer PGAR Bypass Volume",
288 PGAR_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
289 SOC_SINGLE_TLV("Left HP Mixer DACR1 Playback Volume",
290 DACR1_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv),
291
292 SOC_SINGLE_TLV("Right HP Mixer Line2L Bypass Volume",
293 LINE2L_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
294 SOC_SINGLE_TLV("Right HP Mixer PGAL Bypass Volume",
295 PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
296 SOC_SINGLE_TLV("Right HP Mixer DACL1 Playback Volume",
297 DACL1_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
298
299 SOC_SINGLE_TLV("Left HPCOM Mixer Line2R Bypass Volume",
300 LINE2R_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
301 SOC_SINGLE_TLV("Left HPCOM Mixer PGAR Bypass Volume",
302 PGAR_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
303 SOC_SINGLE_TLV("Left HPCOM Mixer DACR1 Playback Volume",
304 DACR1_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
305
306 SOC_SINGLE_TLV("Right HPCOM Mixer Line2L Bypass Volume",
307 LINE2L_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
308 SOC_SINGLE_TLV("Right HPCOM Mixer PGAL Bypass Volume",
309 PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
310 SOC_SINGLE_TLV("Right HPCOM Mixer DACL1 Playback Volume",
311 DACL1_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
312
313 /* Stereo output controls for direct L-to-L and R-to-R routes */
314 SOC_DOUBLE_R_TLV("Line Line2 Bypass Volume",
315 LINE2L_2_LLOPM_VOL, LINE2R_2_RLOPM_VOL,
316 0, 118, 1, output_stage_tlv),
317 SOC_DOUBLE_R_TLV("Line PGA Bypass Volume",
318 PGAL_2_LLOPM_VOL, PGAR_2_RLOPM_VOL,
319 0, 118, 1, output_stage_tlv),
289 SOC_DOUBLE_R_TLV("Line DAC Playback Volume", 320 SOC_DOUBLE_R_TLV("Line DAC Playback Volume",
290 DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL, 321 DACL1_2_LLOPM_VOL, DACR1_2_RLOPM_VOL,
291 0, 118, 1, output_stage_tlv), 322 0, 118, 1, output_stage_tlv),
292 SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0), 323
293 SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0), 324 SOC_DOUBLE_R_TLV("Mono Line2 Bypass Volume",
294 SOC_DOUBLE_R_TLV("LineL DAC Playback Volume", 325 LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL,
295 DACL1_2_LLOPM_VOL, DACR1_2_LLOPM_VOL,
296 0, 118, 1, output_stage_tlv),
297 SOC_SINGLE_TLV("LineL Left PGA Bypass Playback Volume",
298 PGAL_2_LLOPM_VOL, 0, 118, 1, output_stage_tlv),
299 SOC_SINGLE_TLV("LineR Right PGA Bypass Playback Volume",
300 PGAR_2_RLOPM_VOL, 0, 118, 1, output_stage_tlv),
301 SOC_DOUBLE_R_TLV("LineL Line2 Bypass Playback Volume",
302 LINE2L_2_LLOPM_VOL, LINE2R_2_LLOPM_VOL,
303 0, 118, 1, output_stage_tlv), 326 0, 118, 1, output_stage_tlv),
304 SOC_DOUBLE_R_TLV("LineR Line2 Bypass Playback Volume", 327 SOC_DOUBLE_R_TLV("Mono PGA Bypass Volume",
305 LINE2L_2_RLOPM_VOL, LINE2R_2_RLOPM_VOL, 328 PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL,
306 0, 118, 1, output_stage_tlv), 329 0, 118, 1, output_stage_tlv),
307
308 SOC_DOUBLE_R_TLV("Mono DAC Playback Volume", 330 SOC_DOUBLE_R_TLV("Mono DAC Playback Volume",
309 DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL, 331 DACL1_2_MONOLOPM_VOL, DACR1_2_MONOLOPM_VOL,
310 0, 118, 1, output_stage_tlv), 332 0, 118, 1, output_stage_tlv),
311 SOC_SINGLE("Mono DAC Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0), 333
312 SOC_DOUBLE_R_TLV("Mono PGA Bypass Playback Volume", 334 SOC_DOUBLE_R_TLV("HP Line2 Bypass Volume",
313 PGAL_2_MONOLOPM_VOL, PGAR_2_MONOLOPM_VOL, 335 LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
314 0, 118, 1, output_stage_tlv), 336 0, 118, 1, output_stage_tlv),
315 SOC_DOUBLE_R_TLV("Mono Line2 Bypass Playback Volume", 337 SOC_DOUBLE_R_TLV("HP PGA Bypass Volume",
316 LINE2L_2_MONOLOPM_VOL, LINE2R_2_MONOLOPM_VOL, 338 PGAL_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
317 0, 118, 1, output_stage_tlv), 339 0, 118, 1, output_stage_tlv),
318
319 SOC_DOUBLE_R_TLV("HP DAC Playback Volume", 340 SOC_DOUBLE_R_TLV("HP DAC Playback Volume",
320 DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL, 341 DACL1_2_HPLOUT_VOL, DACR1_2_HPROUT_VOL,
321 0, 118, 1, output_stage_tlv), 342 0, 118, 1, output_stage_tlv),
322 SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, 343
323 0x01, 0), 344 SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Volume",
324 SOC_DOUBLE_R_TLV("HP Right PGA Bypass Playback Volume", 345 LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
325 PGAR_2_HPLOUT_VOL, PGAR_2_HPROUT_VOL,
326 0, 118, 1, output_stage_tlv), 346 0, 118, 1, output_stage_tlv),
327 SOC_SINGLE_TLV("HPL PGA Bypass Playback Volume", 347 SOC_DOUBLE_R_TLV("HPCOM PGA Bypass Volume",
328 PGAL_2_HPLOUT_VOL, 0, 118, 1, output_stage_tlv), 348 PGAL_2_HPLCOM_VOL, PGAR_2_HPRCOM_VOL,
329 SOC_SINGLE_TLV("HPR PGA Bypass Playback Volume",
330 PGAL_2_HPROUT_VOL, 0, 118, 1, output_stage_tlv),
331 SOC_DOUBLE_R_TLV("HP Line2 Bypass Playback Volume",
332 LINE2L_2_HPLOUT_VOL, LINE2R_2_HPROUT_VOL,
333 0, 118, 1, output_stage_tlv), 349 0, 118, 1, output_stage_tlv),
334
335 SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume", 350 SOC_DOUBLE_R_TLV("HPCOM DAC Playback Volume",
336 DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL, 351 DACL1_2_HPLCOM_VOL, DACR1_2_HPRCOM_VOL,
337 0, 118, 1, output_stage_tlv), 352 0, 118, 1, output_stage_tlv),
338 SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, 353
354 /* Output pin mute controls */
355 SOC_DOUBLE_R("Line Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
356 0x01, 0),
357 SOC_SINGLE("Mono Playback Switch", MONOLOPM_CTRL, 3, 0x01, 0),
358 SOC_DOUBLE_R("HP Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
359 0x01, 0),
360 SOC_DOUBLE_R("HPCOM Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
339 0x01, 0), 361 0x01, 0),
340 SOC_SINGLE_TLV("HPLCOM PGA Bypass Playback Volume",
341 PGAL_2_HPLCOM_VOL, 0, 118, 1, output_stage_tlv),
342 SOC_SINGLE_TLV("HPRCOM PGA Bypass Playback Volume",
343 PGAL_2_HPRCOM_VOL, 0, 118, 1, output_stage_tlv),
344 SOC_DOUBLE_R_TLV("HPCOM Line2 Bypass Playback Volume",
345 LINE2L_2_HPLCOM_VOL, LINE2R_2_HPRCOM_VOL,
346 0, 118, 1, output_stage_tlv),
347 362
348 /* 363 /*
349 * Note: enable Automatic input Gain Controller with care. It can 364 * Note: enable Automatic input Gain Controller with care. It can
@@ -359,6 +374,14 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
359 SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]), 374 SOC_ENUM("ADC HPF Cut-off", aic3x_enum[ADC_HPF_ENUM]),
360}; 375};
361 376
377/*
378 * Class-D amplifier gain. From 0 to 18 dB in 6 dB steps
379 */
380static DECLARE_TLV_DB_SCALE(classd_amp_tlv, 0, 600, 0);
381
382static const struct snd_kcontrol_new aic3x_classd_amp_gain_ctrl =
383 SOC_DOUBLE_TLV("Class-D Amplifier Gain", CLASSD_CTRL, 6, 4, 3, 0, classd_amp_tlv);
384
362/* Left DAC Mux */ 385/* Left DAC Mux */
363static const struct snd_kcontrol_new aic3x_left_dac_mux_controls = 386static const struct snd_kcontrol_new aic3x_left_dac_mux_controls =
364SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]); 387SOC_DAPM_ENUM("Route", aic3x_enum[LDAC_ENUM]);
@@ -375,22 +398,74 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LHPCOM_ENUM]);
375static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls = 398static const struct snd_kcontrol_new aic3x_right_hpcom_mux_controls =
376SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]); 399SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]);
377 400
378/* Left DAC_L1 Mixer */ 401/* Left Line Mixer */
379static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = { 402static const struct snd_kcontrol_new aic3x_left_line_mixer_controls[] = {
380 SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), 403 SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
381 SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0), 404 SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
382 SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0), 405 SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
383 SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), 406 SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
384 SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), 407 SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
408 SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
409};
410
411/* Right Line Mixer */
412static const struct snd_kcontrol_new aic3x_right_line_mixer_controls[] = {
413 SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
414 SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
415 SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
416 SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
417 SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
418 SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
419};
420
421/* Mono Mixer */
422static const struct snd_kcontrol_new aic3x_mono_mixer_controls[] = {
423 SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
424 SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
425 SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
426 SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
427 SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
428 SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
429};
430
431/* Left HP Mixer */
432static const struct snd_kcontrol_new aic3x_left_hp_mixer_controls[] = {
433 SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
434 SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
435 SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
436 SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLOUT_VOL, 7, 1, 0),
437 SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
438 SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLOUT_VOL, 7, 1, 0),
439};
440
441/* Right HP Mixer */
442static const struct snd_kcontrol_new aic3x_right_hp_mixer_controls[] = {
443 SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPROUT_VOL, 7, 1, 0),
444 SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
445 SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPROUT_VOL, 7, 1, 0),
446 SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
447 SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
448 SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
449};
450
451/* Left HPCOM Mixer */
452static const struct snd_kcontrol_new aic3x_left_hpcom_mixer_controls[] = {
453 SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
454 SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
455 SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
456 SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPLCOM_VOL, 7, 1, 0),
457 SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
458 SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPLCOM_VOL, 7, 1, 0),
385}; 459};
386 460
387/* Right DAC_R1 Mixer */ 461/* Right HPCOM Mixer */
388static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = { 462static const struct snd_kcontrol_new aic3x_right_hpcom_mixer_controls[] = {
389 SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0), 463 SOC_DAPM_SINGLE("Line2L Bypass Switch", LINE2L_2_HPRCOM_VOL, 7, 1, 0),
390 SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), 464 SOC_DAPM_SINGLE("PGAL Bypass Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
391 SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0), 465 SOC_DAPM_SINGLE("DACL1 Switch", DACL1_2_HPRCOM_VOL, 7, 1, 0),
392 SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), 466 SOC_DAPM_SINGLE("Line2R Bypass Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
393 SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), 467 SOC_DAPM_SINGLE("PGAR Bypass Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
468 SOC_DAPM_SINGLE("DACR1 Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
394}; 469};
395 470
396/* Left PGA Mixer */ 471/* Left PGA Mixer */
@@ -427,54 +502,11 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LINE2L_ENUM]);
427static const struct snd_kcontrol_new aic3x_right_line2_mux_controls = 502static const struct snd_kcontrol_new aic3x_right_line2_mux_controls =
428SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]); 503SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]);
429 504
430/* Left PGA Bypass Mixer */
431static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = {
432 SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
433 SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
434 SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
435 SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
436 SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
437 SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
438 SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
439};
440
441/* Right PGA Bypass Mixer */
442static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = {
443 SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
444 SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
445 SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
446 SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
447 SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
448 SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
449 SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
450};
451
452/* Left Line2 Bypass Mixer */
453static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = {
454 SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
455 SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
456 SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
457 SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
458 SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
459};
460
461/* Right Line2 Bypass Mixer */
462static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = {
463 SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
464 SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
465 SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
466 SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
467 SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
468};
469
470static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { 505static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
471 /* Left DAC to Left Outputs */ 506 /* Left DAC to Left Outputs */
472 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", DAC_PWR, 7, 0), 507 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", DAC_PWR, 7, 0),
473 SND_SOC_DAPM_MUX("Left DAC Mux", SND_SOC_NOPM, 0, 0, 508 SND_SOC_DAPM_MUX("Left DAC Mux", SND_SOC_NOPM, 0, 0,
474 &aic3x_left_dac_mux_controls), 509 &aic3x_left_dac_mux_controls),
475 SND_SOC_DAPM_MIXER("Left DAC_L1 Mixer", SND_SOC_NOPM, 0, 0,
476 &aic3x_left_dac_mixer_controls[0],
477 ARRAY_SIZE(aic3x_left_dac_mixer_controls)),
478 SND_SOC_DAPM_MUX("Left HPCOM Mux", SND_SOC_NOPM, 0, 0, 510 SND_SOC_DAPM_MUX("Left HPCOM Mux", SND_SOC_NOPM, 0, 0,
479 &aic3x_left_hpcom_mux_controls), 511 &aic3x_left_hpcom_mux_controls),
480 SND_SOC_DAPM_PGA("Left Line Out", LLOPM_CTRL, 0, 0, NULL, 0), 512 SND_SOC_DAPM_PGA("Left Line Out", LLOPM_CTRL, 0, 0, NULL, 0),
@@ -485,9 +517,6 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
485 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", DAC_PWR, 6, 0), 517 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", DAC_PWR, 6, 0),
486 SND_SOC_DAPM_MUX("Right DAC Mux", SND_SOC_NOPM, 0, 0, 518 SND_SOC_DAPM_MUX("Right DAC Mux", SND_SOC_NOPM, 0, 0,
487 &aic3x_right_dac_mux_controls), 519 &aic3x_right_dac_mux_controls),
488 SND_SOC_DAPM_MIXER("Right DAC_R1 Mixer", SND_SOC_NOPM, 0, 0,
489 &aic3x_right_dac_mixer_controls[0],
490 ARRAY_SIZE(aic3x_right_dac_mixer_controls)),
491 SND_SOC_DAPM_MUX("Right HPCOM Mux", SND_SOC_NOPM, 0, 0, 520 SND_SOC_DAPM_MUX("Right HPCOM Mux", SND_SOC_NOPM, 0, 0,
492 &aic3x_right_hpcom_mux_controls), 521 &aic3x_right_hpcom_mux_controls),
493 SND_SOC_DAPM_PGA("Right Line Out", RLOPM_CTRL, 0, 0, NULL, 0), 522 SND_SOC_DAPM_PGA("Right Line Out", RLOPM_CTRL, 0, 0, NULL, 0),
@@ -551,25 +580,28 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
551 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD", 580 SND_SOC_DAPM_REG(snd_soc_dapm_micbias, "Mic Bias AVDD",
552 MICBIAS_CTRL, 6, 3, 3, 0), 581 MICBIAS_CTRL, 6, 3, 3, 0),
553 582
554 /* Left PGA to Left Output bypass */ 583 /* Output mixers */
555 SND_SOC_DAPM_MIXER("Left PGA Bypass Mixer", SND_SOC_NOPM, 0, 0, 584 SND_SOC_DAPM_MIXER("Left Line Mixer", SND_SOC_NOPM, 0, 0,
556 &aic3x_left_pga_bp_mixer_controls[0], 585 &aic3x_left_line_mixer_controls[0],
557 ARRAY_SIZE(aic3x_left_pga_bp_mixer_controls)), 586 ARRAY_SIZE(aic3x_left_line_mixer_controls)),
558 587 SND_SOC_DAPM_MIXER("Right Line Mixer", SND_SOC_NOPM, 0, 0,
559 /* Right PGA to Right Output bypass */ 588 &aic3x_right_line_mixer_controls[0],
560 SND_SOC_DAPM_MIXER("Right PGA Bypass Mixer", SND_SOC_NOPM, 0, 0, 589 ARRAY_SIZE(aic3x_right_line_mixer_controls)),
561 &aic3x_right_pga_bp_mixer_controls[0], 590 SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
562 ARRAY_SIZE(aic3x_right_pga_bp_mixer_controls)), 591 &aic3x_mono_mixer_controls[0],
563 592 ARRAY_SIZE(aic3x_mono_mixer_controls)),
564 /* Left Line2 to Left Output bypass */ 593 SND_SOC_DAPM_MIXER("Left HP Mixer", SND_SOC_NOPM, 0, 0,
565 SND_SOC_DAPM_MIXER("Left Line2 Bypass Mixer", SND_SOC_NOPM, 0, 0, 594 &aic3x_left_hp_mixer_controls[0],
566 &aic3x_left_line2_bp_mixer_controls[0], 595 ARRAY_SIZE(aic3x_left_hp_mixer_controls)),
567 ARRAY_SIZE(aic3x_left_line2_bp_mixer_controls)), 596 SND_SOC_DAPM_MIXER("Right HP Mixer", SND_SOC_NOPM, 0, 0,
568 597 &aic3x_right_hp_mixer_controls[0],
569 /* Right Line2 to Right Output bypass */ 598 ARRAY_SIZE(aic3x_right_hp_mixer_controls)),
570 SND_SOC_DAPM_MIXER("Right Line2 Bypass Mixer", SND_SOC_NOPM, 0, 0, 599 SND_SOC_DAPM_MIXER("Left HPCOM Mixer", SND_SOC_NOPM, 0, 0,
571 &aic3x_right_line2_bp_mixer_controls[0], 600 &aic3x_left_hpcom_mixer_controls[0],
572 ARRAY_SIZE(aic3x_right_line2_bp_mixer_controls)), 601 ARRAY_SIZE(aic3x_left_hpcom_mixer_controls)),
602 SND_SOC_DAPM_MIXER("Right HPCOM Mixer", SND_SOC_NOPM, 0, 0,
603 &aic3x_right_hpcom_mixer_controls[0],
604 ARRAY_SIZE(aic3x_right_hpcom_mixer_controls)),
573 605
574 SND_SOC_DAPM_OUTPUT("LLOUT"), 606 SND_SOC_DAPM_OUTPUT("LLOUT"),
575 SND_SOC_DAPM_OUTPUT("RLOUT"), 607 SND_SOC_DAPM_OUTPUT("RLOUT"),
@@ -585,69 +617,26 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
585 SND_SOC_DAPM_INPUT("LINE1R"), 617 SND_SOC_DAPM_INPUT("LINE1R"),
586 SND_SOC_DAPM_INPUT("LINE2L"), 618 SND_SOC_DAPM_INPUT("LINE2L"),
587 SND_SOC_DAPM_INPUT("LINE2R"), 619 SND_SOC_DAPM_INPUT("LINE2R"),
588};
589
590static const struct snd_soc_dapm_route intercon[] = {
591 /* Left Output */
592 {"Left DAC Mux", "DAC_L1", "Left DAC"},
593 {"Left DAC Mux", "DAC_L2", "Left DAC"},
594 {"Left DAC Mux", "DAC_L3", "Left DAC"},
595
596 {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"},
597 {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"},
598 {"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"},
599 {"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"},
600 {"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"},
601 {"Left Line Out", NULL, "Left DAC Mux"},
602 {"Left HP Out", NULL, "Left DAC Mux"},
603
604 {"Left HPCOM Mux", "differential of HPLOUT", "Left DAC_L1 Mixer"},
605 {"Left HPCOM Mux", "constant VCM", "Left DAC_L1 Mixer"},
606 {"Left HPCOM Mux", "single-ended", "Left DAC_L1 Mixer"},
607
608 {"Left Line Out", NULL, "Left DAC_L1 Mixer"},
609 {"Mono Out", NULL, "Left DAC_L1 Mixer"},
610 {"Left HP Out", NULL, "Left DAC_L1 Mixer"},
611 {"Left HP Com", NULL, "Left HPCOM Mux"},
612
613 {"LLOUT", NULL, "Left Line Out"},
614 {"LLOUT", NULL, "Left Line Out"},
615 {"HPLOUT", NULL, "Left HP Out"},
616 {"HPLCOM", NULL, "Left HP Com"},
617
618 /* Right Output */
619 {"Right DAC Mux", "DAC_R1", "Right DAC"},
620 {"Right DAC Mux", "DAC_R2", "Right DAC"},
621 {"Right DAC Mux", "DAC_R3", "Right DAC"},
622 620
623 {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"}, 621 /*
624 {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"}, 622 * Virtual output pin to detection block inside codec. This can be
625 {"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"}, 623 * used to keep codec bias on if gpio or detection features are needed.
626 {"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"}, 624 * Force pin on or construct a path with an input jack and mic bias
627 {"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"}, 625 * widgets.
628 {"Right Line Out", NULL, "Right DAC Mux"}, 626 */
629 {"Right HP Out", NULL, "Right DAC Mux"}, 627 SND_SOC_DAPM_OUTPUT("Detection"),
628};
630 629
631 {"Right HPCOM Mux", "differential of HPROUT", "Right DAC_R1 Mixer"}, 630static const struct snd_soc_dapm_widget aic3007_dapm_widgets[] = {
632 {"Right HPCOM Mux", "constant VCM", "Right DAC_R1 Mixer"}, 631 /* Class-D outputs */
633 {"Right HPCOM Mux", "single-ended", "Right DAC_R1 Mixer"}, 632 SND_SOC_DAPM_PGA("Left Class-D Out", CLASSD_CTRL, 3, 0, NULL, 0),
634 {"Right HPCOM Mux", "differential of HPLCOM", "Right DAC_R1 Mixer"}, 633 SND_SOC_DAPM_PGA("Right Class-D Out", CLASSD_CTRL, 2, 0, NULL, 0),
635 {"Right HPCOM Mux", "external feedback", "Right DAC_R1 Mixer"},
636 634
637 {"Right Line Out", NULL, "Right DAC_R1 Mixer"}, 635 SND_SOC_DAPM_OUTPUT("SPOP"),
638 {"Mono Out", NULL, "Right DAC_R1 Mixer"}, 636 SND_SOC_DAPM_OUTPUT("SPOM"),
639 {"Right HP Out", NULL, "Right DAC_R1 Mixer"}, 637};
640 {"Right HP Com", NULL, "Right HPCOM Mux"},
641
642 {"RLOUT", NULL, "Right Line Out"},
643 {"RLOUT", NULL, "Right Line Out"},
644 {"HPROUT", NULL, "Right HP Out"},
645 {"HPRCOM", NULL, "Right HP Com"},
646
647 /* Mono Output */
648 {"MONO_LOUT", NULL, "Mono Out"},
649 {"MONO_LOUT", NULL, "Mono Out"},
650 638
639static const struct snd_soc_dapm_route intercon[] = {
651 /* Left Input */ 640 /* Left Input */
652 {"Left Line1L Mux", "single-ended", "LINE1L"}, 641 {"Left Line1L Mux", "single-ended", "LINE1L"},
653 {"Left Line1L Mux", "differential", "LINE1L"}, 642 {"Left Line1L Mux", "differential", "LINE1L"},
@@ -680,74 +669,6 @@ static const struct snd_soc_dapm_route intercon[] = {
680 {"Right ADC", NULL, "Right PGA Mixer"}, 669 {"Right ADC", NULL, "Right PGA Mixer"},
681 {"Right ADC", NULL, "GPIO1 dmic modclk"}, 670 {"Right ADC", NULL, "GPIO1 dmic modclk"},
682 671
683 /* Left PGA Bypass */
684 {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"},
685 {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"},
686 {"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"},
687 {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"},
688 {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"},
689 {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"},
690 {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"},
691
692 {"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"},
693 {"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"},
694 {"Left HPCOM Mux", "single-ended", "Left PGA Bypass Mixer"},
695
696 {"Left Line Out", NULL, "Left PGA Bypass Mixer"},
697 {"Mono Out", NULL, "Left PGA Bypass Mixer"},
698 {"Left HP Out", NULL, "Left PGA Bypass Mixer"},
699
700 /* Right PGA Bypass */
701 {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"},
702 {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"},
703 {"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"},
704 {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"},
705 {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"},
706 {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"},
707 {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"},
708
709 {"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"},
710 {"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"},
711 {"Right HPCOM Mux", "single-ended", "Right PGA Bypass Mixer"},
712 {"Right HPCOM Mux", "differential of HPLCOM", "Right PGA Bypass Mixer"},
713 {"Right HPCOM Mux", "external feedback", "Right PGA Bypass Mixer"},
714
715 {"Right Line Out", NULL, "Right PGA Bypass Mixer"},
716 {"Mono Out", NULL, "Right PGA Bypass Mixer"},
717 {"Right HP Out", NULL, "Right PGA Bypass Mixer"},
718
719 /* Left Line2 Bypass */
720 {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"},
721 {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"},
722 {"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"},
723 {"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"},
724 {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"},
725
726 {"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"},
727 {"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"},
728 {"Left HPCOM Mux", "single-ended", "Left Line2 Bypass Mixer"},
729
730 {"Left Line Out", NULL, "Left Line2 Bypass Mixer"},
731 {"Mono Out", NULL, "Left Line2 Bypass Mixer"},
732 {"Left HP Out", NULL, "Left Line2 Bypass Mixer"},
733
734 /* Right Line2 Bypass */
735 {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"},
736 {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"},
737 {"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"},
738 {"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"},
739 {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"},
740
741 {"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"},
742 {"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"},
743 {"Right HPCOM Mux", "single-ended", "Right Line2 Bypass Mixer"},
744 {"Right HPCOM Mux", "differential of HPLCOM", "Right Line2 Bypass Mixer"},
745 {"Right HPCOM Mux", "external feedback", "Right Line2 Bypass Mixer"},
746
747 {"Right Line Out", NULL, "Right Line2 Bypass Mixer"},
748 {"Mono Out", NULL, "Right Line2 Bypass Mixer"},
749 {"Right HP Out", NULL, "Right Line2 Bypass Mixer"},
750
751 /* 672 /*
752 * Logical path between digital mic enable and GPIO1 modulator clock 673 * Logical path between digital mic enable and GPIO1 modulator clock
753 * output function 674 * output function
@@ -755,16 +676,131 @@ static const struct snd_soc_dapm_route intercon[] = {
755 {"GPIO1 dmic modclk", NULL, "DMic Rate 128"}, 676 {"GPIO1 dmic modclk", NULL, "DMic Rate 128"},
756 {"GPIO1 dmic modclk", NULL, "DMic Rate 64"}, 677 {"GPIO1 dmic modclk", NULL, "DMic Rate 64"},
757 {"GPIO1 dmic modclk", NULL, "DMic Rate 32"}, 678 {"GPIO1 dmic modclk", NULL, "DMic Rate 32"},
679
680 /* Left DAC Output */
681 {"Left DAC Mux", "DAC_L1", "Left DAC"},
682 {"Left DAC Mux", "DAC_L2", "Left DAC"},
683 {"Left DAC Mux", "DAC_L3", "Left DAC"},
684
685 /* Right DAC Output */
686 {"Right DAC Mux", "DAC_R1", "Right DAC"},
687 {"Right DAC Mux", "DAC_R2", "Right DAC"},
688 {"Right DAC Mux", "DAC_R3", "Right DAC"},
689
690 /* Left Line Output */
691 {"Left Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
692 {"Left Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
693 {"Left Line Mixer", "DACL1 Switch", "Left DAC Mux"},
694 {"Left Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
695 {"Left Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
696 {"Left Line Mixer", "DACR1 Switch", "Right DAC Mux"},
697
698 {"Left Line Out", NULL, "Left Line Mixer"},
699 {"Left Line Out", NULL, "Left DAC Mux"},
700 {"LLOUT", NULL, "Left Line Out"},
701
702 /* Right Line Output */
703 {"Right Line Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
704 {"Right Line Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
705 {"Right Line Mixer", "DACL1 Switch", "Left DAC Mux"},
706 {"Right Line Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
707 {"Right Line Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
708 {"Right Line Mixer", "DACR1 Switch", "Right DAC Mux"},
709
710 {"Right Line Out", NULL, "Right Line Mixer"},
711 {"Right Line Out", NULL, "Right DAC Mux"},
712 {"RLOUT", NULL, "Right Line Out"},
713
714 /* Mono Output */
715 {"Mono Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
716 {"Mono Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
717 {"Mono Mixer", "DACL1 Switch", "Left DAC Mux"},
718 {"Mono Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
719 {"Mono Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
720 {"Mono Mixer", "DACR1 Switch", "Right DAC Mux"},
721
722 {"Mono Out", NULL, "Mono Mixer"},
723 {"MONO_LOUT", NULL, "Mono Out"},
724
725 /* Left HP Output */
726 {"Left HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
727 {"Left HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
728 {"Left HP Mixer", "DACL1 Switch", "Left DAC Mux"},
729 {"Left HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
730 {"Left HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
731 {"Left HP Mixer", "DACR1 Switch", "Right DAC Mux"},
732
733 {"Left HP Out", NULL, "Left HP Mixer"},
734 {"Left HP Out", NULL, "Left DAC Mux"},
735 {"HPLOUT", NULL, "Left HP Out"},
736
737 /* Right HP Output */
738 {"Right HP Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
739 {"Right HP Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
740 {"Right HP Mixer", "DACL1 Switch", "Left DAC Mux"},
741 {"Right HP Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
742 {"Right HP Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
743 {"Right HP Mixer", "DACR1 Switch", "Right DAC Mux"},
744
745 {"Right HP Out", NULL, "Right HP Mixer"},
746 {"Right HP Out", NULL, "Right DAC Mux"},
747 {"HPROUT", NULL, "Right HP Out"},
748
749 /* Left HPCOM Output */
750 {"Left HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
751 {"Left HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
752 {"Left HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"},
753 {"Left HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
754 {"Left HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
755 {"Left HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"},
756
757 {"Left HPCOM Mux", "differential of HPLOUT", "Left HP Mixer"},
758 {"Left HPCOM Mux", "constant VCM", "Left HPCOM Mixer"},
759 {"Left HPCOM Mux", "single-ended", "Left HPCOM Mixer"},
760 {"Left HP Com", NULL, "Left HPCOM Mux"},
761 {"HPLCOM", NULL, "Left HP Com"},
762
763 /* Right HPCOM Output */
764 {"Right HPCOM Mixer", "Line2L Bypass Switch", "Left Line2L Mux"},
765 {"Right HPCOM Mixer", "PGAL Bypass Switch", "Left PGA Mixer"},
766 {"Right HPCOM Mixer", "DACL1 Switch", "Left DAC Mux"},
767 {"Right HPCOM Mixer", "Line2R Bypass Switch", "Right Line2R Mux"},
768 {"Right HPCOM Mixer", "PGAR Bypass Switch", "Right PGA Mixer"},
769 {"Right HPCOM Mixer", "DACR1 Switch", "Right DAC Mux"},
770
771 {"Right HPCOM Mux", "differential of HPROUT", "Right HP Mixer"},
772 {"Right HPCOM Mux", "constant VCM", "Right HPCOM Mixer"},
773 {"Right HPCOM Mux", "single-ended", "Right HPCOM Mixer"},
774 {"Right HPCOM Mux", "differential of HPLCOM", "Left HPCOM Mixer"},
775 {"Right HPCOM Mux", "external feedback", "Right HPCOM Mixer"},
776 {"Right HP Com", NULL, "Right HPCOM Mux"},
777 {"HPRCOM", NULL, "Right HP Com"},
778};
779
780static const struct snd_soc_dapm_route intercon_3007[] = {
781 /* Class-D outputs */
782 {"Left Class-D Out", NULL, "Left Line Out"},
783 {"Right Class-D Out", NULL, "Left Line Out"},
784 {"SPOP", NULL, "Left Class-D Out"},
785 {"SPOM", NULL, "Right Class-D Out"},
758}; 786};
759 787
760static int aic3x_add_widgets(struct snd_soc_codec *codec) 788static int aic3x_add_widgets(struct snd_soc_codec *codec)
761{ 789{
790 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
791
762 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, 792 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
763 ARRAY_SIZE(aic3x_dapm_widgets)); 793 ARRAY_SIZE(aic3x_dapm_widgets));
764 794
765 /* set up audio path interconnects */ 795 /* set up audio path interconnects */
766 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 796 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
767 797
798 if (aic3x->model == AIC3X_MODEL_3007) {
799 snd_soc_dapm_new_controls(codec, aic3007_dapm_widgets,
800 ARRAY_SIZE(aic3007_dapm_widgets));
801 snd_soc_dapm_add_routes(codec, intercon_3007, ARRAY_SIZE(intercon_3007));
802 }
803
768 return 0; 804 return 0;
769} 805}
770 806
@@ -773,8 +809,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
773 struct snd_soc_dai *dai) 809 struct snd_soc_dai *dai)
774{ 810{
775 struct snd_soc_pcm_runtime *rtd = substream->private_data; 811 struct snd_soc_pcm_runtime *rtd = substream->private_data;
776 struct snd_soc_device *socdev = rtd->socdev; 812 struct snd_soc_codec *codec =rtd->codec;
777 struct snd_soc_codec *codec = socdev->card->codec;
778 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec); 813 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
779 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0; 814 int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
780 u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1; 815 u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
@@ -783,8 +818,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
783 int clk; 818 int clk;
784 819
785 /* select data word length */ 820 /* select data word length */
786 data = 821 data = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
787 aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & (~(0x3 << 4));
788 switch (params_format(params)) { 822 switch (params_format(params)) {
789 case SNDRV_PCM_FORMAT_S16_LE: 823 case SNDRV_PCM_FORMAT_S16_LE:
790 break; 824 break;
@@ -798,7 +832,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
798 data |= (0x03 << 4); 832 data |= (0x03 << 4);
799 break; 833 break;
800 } 834 }
801 aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, data); 835 snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, data);
802 836
803 /* Fsref can be 44100 or 48000 */ 837 /* Fsref can be 44100 or 48000 */
804 fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000; 838 fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000;
@@ -813,17 +847,17 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
813 847
814 if (bypass_pll) { 848 if (bypass_pll) {
815 pll_q &= 0xf; 849 pll_q &= 0xf;
816 aic3x_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT); 850 snd_soc_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
817 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV); 851 snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
818 /* disable PLL if it is bypassed */ 852 /* disable PLL if it is bypassed */
819 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 853 reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
820 aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE); 854 snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
821 855
822 } else { 856 } else {
823 aic3x_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV); 857 snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
824 /* enable PLL when it is used */ 858 /* enable PLL when it is used */
825 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 859 reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
826 aic3x_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE); 860 snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
827 } 861 }
828 862
829 /* Route Left DAC to left channel input and 863 /* Route Left DAC to left channel input and
@@ -832,7 +866,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
832 data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000; 866 data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000;
833 if (params_rate(params) >= 64000) 867 if (params_rate(params) >= 64000)
834 data |= DUAL_RATE_MODE; 868 data |= DUAL_RATE_MODE;
835 aic3x_write(codec, AIC3X_CODEC_DATAPATH_REG, data); 869 snd_soc_write(codec, AIC3X_CODEC_DATAPATH_REG, data);
836 870
837 /* codec sample rate select */ 871 /* codec sample rate select */
838 data = (fsref * 20) / params_rate(params); 872 data = (fsref * 20) / params_rate(params);
@@ -841,7 +875,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
841 data /= 5; 875 data /= 5;
842 data -= 2; 876 data -= 2;
843 data |= (data << 4); 877 data |= (data << 4);
844 aic3x_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data); 878 snd_soc_write(codec, AIC3X_SAMPLE_RATE_SEL_REG, data);
845 879
846 if (bypass_pll) 880 if (bypass_pll)
847 return 0; 881 return 0;
@@ -910,13 +944,16 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
910 } 944 }
911 945
912found: 946found:
913 data = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 947 data = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
914 aic3x_write(codec, AIC3X_PLL_PROGA_REG, data | (pll_p << PLLP_SHIFT)); 948 snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
915 aic3x_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG, pll_r << PLLR_SHIFT); 949 data | (pll_p << PLLP_SHIFT));
916 aic3x_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT); 950 snd_soc_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG,
917 aic3x_write(codec, AIC3X_PLL_PROGC_REG, (pll_d >> 6) << PLLD_MSB_SHIFT); 951 pll_r << PLLR_SHIFT);
918 aic3x_write(codec, AIC3X_PLL_PROGD_REG, 952 snd_soc_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT);
919 (pll_d & 0x3F) << PLLD_LSB_SHIFT); 953 snd_soc_write(codec, AIC3X_PLL_PROGC_REG,
954 (pll_d >> 6) << PLLD_MSB_SHIFT);
955 snd_soc_write(codec, AIC3X_PLL_PROGD_REG,
956 (pll_d & 0x3F) << PLLD_LSB_SHIFT);
920 957
921 return 0; 958 return 0;
922} 959}
@@ -924,15 +961,15 @@ found:
924static int aic3x_mute(struct snd_soc_dai *dai, int mute) 961static int aic3x_mute(struct snd_soc_dai *dai, int mute)
925{ 962{
926 struct snd_soc_codec *codec = dai->codec; 963 struct snd_soc_codec *codec = dai->codec;
927 u8 ldac_reg = aic3x_read_reg_cache(codec, LDAC_VOL) & ~MUTE_ON; 964 u8 ldac_reg = snd_soc_read(codec, LDAC_VOL) & ~MUTE_ON;
928 u8 rdac_reg = aic3x_read_reg_cache(codec, RDAC_VOL) & ~MUTE_ON; 965 u8 rdac_reg = snd_soc_read(codec, RDAC_VOL) & ~MUTE_ON;
929 966
930 if (mute) { 967 if (mute) {
931 aic3x_write(codec, LDAC_VOL, ldac_reg | MUTE_ON); 968 snd_soc_write(codec, LDAC_VOL, ldac_reg | MUTE_ON);
932 aic3x_write(codec, RDAC_VOL, rdac_reg | MUTE_ON); 969 snd_soc_write(codec, RDAC_VOL, rdac_reg | MUTE_ON);
933 } else { 970 } else {
934 aic3x_write(codec, LDAC_VOL, ldac_reg); 971 snd_soc_write(codec, LDAC_VOL, ldac_reg);
935 aic3x_write(codec, RDAC_VOL, rdac_reg); 972 snd_soc_write(codec, RDAC_VOL, rdac_reg);
936 } 973 }
937 974
938 return 0; 975 return 0;
@@ -956,8 +993,8 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
956 u8 iface_areg, iface_breg; 993 u8 iface_areg, iface_breg;
957 int delay = 0; 994 int delay = 0;
958 995
959 iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f; 996 iface_areg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f;
960 iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f; 997 iface_breg = snd_soc_read(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f;
961 998
962 /* set master/slave audio interface */ 999 /* set master/slave audio interface */
963 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 1000 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -996,13 +1033,98 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
996 } 1033 }
997 1034
998 /* set iface */ 1035 /* set iface */
999 aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg); 1036 snd_soc_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg);
1000 aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg); 1037 snd_soc_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg);
1001 aic3x_write(codec, AIC3X_ASD_INTF_CTRLC, delay); 1038 snd_soc_write(codec, AIC3X_ASD_INTF_CTRLC, delay);
1039
1040 return 0;
1041}
1042
1043static int aic3x_init_3007(struct snd_soc_codec *codec)
1044{
1045 u8 tmp1, tmp2, *cache = codec->reg_cache;
1046
1047 /*
1048 * There is no need to cache writes to undocumented page 0xD but
1049 * respective page 0 register cache entries must be preserved
1050 */
1051 tmp1 = cache[0xD];
1052 tmp2 = cache[0x8];
1053 /* Class-D speaker driver init; datasheet p. 46 */
1054 snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x0D);
1055 snd_soc_write(codec, 0xD, 0x0D);
1056 snd_soc_write(codec, 0x8, 0x5C);
1057 snd_soc_write(codec, 0x8, 0x5D);
1058 snd_soc_write(codec, 0x8, 0x5C);
1059 snd_soc_write(codec, AIC3X_PAGE_SELECT, 0x00);
1060 cache[0xD] = tmp1;
1061 cache[0x8] = tmp2;
1002 1062
1003 return 0; 1063 return 0;
1004} 1064}
1005 1065
1066static int aic3x_regulator_event(struct notifier_block *nb,
1067 unsigned long event, void *data)
1068{
1069 struct aic3x_disable_nb *disable_nb =
1070 container_of(nb, struct aic3x_disable_nb, nb);
1071 struct aic3x_priv *aic3x = disable_nb->aic3x;
1072
1073 if (event & REGULATOR_EVENT_DISABLE) {
1074 /*
1075 * Put codec to reset and require cache sync as at least one
1076 * of the supplies was disabled
1077 */
1078 if (aic3x->gpio_reset >= 0)
1079 gpio_set_value(aic3x->gpio_reset, 0);
1080 aic3x->codec->cache_sync = 1;
1081 }
1082
1083 return 0;
1084}
1085
1086static int aic3x_set_power(struct snd_soc_codec *codec, int power)
1087{
1088 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1089 int i, ret;
1090 u8 *cache = codec->reg_cache;
1091
1092 if (power) {
1093 ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
1094 aic3x->supplies);
1095 if (ret)
1096 goto out;
1097 aic3x->power = 1;
1098 /*
1099 * Reset release and cache sync is necessary only if some
1100 * supply was off or if there were cached writes
1101 */
1102 if (!codec->cache_sync)
1103 goto out;
1104
1105 if (aic3x->gpio_reset >= 0) {
1106 udelay(1);
1107 gpio_set_value(aic3x->gpio_reset, 1);
1108 }
1109
1110 /* Sync reg_cache with the hardware */
1111 codec->cache_only = 0;
1112 for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++)
1113 snd_soc_write(codec, i, cache[i]);
1114 if (aic3x->model == AIC3X_MODEL_3007)
1115 aic3x_init_3007(codec);
1116 codec->cache_sync = 0;
1117 } else {
1118 aic3x->power = 0;
1119 /* HW writes are needless when bias is off */
1120 codec->cache_only = 1;
1121 ret = regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies),
1122 aic3x->supplies);
1123 }
1124out:
1125 return ret;
1126}
1127
1006static int aic3x_set_bias_level(struct snd_soc_codec *codec, 1128static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1007 enum snd_soc_bias_level level) 1129 enum snd_soc_bias_level level)
1008{ 1130{
@@ -1013,23 +1135,29 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
1013 case SND_SOC_BIAS_ON: 1135 case SND_SOC_BIAS_ON:
1014 break; 1136 break;
1015 case SND_SOC_BIAS_PREPARE: 1137 case SND_SOC_BIAS_PREPARE:
1016 if (aic3x->master) { 1138 if (codec->bias_level == SND_SOC_BIAS_STANDBY &&
1139 aic3x->master) {
1017 /* enable pll */ 1140 /* enable pll */
1018 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 1141 reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
1019 aic3x_write(codec, AIC3X_PLL_PROGA_REG, 1142 snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
1020 reg | PLL_ENABLE); 1143 reg | PLL_ENABLE);
1021 } 1144 }
1022 break; 1145 break;
1023 case SND_SOC_BIAS_STANDBY: 1146 case SND_SOC_BIAS_STANDBY:
1024 /* fall through and disable pll */ 1147 if (!aic3x->power)
1025 case SND_SOC_BIAS_OFF: 1148 aic3x_set_power(codec, 1);
1026 if (aic3x->master) { 1149 if (codec->bias_level == SND_SOC_BIAS_PREPARE &&
1150 aic3x->master) {
1027 /* disable pll */ 1151 /* disable pll */
1028 reg = aic3x_read_reg_cache(codec, AIC3X_PLL_PROGA_REG); 1152 reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
1029 aic3x_write(codec, AIC3X_PLL_PROGA_REG, 1153 snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
1030 reg & ~PLL_ENABLE); 1154 reg & ~PLL_ENABLE);
1031 } 1155 }
1032 break; 1156 break;
1157 case SND_SOC_BIAS_OFF:
1158 if (aic3x->power)
1159 aic3x_set_power(codec, 0);
1160 break;
1033 } 1161 }
1034 codec->bias_level = level; 1162 codec->bias_level = level;
1035 1163
@@ -1040,8 +1168,8 @@ void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
1040{ 1168{
1041 u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG; 1169 u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
1042 u8 bit = gpio ? 3: 0; 1170 u8 bit = gpio ? 3: 0;
1043 u8 val = aic3x_read_reg_cache(codec, reg) & ~(1 << bit); 1171 u8 val = snd_soc_read(codec, reg) & ~(1 << bit);
1044 aic3x_write(codec, reg, val | (!!state << bit)); 1172 snd_soc_write(codec, reg, val | (!!state << bit));
1045} 1173}
1046EXPORT_SYMBOL_GPL(aic3x_set_gpio); 1174EXPORT_SYMBOL_GPL(aic3x_set_gpio);
1047 1175
@@ -1070,7 +1198,7 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
1070 if (detect & AIC3X_HEADSET_DETECT_MASK) 1198 if (detect & AIC3X_HEADSET_DETECT_MASK)
1071 val |= AIC3X_HEADSET_DETECT_ENABLED; 1199 val |= AIC3X_HEADSET_DETECT_ENABLED;
1072 1200
1073 aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val); 1201 snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
1074} 1202}
1075EXPORT_SYMBOL_GPL(aic3x_set_headset_detection); 1203EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
1076 1204
@@ -1101,8 +1229,8 @@ static struct snd_soc_dai_ops aic3x_dai_ops = {
1101 .set_fmt = aic3x_set_dai_fmt, 1229 .set_fmt = aic3x_set_dai_fmt,
1102}; 1230};
1103 1231
1104struct snd_soc_dai aic3x_dai = { 1232static struct snd_soc_dai_driver aic3x_dai = {
1105 .name = "tlv320aic3x", 1233 .name = "tlv320aic3x-hifi",
1106 .playback = { 1234 .playback = {
1107 .stream_name = "Playback", 1235 .stream_name = "Playback",
1108 .channels_min = 1, 1236 .channels_min = 1,
@@ -1116,34 +1244,18 @@ struct snd_soc_dai aic3x_dai = {
1116 .rates = AIC3X_RATES, 1244 .rates = AIC3X_RATES,
1117 .formats = AIC3X_FORMATS,}, 1245 .formats = AIC3X_FORMATS,},
1118 .ops = &aic3x_dai_ops, 1246 .ops = &aic3x_dai_ops,
1247 .symmetric_rates = 1,
1119}; 1248};
1120EXPORT_SYMBOL_GPL(aic3x_dai);
1121 1249
1122static int aic3x_suspend(struct platform_device *pdev, pm_message_t state) 1250static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
1123{ 1251{
1124 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1125 struct snd_soc_codec *codec = socdev->card->codec;
1126
1127 aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF); 1252 aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
1128 1253
1129 return 0; 1254 return 0;
1130} 1255}
1131 1256
1132static int aic3x_resume(struct platform_device *pdev) 1257static int aic3x_resume(struct snd_soc_codec *codec)
1133{ 1258{
1134 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1135 struct snd_soc_codec *codec = socdev->card->codec;
1136 int i;
1137 u8 data[2];
1138 u8 *cache = codec->reg_cache;
1139
1140 /* Sync reg_cache with the hardware */
1141 for (i = 0; i < ARRAY_SIZE(aic3x_reg); i++) {
1142 data[0] = i;
1143 data[1] = cache[i];
1144 codec->hw_write(codec->control_data, data, 2);
1145 }
1146
1147 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1259 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1148 1260
1149 return 0; 1261 return 0;
@@ -1155,152 +1267,203 @@ static int aic3x_resume(struct platform_device *pdev)
1155 */ 1267 */
1156static int aic3x_init(struct snd_soc_codec *codec) 1268static int aic3x_init(struct snd_soc_codec *codec)
1157{ 1269{
1270 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1158 int reg; 1271 int reg;
1159 1272
1160 mutex_init(&codec->mutex); 1273 snd_soc_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
1161 INIT_LIST_HEAD(&codec->dapm_widgets); 1274 snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
1162 INIT_LIST_HEAD(&codec->dapm_paths);
1163
1164 codec->name = "tlv320aic3x";
1165 codec->owner = THIS_MODULE;
1166 codec->read = aic3x_read_reg_cache;
1167 codec->write = aic3x_write;
1168 codec->set_bias_level = aic3x_set_bias_level;
1169 codec->dai = &aic3x_dai;
1170 codec->num_dai = 1;
1171 codec->reg_cache_size = ARRAY_SIZE(aic3x_reg);
1172 codec->reg_cache = kmemdup(aic3x_reg, sizeof(aic3x_reg), GFP_KERNEL);
1173 if (codec->reg_cache == NULL)
1174 return -ENOMEM;
1175
1176 aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
1177 aic3x_write(codec, AIC3X_RESET, SOFT_RESET);
1178 1275
1179 /* DAC default volume and mute */ 1276 /* DAC default volume and mute */
1180 aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON); 1277 snd_soc_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON);
1181 aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON); 1278 snd_soc_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON);
1182 1279
1183 /* DAC to HP default volume and route to Output mixer */ 1280 /* DAC to HP default volume and route to Output mixer */
1184 aic3x_write(codec, DACL1_2_HPLOUT_VOL, DEFAULT_VOL | ROUTE_ON); 1281 snd_soc_write(codec, DACL1_2_HPLOUT_VOL, DEFAULT_VOL | ROUTE_ON);
1185 aic3x_write(codec, DACR1_2_HPROUT_VOL, DEFAULT_VOL | ROUTE_ON); 1282 snd_soc_write(codec, DACR1_2_HPROUT_VOL, DEFAULT_VOL | ROUTE_ON);
1186 aic3x_write(codec, DACL1_2_HPLCOM_VOL, DEFAULT_VOL | ROUTE_ON); 1283 snd_soc_write(codec, DACL1_2_HPLCOM_VOL, DEFAULT_VOL | ROUTE_ON);
1187 aic3x_write(codec, DACR1_2_HPRCOM_VOL, DEFAULT_VOL | ROUTE_ON); 1284 snd_soc_write(codec, DACR1_2_HPRCOM_VOL, DEFAULT_VOL | ROUTE_ON);
1188 /* DAC to Line Out default volume and route to Output mixer */ 1285 /* DAC to Line Out default volume and route to Output mixer */
1189 aic3x_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON); 1286 snd_soc_write(codec, DACL1_2_LLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
1190 aic3x_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON); 1287 snd_soc_write(codec, DACR1_2_RLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
1191 /* DAC to Mono Line Out default volume and route to Output mixer */ 1288 /* DAC to Mono Line Out default volume and route to Output mixer */
1192 aic3x_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); 1289 snd_soc_write(codec, DACL1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
1193 aic3x_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON); 1290 snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
1194 1291
1195 /* unmute all outputs */ 1292 /* unmute all outputs */
1196 reg = aic3x_read_reg_cache(codec, LLOPM_CTRL); 1293 reg = snd_soc_read(codec, LLOPM_CTRL);
1197 aic3x_write(codec, LLOPM_CTRL, reg | UNMUTE); 1294 snd_soc_write(codec, LLOPM_CTRL, reg | UNMUTE);
1198 reg = aic3x_read_reg_cache(codec, RLOPM_CTRL); 1295 reg = snd_soc_read(codec, RLOPM_CTRL);
1199 aic3x_write(codec, RLOPM_CTRL, reg | UNMUTE); 1296 snd_soc_write(codec, RLOPM_CTRL, reg | UNMUTE);
1200 reg = aic3x_read_reg_cache(codec, MONOLOPM_CTRL); 1297 reg = snd_soc_read(codec, MONOLOPM_CTRL);
1201 aic3x_write(codec, MONOLOPM_CTRL, reg | UNMUTE); 1298 snd_soc_write(codec, MONOLOPM_CTRL, reg | UNMUTE);
1202 reg = aic3x_read_reg_cache(codec, HPLOUT_CTRL); 1299 reg = snd_soc_read(codec, HPLOUT_CTRL);
1203 aic3x_write(codec, HPLOUT_CTRL, reg | UNMUTE); 1300 snd_soc_write(codec, HPLOUT_CTRL, reg | UNMUTE);
1204 reg = aic3x_read_reg_cache(codec, HPROUT_CTRL); 1301 reg = snd_soc_read(codec, HPROUT_CTRL);
1205 aic3x_write(codec, HPROUT_CTRL, reg | UNMUTE); 1302 snd_soc_write(codec, HPROUT_CTRL, reg | UNMUTE);
1206 reg = aic3x_read_reg_cache(codec, HPLCOM_CTRL); 1303 reg = snd_soc_read(codec, HPLCOM_CTRL);
1207 aic3x_write(codec, HPLCOM_CTRL, reg | UNMUTE); 1304 snd_soc_write(codec, HPLCOM_CTRL, reg | UNMUTE);
1208 reg = aic3x_read_reg_cache(codec, HPRCOM_CTRL); 1305 reg = snd_soc_read(codec, HPRCOM_CTRL);
1209 aic3x_write(codec, HPRCOM_CTRL, reg | UNMUTE); 1306 snd_soc_write(codec, HPRCOM_CTRL, reg | UNMUTE);
1210 1307
1211 /* ADC default volume and unmute */ 1308 /* ADC default volume and unmute */
1212 aic3x_write(codec, LADC_VOL, DEFAULT_GAIN); 1309 snd_soc_write(codec, LADC_VOL, DEFAULT_GAIN);
1213 aic3x_write(codec, RADC_VOL, DEFAULT_GAIN); 1310 snd_soc_write(codec, RADC_VOL, DEFAULT_GAIN);
1214 /* By default route Line1 to ADC PGA mixer */ 1311 /* By default route Line1 to ADC PGA mixer */
1215 aic3x_write(codec, LINE1L_2_LADC_CTRL, 0x0); 1312 snd_soc_write(codec, LINE1L_2_LADC_CTRL, 0x0);
1216 aic3x_write(codec, LINE1R_2_RADC_CTRL, 0x0); 1313 snd_soc_write(codec, LINE1R_2_RADC_CTRL, 0x0);
1217 1314
1218 /* PGA to HP Bypass default volume, disconnect from Output Mixer */ 1315 /* PGA to HP Bypass default volume, disconnect from Output Mixer */
1219 aic3x_write(codec, PGAL_2_HPLOUT_VOL, DEFAULT_VOL); 1316 snd_soc_write(codec, PGAL_2_HPLOUT_VOL, DEFAULT_VOL);
1220 aic3x_write(codec, PGAR_2_HPROUT_VOL, DEFAULT_VOL); 1317 snd_soc_write(codec, PGAR_2_HPROUT_VOL, DEFAULT_VOL);
1221 aic3x_write(codec, PGAL_2_HPLCOM_VOL, DEFAULT_VOL); 1318 snd_soc_write(codec, PGAL_2_HPLCOM_VOL, DEFAULT_VOL);
1222 aic3x_write(codec, PGAR_2_HPRCOM_VOL, DEFAULT_VOL); 1319 snd_soc_write(codec, PGAR_2_HPRCOM_VOL, DEFAULT_VOL);
1223 /* PGA to Line Out default volume, disconnect from Output Mixer */ 1320 /* PGA to Line Out default volume, disconnect from Output Mixer */
1224 aic3x_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL); 1321 snd_soc_write(codec, PGAL_2_LLOPM_VOL, DEFAULT_VOL);
1225 aic3x_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL); 1322 snd_soc_write(codec, PGAR_2_RLOPM_VOL, DEFAULT_VOL);
1226 /* PGA to Mono Line Out default volume, disconnect from Output Mixer */ 1323 /* PGA to Mono Line Out default volume, disconnect from Output Mixer */
1227 aic3x_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL); 1324 snd_soc_write(codec, PGAL_2_MONOLOPM_VOL, DEFAULT_VOL);
1228 aic3x_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL); 1325 snd_soc_write(codec, PGAR_2_MONOLOPM_VOL, DEFAULT_VOL);
1229 1326
1230 /* Line2 to HP Bypass default volume, disconnect from Output Mixer */ 1327 /* Line2 to HP Bypass default volume, disconnect from Output Mixer */
1231 aic3x_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL); 1328 snd_soc_write(codec, LINE2L_2_HPLOUT_VOL, DEFAULT_VOL);
1232 aic3x_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL); 1329 snd_soc_write(codec, LINE2R_2_HPROUT_VOL, DEFAULT_VOL);
1233 aic3x_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL); 1330 snd_soc_write(codec, LINE2L_2_HPLCOM_VOL, DEFAULT_VOL);
1234 aic3x_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL); 1331 snd_soc_write(codec, LINE2R_2_HPRCOM_VOL, DEFAULT_VOL);
1235 /* Line2 Line Out default volume, disconnect from Output Mixer */ 1332 /* Line2 Line Out default volume, disconnect from Output Mixer */
1236 aic3x_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL); 1333 snd_soc_write(codec, LINE2L_2_LLOPM_VOL, DEFAULT_VOL);
1237 aic3x_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL); 1334 snd_soc_write(codec, LINE2R_2_RLOPM_VOL, DEFAULT_VOL);
1238 /* Line2 to Mono Out default volume, disconnect from Output Mixer */ 1335 /* Line2 to Mono Out default volume, disconnect from Output Mixer */
1239 aic3x_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL); 1336 snd_soc_write(codec, LINE2L_2_MONOLOPM_VOL, DEFAULT_VOL);
1240 aic3x_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL); 1337 snd_soc_write(codec, LINE2R_2_MONOLOPM_VOL, DEFAULT_VOL);
1241 1338
1242 /* off, with power on */ 1339 if (aic3x->model == AIC3X_MODEL_3007) {
1243 aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1340 aic3x_init_3007(codec);
1341 snd_soc_write(codec, CLASSD_CTRL, 0);
1342 }
1244 1343
1245 return 0; 1344 return 0;
1246} 1345}
1247 1346
1248static struct snd_soc_codec *aic3x_codec; 1347static int aic3x_probe(struct snd_soc_codec *codec)
1249
1250static int aic3x_register(struct snd_soc_codec *codec)
1251{ 1348{
1252 int ret; 1349 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1350 int ret, i;
1253 1351
1254 ret = aic3x_init(codec); 1352 codec->control_data = aic3x->control_data;
1255 if (ret < 0) { 1353 aic3x->codec = codec;
1256 dev_err(codec->dev, "Failed to initialise device\n"); 1354 codec->idle_bias_off = 1;
1355
1356 ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
1357 if (ret != 0) {
1358 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1257 return ret; 1359 return ret;
1258 } 1360 }
1259 1361
1260 aic3x_codec = codec; 1362 if (aic3x->gpio_reset >= 0) {
1363 ret = gpio_request(aic3x->gpio_reset, "tlv320aic3x reset");
1364 if (ret != 0)
1365 goto err_gpio;
1366 gpio_direction_output(aic3x->gpio_reset, 0);
1367 }
1368
1369 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
1370 aic3x->supplies[i].supply = aic3x_supply_names[i];
1261 1371
1262 ret = snd_soc_register_codec(codec); 1372 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
1263 if (ret) { 1373 aic3x->supplies);
1264 dev_err(codec->dev, "Failed to register codec\n"); 1374 if (ret != 0) {
1265 return ret; 1375 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1376 goto err_get;
1377 }
1378 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) {
1379 aic3x->disable_nb[i].nb.notifier_call = aic3x_regulator_event;
1380 aic3x->disable_nb[i].aic3x = aic3x;
1381 ret = regulator_register_notifier(aic3x->supplies[i].consumer,
1382 &aic3x->disable_nb[i].nb);
1383 if (ret) {
1384 dev_err(codec->dev,
1385 "Failed to request regulator notifier: %d\n",
1386 ret);
1387 goto err_notif;
1388 }
1266 } 1389 }
1267 1390
1268 ret = snd_soc_register_dai(&aic3x_dai); 1391 codec->cache_only = 1;
1269 if (ret) { 1392 aic3x_init(codec);
1270 dev_err(codec->dev, "Failed to register dai\n"); 1393
1271 snd_soc_unregister_codec(codec); 1394 if (aic3x->setup) {
1272 return ret; 1395 /* setup GPIO functions */
1396 snd_soc_write(codec, AIC3X_GPIO1_REG,
1397 (aic3x->setup->gpio_func[0] & 0xf) << 4);
1398 snd_soc_write(codec, AIC3X_GPIO2_REG,
1399 (aic3x->setup->gpio_func[1] & 0xf) << 4);
1273 } 1400 }
1274 1401
1402 snd_soc_add_controls(codec, aic3x_snd_controls,
1403 ARRAY_SIZE(aic3x_snd_controls));
1404 if (aic3x->model == AIC3X_MODEL_3007)
1405 snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
1406
1407 aic3x_add_widgets(codec);
1408
1275 return 0; 1409 return 0;
1410
1411err_notif:
1412 while (i--)
1413 regulator_unregister_notifier(aic3x->supplies[i].consumer,
1414 &aic3x->disable_nb[i].nb);
1415 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1416err_get:
1417 if (aic3x->gpio_reset >= 0)
1418 gpio_free(aic3x->gpio_reset);
1419err_gpio:
1420 kfree(aic3x);
1421 return ret;
1276} 1422}
1277 1423
1278static int aic3x_unregister(struct aic3x_priv *aic3x) 1424static int aic3x_remove(struct snd_soc_codec *codec)
1279{ 1425{
1280 aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF); 1426 struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
1281 1427 int i;
1282 snd_soc_unregister_dai(&aic3x_dai);
1283 snd_soc_unregister_codec(&aic3x->codec);
1284 1428
1429 aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
1285 if (aic3x->gpio_reset >= 0) { 1430 if (aic3x->gpio_reset >= 0) {
1286 gpio_set_value(aic3x->gpio_reset, 0); 1431 gpio_set_value(aic3x->gpio_reset, 0);
1287 gpio_free(aic3x->gpio_reset); 1432 gpio_free(aic3x->gpio_reset);
1288 } 1433 }
1289 regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); 1434 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
1435 regulator_unregister_notifier(aic3x->supplies[i].consumer,
1436 &aic3x->disable_nb[i].nb);
1290 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); 1437 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies);
1291 1438
1292 kfree(aic3x);
1293 aic3x_codec = NULL;
1294
1295 return 0; 1439 return 0;
1296} 1440}
1297 1441
1442static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
1443 .set_bias_level = aic3x_set_bias_level,
1444 .reg_cache_size = ARRAY_SIZE(aic3x_reg),
1445 .reg_word_size = sizeof(u8),
1446 .reg_cache_default = aic3x_reg,
1447 .probe = aic3x_probe,
1448 .remove = aic3x_remove,
1449 .suspend = aic3x_suspend,
1450 .resume = aic3x_resume,
1451};
1452
1298#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1453#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1299/* 1454/*
1300 * AIC3X 2 wire address can be up to 4 devices with device addresses 1455 * AIC3X 2 wire address can be up to 4 devices with device addresses
1301 * 0x18, 0x19, 0x1A, 0x1B 1456 * 0x18, 0x19, 0x1A, 0x1B
1302 */ 1457 */
1303 1458
1459static const struct i2c_device_id aic3x_i2c_id[] = {
1460 [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
1461 [AIC3X_MODEL_33] = { "tlv320aic33", 0 },
1462 [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
1463 { }
1464};
1465MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
1466
1304/* 1467/*
1305 * If the i2c layer weren't so broken, we could pass this kind of data 1468 * If the i2c layer weren't so broken, we could pass this kind of data
1306 * around 1469 * around
@@ -1308,10 +1471,10 @@ static int aic3x_unregister(struct aic3x_priv *aic3x)
1308static int aic3x_i2c_probe(struct i2c_client *i2c, 1471static int aic3x_i2c_probe(struct i2c_client *i2c,
1309 const struct i2c_device_id *id) 1472 const struct i2c_device_id *id)
1310{ 1473{
1311 struct snd_soc_codec *codec;
1312 struct aic3x_priv *aic3x;
1313 struct aic3x_pdata *pdata = i2c->dev.platform_data; 1474 struct aic3x_pdata *pdata = i2c->dev.platform_data;
1314 int ret, i; 1475 struct aic3x_priv *aic3x;
1476 int ret;
1477 const struct i2c_device_id *tbl;
1315 1478
1316 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); 1479 aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
1317 if (aic3x == NULL) { 1480 if (aic3x == NULL) {
@@ -1319,75 +1482,41 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
1319 return -ENOMEM; 1482 return -ENOMEM;
1320 } 1483 }
1321 1484
1322 codec = &aic3x->codec; 1485 aic3x->control_data = i2c;
1323 codec->dev = &i2c->dev; 1486 aic3x->control_type = SND_SOC_I2C;
1324 snd_soc_codec_set_drvdata(codec, aic3x);
1325 codec->control_data = i2c;
1326 codec->hw_write = (hw_write_t) i2c_master_send;
1327 1487
1328 i2c_set_clientdata(i2c, aic3x); 1488 i2c_set_clientdata(i2c, aic3x);
1329 1489 if (pdata) {
1330 aic3x->gpio_reset = -1;
1331 if (pdata && pdata->gpio_reset >= 0) {
1332 ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset");
1333 if (ret != 0)
1334 goto err_gpio;
1335 aic3x->gpio_reset = pdata->gpio_reset; 1490 aic3x->gpio_reset = pdata->gpio_reset;
1336 gpio_direction_output(aic3x->gpio_reset, 0); 1491 aic3x->setup = pdata->setup;
1337 } 1492 } else {
1338 1493 aic3x->gpio_reset = -1;
1339 for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++)
1340 aic3x->supplies[i].supply = aic3x_supply_names[i];
1341
1342 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(aic3x->supplies),
1343 aic3x->supplies);
1344 if (ret != 0) {
1345 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1346 goto err_get;
1347 }
1348
1349 ret = regulator_bulk_enable(ARRAY_SIZE(aic3x->supplies),
1350 aic3x->supplies);
1351 if (ret != 0) {
1352 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1353 goto err_enable;
1354 } 1494 }
1355 1495
1356 if (aic3x->gpio_reset >= 0) { 1496 for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
1357 udelay(1); 1497 if (!strcmp(tbl->name, id->name))
1358 gpio_set_value(aic3x->gpio_reset, 1); 1498 break;
1359 } 1499 }
1500 aic3x->model = tbl - aic3x_i2c_id;
1360 1501
1361 return aic3x_register(codec); 1502 ret = snd_soc_register_codec(&i2c->dev,
1362 1503 &soc_codec_dev_aic3x, &aic3x_dai, 1);
1363err_enable: 1504 if (ret < 0)
1364 regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); 1505 kfree(aic3x);
1365err_get:
1366 if (aic3x->gpio_reset >= 0)
1367 gpio_free(aic3x->gpio_reset);
1368err_gpio:
1369 kfree(aic3x);
1370 return ret; 1506 return ret;
1371} 1507}
1372 1508
1373static int aic3x_i2c_remove(struct i2c_client *client) 1509static int aic3x_i2c_remove(struct i2c_client *client)
1374{ 1510{
1375 struct aic3x_priv *aic3x = i2c_get_clientdata(client); 1511 snd_soc_unregister_codec(&client->dev);
1376 1512 kfree(i2c_get_clientdata(client));
1377 return aic3x_unregister(aic3x); 1513 return 0;
1378} 1514}
1379 1515
1380static const struct i2c_device_id aic3x_i2c_id[] = {
1381 { "tlv320aic3x", 0 },
1382 { "tlv320aic33", 0 },
1383 { }
1384};
1385MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
1386
1387/* machine i2c codec control layer */ 1516/* machine i2c codec control layer */
1388static struct i2c_driver aic3x_i2c_driver = { 1517static struct i2c_driver aic3x_i2c_driver = {
1389 .driver = { 1518 .driver = {
1390 .name = "aic3x I2C Codec", 1519 .name = "tlv320aic3x-codec",
1391 .owner = THIS_MODULE, 1520 .owner = THIS_MODULE,
1392 }, 1521 },
1393 .probe = aic3x_i2c_probe, 1522 .probe = aic3x_i2c_probe,
@@ -1409,90 +1538,27 @@ static inline void aic3x_i2c_exit(void)
1409{ 1538{
1410 i2c_del_driver(&aic3x_i2c_driver); 1539 i2c_del_driver(&aic3x_i2c_driver);
1411} 1540}
1412#else
1413static inline void aic3x_i2c_init(void) { }
1414static inline void aic3x_i2c_exit(void) { }
1415#endif 1541#endif
1416 1542
1417static int aic3x_probe(struct platform_device *pdev) 1543static int __init aic3x_modinit(void)
1418{ 1544{
1419 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1420 struct aic3x_setup_data *setup;
1421 struct snd_soc_codec *codec;
1422 int ret = 0; 1545 int ret = 0;
1423 1546#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1424 codec = aic3x_codec; 1547 ret = i2c_add_driver(&aic3x_i2c_driver);
1425 if (!codec) { 1548 if (ret != 0) {
1426 dev_err(&pdev->dev, "Codec not registered\n"); 1549 printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n",
1427 return -ENODEV; 1550 ret);
1428 }
1429
1430 socdev->card->codec = codec;
1431 setup = socdev->codec_data;
1432
1433 if (setup) {
1434 /* setup GPIO functions */
1435 aic3x_write(codec, AIC3X_GPIO1_REG,
1436 (setup->gpio_func[0] & 0xf) << 4);
1437 aic3x_write(codec, AIC3X_GPIO2_REG,
1438 (setup->gpio_func[1] & 0xf) << 4);
1439 }
1440
1441 /* register pcms */
1442 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1443 if (ret < 0) {
1444 printk(KERN_ERR "aic3x: failed to create pcms\n");
1445 goto pcm_err;
1446 } 1551 }
1447 1552#endif
1448 snd_soc_add_controls(codec, aic3x_snd_controls,
1449 ARRAY_SIZE(aic3x_snd_controls));
1450
1451 aic3x_add_widgets(codec);
1452
1453 return ret;
1454
1455pcm_err:
1456 kfree(codec->reg_cache);
1457 return ret; 1553 return ret;
1458} 1554}
1459
1460static int aic3x_remove(struct platform_device *pdev)
1461{
1462 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1463 struct snd_soc_codec *codec = socdev->card->codec;
1464
1465 /* power down chip */
1466 if (codec->control_data)
1467 aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
1468
1469 snd_soc_free_pcms(socdev);
1470 snd_soc_dapm_free(socdev);
1471
1472 kfree(codec->reg_cache);
1473
1474 return 0;
1475}
1476
1477struct snd_soc_codec_device soc_codec_dev_aic3x = {
1478 .probe = aic3x_probe,
1479 .remove = aic3x_remove,
1480 .suspend = aic3x_suspend,
1481 .resume = aic3x_resume,
1482};
1483EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
1484
1485static int __init aic3x_modinit(void)
1486{
1487 aic3x_i2c_init();
1488
1489 return 0;
1490}
1491module_init(aic3x_modinit); 1555module_init(aic3x_modinit);
1492 1556
1493static void __exit aic3x_exit(void) 1557static void __exit aic3x_exit(void)
1494{ 1558{
1495 aic3x_i2c_exit(); 1559#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1560 i2c_del_driver(&aic3x_i2c_driver);
1561#endif
1496} 1562}
1497module_exit(aic3x_exit); 1563module_exit(aic3x_exit);
1498 1564
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 9af1c886213c..06a19784b162 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -81,50 +81,63 @@
81/* DAC Digital control registers */ 81/* DAC Digital control registers */
82#define LDAC_VOL 43 82#define LDAC_VOL 43
83#define RDAC_VOL 44 83#define RDAC_VOL 44
84/* High Power Output control registers */ 84/* Left High Power Output control registers */
85#define LINE2L_2_HPLOUT_VOL 45 85#define LINE2L_2_HPLOUT_VOL 45
86#define LINE2R_2_HPROUT_VOL 62
87#define PGAL_2_HPLOUT_VOL 46 86#define PGAL_2_HPLOUT_VOL 46
88#define PGAL_2_HPROUT_VOL 60
89#define PGAR_2_HPLOUT_VOL 49
90#define PGAR_2_HPROUT_VOL 63
91#define DACL1_2_HPLOUT_VOL 47 87#define DACL1_2_HPLOUT_VOL 47
92#define DACR1_2_HPROUT_VOL 64 88#define LINE2R_2_HPLOUT_VOL 48
89#define PGAR_2_HPLOUT_VOL 49
90#define DACR1_2_HPLOUT_VOL 50
93#define HPLOUT_CTRL 51 91#define HPLOUT_CTRL 51
94#define HPROUT_CTRL 65 92/* Left High Power COM control registers */
95/* High Power COM control registers */
96#define LINE2L_2_HPLCOM_VOL 52 93#define LINE2L_2_HPLCOM_VOL 52
97#define LINE2R_2_HPRCOM_VOL 69
98#define PGAL_2_HPLCOM_VOL 53 94#define PGAL_2_HPLCOM_VOL 53
95#define DACL1_2_HPLCOM_VOL 54
96#define LINE2R_2_HPLCOM_VOL 55
99#define PGAR_2_HPLCOM_VOL 56 97#define PGAR_2_HPLCOM_VOL 56
98#define DACR1_2_HPLCOM_VOL 57
99#define HPLCOM_CTRL 58
100/* Right High Power Output control registers */
101#define LINE2L_2_HPROUT_VOL 59
102#define PGAL_2_HPROUT_VOL 60
103#define DACL1_2_HPROUT_VOL 61
104#define LINE2R_2_HPROUT_VOL 62
105#define PGAR_2_HPROUT_VOL 63
106#define DACR1_2_HPROUT_VOL 64
107#define HPROUT_CTRL 65
108/* Right High Power COM control registers */
109#define LINE2L_2_HPRCOM_VOL 66
100#define PGAL_2_HPRCOM_VOL 67 110#define PGAL_2_HPRCOM_VOL 67
111#define DACL1_2_HPRCOM_VOL 68
112#define LINE2R_2_HPRCOM_VOL 69
101#define PGAR_2_HPRCOM_VOL 70 113#define PGAR_2_HPRCOM_VOL 70
102#define DACL1_2_HPLCOM_VOL 54
103#define DACR1_2_HPRCOM_VOL 71 114#define DACR1_2_HPRCOM_VOL 71
104#define HPLCOM_CTRL 58
105#define HPRCOM_CTRL 72 115#define HPRCOM_CTRL 72
106/* Mono Line Output Plus/Minus control registers */ 116/* Mono Line Output Plus/Minus control registers */
107#define LINE2L_2_MONOLOPM_VOL 73 117#define LINE2L_2_MONOLOPM_VOL 73
108#define LINE2R_2_MONOLOPM_VOL 76
109#define PGAL_2_MONOLOPM_VOL 74 118#define PGAL_2_MONOLOPM_VOL 74
110#define PGAR_2_MONOLOPM_VOL 77
111#define DACL1_2_MONOLOPM_VOL 75 119#define DACL1_2_MONOLOPM_VOL 75
120#define LINE2R_2_MONOLOPM_VOL 76
121#define PGAR_2_MONOLOPM_VOL 77
112#define DACR1_2_MONOLOPM_VOL 78 122#define DACR1_2_MONOLOPM_VOL 78
113#define MONOLOPM_CTRL 79 123#define MONOLOPM_CTRL 79
114/* Line Output Plus/Minus control registers */ 124/* Class-D speaker driver on tlv320aic3007 */
125#define CLASSD_CTRL 73
126/* Left Line Output Plus/Minus control registers */
115#define LINE2L_2_LLOPM_VOL 80 127#define LINE2L_2_LLOPM_VOL 80
116#define LINE2L_2_RLOPM_VOL 87
117#define LINE2R_2_LLOPM_VOL 83
118#define LINE2R_2_RLOPM_VOL 90
119#define PGAL_2_LLOPM_VOL 81 128#define PGAL_2_LLOPM_VOL 81
120#define PGAL_2_RLOPM_VOL 88
121#define PGAR_2_LLOPM_VOL 84
122#define PGAR_2_RLOPM_VOL 91
123#define DACL1_2_LLOPM_VOL 82 129#define DACL1_2_LLOPM_VOL 82
124#define DACL1_2_RLOPM_VOL 89 130#define LINE2R_2_LLOPM_VOL 83
125#define DACR1_2_RLOPM_VOL 92 131#define PGAR_2_LLOPM_VOL 84
126#define DACR1_2_LLOPM_VOL 85 132#define DACR1_2_LLOPM_VOL 85
127#define LLOPM_CTRL 86 133#define LLOPM_CTRL 86
134/* Right Line Output Plus/Minus control registers */
135#define LINE2L_2_RLOPM_VOL 87
136#define PGAL_2_RLOPM_VOL 88
137#define DACL1_2_RLOPM_VOL 89
138#define LINE2R_2_RLOPM_VOL 90
139#define PGAR_2_RLOPM_VOL 91
140#define DACR1_2_RLOPM_VOL 92
128#define RLOPM_CTRL 93 141#define RLOPM_CTRL 93
129/* GPIO/IRQ registers */ 142/* GPIO/IRQ registers */
130#define AIC3X_STICKY_IRQ_FLAGS_REG 96 143#define AIC3X_STICKY_IRQ_FLAGS_REG 96
@@ -199,42 +212,6 @@
199/* Default input volume */ 212/* Default input volume */
200#define DEFAULT_GAIN 0x20 213#define DEFAULT_GAIN 0x20
201 214
202/* GPIO API */
203enum {
204 AIC3X_GPIO1_FUNC_DISABLED = 0,
205 AIC3X_GPIO1_FUNC_AUDIO_WORDCLK_ADC = 1,
206 AIC3X_GPIO1_FUNC_CLOCK_MUX = 2,
207 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV2 = 3,
208 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV4 = 4,
209 AIC3X_GPIO1_FUNC_CLOCK_MUX_DIV8 = 5,
210 AIC3X_GPIO1_FUNC_SHORT_CIRCUIT_IRQ = 6,
211 AIC3X_GPIO1_FUNC_AGC_NOISE_IRQ = 7,
212 AIC3X_GPIO1_FUNC_INPUT = 8,
213 AIC3X_GPIO1_FUNC_OUTPUT = 9,
214 AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK = 10,
215 AIC3X_GPIO1_FUNC_AUDIO_WORDCLK = 11,
216 AIC3X_GPIO1_FUNC_BUTTON_IRQ = 12,
217 AIC3X_GPIO1_FUNC_HEADSET_DETECT_IRQ = 13,
218 AIC3X_GPIO1_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 14,
219 AIC3X_GPIO1_FUNC_ALL_IRQ = 16
220};
221
222enum {
223 AIC3X_GPIO2_FUNC_DISABLED = 0,
224 AIC3X_GPIO2_FUNC_HEADSET_DETECT_IRQ = 2,
225 AIC3X_GPIO2_FUNC_INPUT = 3,
226 AIC3X_GPIO2_FUNC_OUTPUT = 4,
227 AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT = 5,
228 AIC3X_GPIO2_FUNC_AUDIO_BITCLK = 8,
229 AIC3X_GPIO2_FUNC_HEADSET_DETECT_OR_BUTTON_IRQ = 9,
230 AIC3X_GPIO2_FUNC_ALL_IRQ = 10,
231 AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_OR_AGC_IRQ = 11,
232 AIC3X_GPIO2_FUNC_HEADSET_OR_BUTTON_PRESS_OR_SHORT_CIRCUIT_IRQ = 12,
233 AIC3X_GPIO2_FUNC_SHORT_CIRCUIT_IRQ = 13,
234 AIC3X_GPIO2_FUNC_AGC_NOISE_IRQ = 14,
235 AIC3X_GPIO2_FUNC_BUTTON_PRESS_IRQ = 15
236};
237
238void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); 215void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
239int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); 216int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
240 217
@@ -281,11 +258,4 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
281int aic3x_headset_detected(struct snd_soc_codec *codec); 258int aic3x_headset_detected(struct snd_soc_codec *codec);
282int aic3x_button_pressed(struct snd_soc_codec *codec); 259int aic3x_button_pressed(struct snd_soc_codec *codec);
283 260
284struct aic3x_setup_data {
285 unsigned int gpio_func[2];
286};
287
288extern struct snd_soc_dai aic3x_dai;
289extern struct snd_soc_codec_device soc_codec_dev_aic3x;
290
291#endif /* _AIC3X_H */ 261#endif /* _AIC3X_H */
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 8651b01ed223..d251ff54a2d3 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -66,8 +66,6 @@
66static void dac33_calculate_times(struct snd_pcm_substream *substream); 66static void dac33_calculate_times(struct snd_pcm_substream *substream);
67static int dac33_prepare_chip(struct snd_pcm_substream *substream); 67static int dac33_prepare_chip(struct snd_pcm_substream *substream);
68 68
69static struct snd_soc_codec *tlv320dac33_codec;
70
71enum dac33_state { 69enum dac33_state {
72 DAC33_IDLE = 0, 70 DAC33_IDLE = 0,
73 DAC33_PREFILL, 71 DAC33_PREFILL,
@@ -93,7 +91,7 @@ struct tlv320dac33_priv {
93 struct mutex mutex; 91 struct mutex mutex;
94 struct workqueue_struct *dac33_wq; 92 struct workqueue_struct *dac33_wq;
95 struct work_struct work; 93 struct work_struct work;
96 struct snd_soc_codec codec; 94 struct snd_soc_codec *codec;
97 struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; 95 struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES];
98 struct snd_pcm_substream *substream; 96 struct snd_pcm_substream *substream;
99 int power_gpio; 97 int power_gpio;
@@ -128,6 +126,8 @@ struct tlv320dac33_priv {
128 unsigned int uthr; 126 unsigned int uthr;
129 127
130 enum dac33_state state; 128 enum dac33_state state;
129 enum snd_soc_control_type control_type;
130 void *control_data;
131}; 131};
132 132
133static const u8 dac33_reg[DAC33_CACHEREGNUM] = { 133static const u8 dac33_reg[DAC33_CACHEREGNUM] = {
@@ -524,6 +524,22 @@ static const struct soc_enum dac33_fifo_mode_enum =
524 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts), 524 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dac33_fifo_mode_texts),
525 dac33_fifo_mode_texts); 525 dac33_fifo_mode_texts);
526 526
527/* L/R Line Output Gain */
528static const char *lr_lineout_gain_texts[] = {
529 "Line -12dB DAC 0dB", "Line -6dB DAC 6dB",
530 "Line 0dB DAC 12dB", "Line 6dB DAC 18dB",
531};
532
533static const struct soc_enum l_lineout_gain_enum =
534 SOC_ENUM_SINGLE(DAC33_LDAC_PWR_CTRL, 0,
535 ARRAY_SIZE(lr_lineout_gain_texts),
536 lr_lineout_gain_texts);
537
538static const struct soc_enum r_lineout_gain_enum =
539 SOC_ENUM_SINGLE(DAC33_RDAC_PWR_CTRL, 0,
540 ARRAY_SIZE(lr_lineout_gain_texts),
541 lr_lineout_gain_texts);
542
527/* 543/*
528 * DACL/R digital volume control: 544 * DACL/R digital volume control:
529 * from 0 dB to -63.5 in 0.5 dB steps 545 * from 0 dB to -63.5 in 0.5 dB steps
@@ -541,6 +557,8 @@ static const struct snd_kcontrol_new dac33_snd_controls[] = {
541 DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1), 557 DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1),
542 SOC_DOUBLE_R("Line to Line Out Volume", 558 SOC_DOUBLE_R("Line to Line Out Volume",
543 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1), 559 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
560 SOC_ENUM("Left Line Output Gain", l_lineout_gain_enum),
561 SOC_ENUM("Right Line Output Gain", r_lineout_gain_enum),
544}; 562};
545 563
546static const struct snd_kcontrol_new dac33_mode_snd_controls[] = { 564static const struct snd_kcontrol_new dac33_mode_snd_controls[] = {
@@ -650,9 +668,8 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,
650 668
651static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33) 669static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
652{ 670{
653 struct snd_soc_codec *codec; 671 struct snd_soc_codec *codec = dac33->codec;
654 672 unsigned int delay;
655 codec = &dac33->codec;
656 673
657 switch (dac33->fifo_mode) { 674 switch (dac33->fifo_mode) {
658 case DAC33_FIFO_MODE1: 675 case DAC33_FIFO_MODE1:
@@ -668,8 +685,9 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
668 dac33_write16(codec, DAC33_PREFILL_MSB, 685 dac33_write16(codec, DAC33_PREFILL_MSB,
669 DAC33_THRREG(dac33->alarm_threshold)); 686 DAC33_THRREG(dac33->alarm_threshold));
670 /* Enable Alarm Threshold IRQ with a delay */ 687 /* Enable Alarm Threshold IRQ with a delay */
671 udelay(SAMPLES_TO_US(dac33->burst_rate, 688 delay = SAMPLES_TO_US(dac33->burst_rate,
672 dac33->alarm_threshold)); 689 dac33->alarm_threshold) + 1000;
690 usleep_range(delay, delay + 500);
673 dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT); 691 dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT);
674 break; 692 break;
675 case DAC33_FIFO_MODE7: 693 case DAC33_FIFO_MODE7:
@@ -695,9 +713,7 @@ static inline void dac33_prefill_handler(struct tlv320dac33_priv *dac33)
695 713
696static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33) 714static inline void dac33_playback_handler(struct tlv320dac33_priv *dac33)
697{ 715{
698 struct snd_soc_codec *codec; 716 struct snd_soc_codec *codec = dac33->codec;
699
700 codec = &dac33->codec;
701 717
702 switch (dac33->fifo_mode) { 718 switch (dac33->fifo_mode) {
703 case DAC33_FIFO_MODE1: 719 case DAC33_FIFO_MODE1:
@@ -726,7 +742,7 @@ static void dac33_work(struct work_struct *work)
726 u8 reg; 742 u8 reg;
727 743
728 dac33 = container_of(work, struct tlv320dac33_priv, work); 744 dac33 = container_of(work, struct tlv320dac33_priv, work);
729 codec = &dac33->codec; 745 codec = dac33->codec;
730 746
731 mutex_lock(&dac33->mutex); 747 mutex_lock(&dac33->mutex);
732 switch (dac33->state) { 748 switch (dac33->state) {
@@ -771,11 +787,11 @@ static irqreturn_t dac33_interrupt_handler(int irq, void *dev)
771 787
772static void dac33_oscwait(struct snd_soc_codec *codec) 788static void dac33_oscwait(struct snd_soc_codec *codec)
773{ 789{
774 int timeout = 20; 790 int timeout = 60;
775 u8 reg; 791 u8 reg;
776 792
777 do { 793 do {
778 msleep(1); 794 usleep_range(1000, 2000);
779 dac33_read(codec, DAC33_INT_OSC_STATUS, &reg); 795 dac33_read(codec, DAC33_INT_OSC_STATUS, &reg);
780 } while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--); 796 } while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--);
781 if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) 797 if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL)
@@ -787,8 +803,7 @@ static int dac33_startup(struct snd_pcm_substream *substream,
787 struct snd_soc_dai *dai) 803 struct snd_soc_dai *dai)
788{ 804{
789 struct snd_soc_pcm_runtime *rtd = substream->private_data; 805 struct snd_soc_pcm_runtime *rtd = substream->private_data;
790 struct snd_soc_device *socdev = rtd->socdev; 806 struct snd_soc_codec *codec = rtd->codec;
791 struct snd_soc_codec *codec = socdev->card->codec;
792 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 807 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
793 808
794 /* Stream started, save the substream pointer */ 809 /* Stream started, save the substream pointer */
@@ -801,8 +816,7 @@ static void dac33_shutdown(struct snd_pcm_substream *substream,
801 struct snd_soc_dai *dai) 816 struct snd_soc_dai *dai)
802{ 817{
803 struct snd_soc_pcm_runtime *rtd = substream->private_data; 818 struct snd_soc_pcm_runtime *rtd = substream->private_data;
804 struct snd_soc_device *socdev = rtd->socdev; 819 struct snd_soc_codec *codec = rtd->codec;
805 struct snd_soc_codec *codec = socdev->card->codec;
806 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 820 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
807 821
808 dac33->substream = NULL; 822 dac33->substream = NULL;
@@ -817,8 +831,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
817 struct snd_soc_dai *dai) 831 struct snd_soc_dai *dai)
818{ 832{
819 struct snd_soc_pcm_runtime *rtd = substream->private_data; 833 struct snd_soc_pcm_runtime *rtd = substream->private_data;
820 struct snd_soc_device *socdev = rtd->socdev; 834 struct snd_soc_codec *codec = rtd->codec;
821 struct snd_soc_codec *codec = socdev->card->codec;
822 835
823 /* Check parameters for validity */ 836 /* Check parameters for validity */
824 switch (params_rate(params)) { 837 switch (params_rate(params)) {
@@ -856,8 +869,7 @@ static int dac33_hw_params(struct snd_pcm_substream *substream,
856static int dac33_prepare_chip(struct snd_pcm_substream *substream) 869static int dac33_prepare_chip(struct snd_pcm_substream *substream)
857{ 870{
858 struct snd_soc_pcm_runtime *rtd = substream->private_data; 871 struct snd_soc_pcm_runtime *rtd = substream->private_data;
859 struct snd_soc_device *socdev = rtd->socdev; 872 struct snd_soc_codec *codec = rtd->codec;
860 struct snd_soc_codec *codec = socdev->card->codec;
861 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 873 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
862 unsigned int oscset, ratioset, pwr_ctrl, reg_tmp; 874 unsigned int oscset, ratioset, pwr_ctrl, reg_tmp;
863 u8 aictrl_a, aictrl_b, fifoctrl_a; 875 u8 aictrl_a, aictrl_b, fifoctrl_a;
@@ -1049,8 +1061,7 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream)
1049static void dac33_calculate_times(struct snd_pcm_substream *substream) 1061static void dac33_calculate_times(struct snd_pcm_substream *substream)
1050{ 1062{
1051 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1063 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1052 struct snd_soc_device *socdev = rtd->socdev; 1064 struct snd_soc_codec *codec = rtd->codec;
1053 struct snd_soc_codec *codec = socdev->card->codec;
1054 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 1065 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
1055 unsigned int period_size = substream->runtime->period_size; 1066 unsigned int period_size = substream->runtime->period_size;
1056 unsigned int rate = substream->runtime->rate; 1067 unsigned int rate = substream->runtime->rate;
@@ -1129,8 +1140,7 @@ static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
1129 struct snd_soc_dai *dai) 1140 struct snd_soc_dai *dai)
1130{ 1141{
1131 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1142 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1132 struct snd_soc_device *socdev = rtd->socdev; 1143 struct snd_soc_codec *codec = rtd->codec;
1133 struct snd_soc_codec *codec = socdev->card->codec;
1134 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 1144 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
1135 int ret = 0; 1145 int ret = 0;
1136 1146
@@ -1163,8 +1173,7 @@ static snd_pcm_sframes_t dac33_dai_delay(
1163 struct snd_soc_dai *dai) 1173 struct snd_soc_dai *dai)
1164{ 1174{
1165 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1175 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1166 struct snd_soc_device *socdev = rtd->socdev; 1176 struct snd_soc_codec *codec = rtd->codec;
1167 struct snd_soc_codec *codec = socdev->card->codec;
1168 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); 1177 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
1169 unsigned long long t0, t1, t_now; 1178 unsigned long long t0, t1, t_now;
1170 unsigned int time_delta, uthr; 1179 unsigned int time_delta, uthr;
@@ -1389,24 +1398,46 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
1389 return 0; 1398 return 0;
1390} 1399}
1391 1400
1392static int dac33_soc_probe(struct platform_device *pdev) 1401static int dac33_soc_probe(struct snd_soc_codec *codec)
1393{ 1402{
1394 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1403 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
1395 struct snd_soc_codec *codec;
1396 struct tlv320dac33_priv *dac33;
1397 int ret = 0; 1404 int ret = 0;
1398 1405
1399 BUG_ON(!tlv320dac33_codec); 1406 codec->control_data = dac33->control_data;
1407 codec->hw_write = (hw_write_t) i2c_master_send;
1408 codec->idle_bias_off = 1;
1409 dac33->codec = codec;
1400 1410
1401 codec = tlv320dac33_codec; 1411 /* Read the tlv320dac33 ID registers */
1402 socdev->card->codec = codec; 1412 ret = dac33_hard_power(codec, 1);
1403 dac33 = snd_soc_codec_get_drvdata(codec); 1413 if (ret != 0) {
1414 dev_err(codec->dev, "Failed to power up codec: %d\n", ret);
1415 goto err_power;
1416 }
1417 dac33_read_id(codec);
1418 dac33_hard_power(codec, 0);
1419
1420 /* Check if the IRQ number is valid and request it */
1421 if (dac33->irq >= 0) {
1422 ret = request_irq(dac33->irq, dac33_interrupt_handler,
1423 IRQF_TRIGGER_RISING | IRQF_DISABLED,
1424 codec->name, codec);
1425 if (ret < 0) {
1426 dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
1427 dac33->irq, ret);
1428 dac33->irq = -1;
1429 }
1430 if (dac33->irq != -1) {
1431 /* Setup work queue */
1432 dac33->dac33_wq =
1433 create_singlethread_workqueue("tlv320dac33");
1434 if (dac33->dac33_wq == NULL) {
1435 free_irq(dac33->irq, codec);
1436 return -ENOMEM;
1437 }
1404 1438
1405 /* register pcms */ 1439 INIT_WORK(&dac33->work, dac33_work);
1406 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 1440 }
1407 if (ret < 0) {
1408 dev_err(codec->dev, "failed to create pcms\n");
1409 goto pcm_err;
1410 } 1441 }
1411 1442
1412 snd_soc_add_controls(codec, dac33_snd_controls, 1443 snd_soc_add_controls(codec, dac33_snd_controls,
@@ -1420,56 +1451,51 @@ static int dac33_soc_probe(struct platform_device *pdev)
1420 snd_soc_add_controls(codec, dac33_fifo_snd_controls, 1451 snd_soc_add_controls(codec, dac33_fifo_snd_controls,
1421 ARRAY_SIZE(dac33_fifo_snd_controls)); 1452 ARRAY_SIZE(dac33_fifo_snd_controls));
1422 } 1453 }
1423
1424 dac33_add_widgets(codec); 1454 dac33_add_widgets(codec);
1425 1455
1426 return 0; 1456err_power:
1427
1428pcm_err:
1429 dac33_hard_power(codec, 0);
1430 return ret; 1457 return ret;
1431} 1458}
1432 1459
1433static int dac33_soc_remove(struct platform_device *pdev) 1460static int dac33_soc_remove(struct snd_soc_codec *codec)
1434{ 1461{
1435 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1462 struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec);
1436 struct snd_soc_codec *codec = socdev->card->codec;
1437 1463
1438 dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); 1464 dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
1439 1465
1440 snd_soc_free_pcms(socdev); 1466 if (dac33->irq >= 0) {
1441 snd_soc_dapm_free(socdev); 1467 free_irq(dac33->irq, dac33->codec);
1442 1468 destroy_workqueue(dac33->dac33_wq);
1469 }
1443 return 0; 1470 return 0;
1444} 1471}
1445 1472
1446static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state) 1473static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
1447{ 1474{
1448 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1449 struct snd_soc_codec *codec = socdev->card->codec;
1450
1451 dac33_set_bias_level(codec, SND_SOC_BIAS_OFF); 1475 dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
1452 1476
1453 return 0; 1477 return 0;
1454} 1478}
1455 1479
1456static int dac33_soc_resume(struct platform_device *pdev) 1480static int dac33_soc_resume(struct snd_soc_codec *codec)
1457{ 1481{
1458 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1459 struct snd_soc_codec *codec = socdev->card->codec;
1460
1461 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1482 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1462 1483
1463 return 0; 1484 return 0;
1464} 1485}
1465 1486
1466struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = { 1487static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
1488 .read = dac33_read_reg_cache,
1489 .write = dac33_write_locked,
1490 .set_bias_level = dac33_set_bias_level,
1491 .reg_cache_size = ARRAY_SIZE(dac33_reg),
1492 .reg_word_size = sizeof(u8),
1493 .reg_cache_default = dac33_reg,
1467 .probe = dac33_soc_probe, 1494 .probe = dac33_soc_probe,
1468 .remove = dac33_soc_remove, 1495 .remove = dac33_soc_remove,
1469 .suspend = dac33_soc_suspend, 1496 .suspend = dac33_soc_suspend,
1470 .resume = dac33_soc_resume, 1497 .resume = dac33_soc_resume,
1471}; 1498};
1472EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
1473 1499
1474#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \ 1500#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \
1475 SNDRV_PCM_RATE_48000) 1501 SNDRV_PCM_RATE_48000)
@@ -1485,8 +1511,8 @@ static struct snd_soc_dai_ops dac33_dai_ops = {
1485 .set_fmt = dac33_set_dai_fmt, 1511 .set_fmt = dac33_set_dai_fmt,
1486}; 1512};
1487 1513
1488struct snd_soc_dai dac33_dai = { 1514static struct snd_soc_dai_driver dac33_dai = {
1489 .name = "tlv320dac33", 1515 .name = "tlv320dac33-hifi",
1490 .playback = { 1516 .playback = {
1491 .stream_name = "Playback", 1517 .stream_name = "Playback",
1492 .channels_min = 2, 1518 .channels_min = 2,
@@ -1495,14 +1521,12 @@ struct snd_soc_dai dac33_dai = {
1495 .formats = DAC33_FORMATS,}, 1521 .formats = DAC33_FORMATS,},
1496 .ops = &dac33_dai_ops, 1522 .ops = &dac33_dai_ops,
1497}; 1523};
1498EXPORT_SYMBOL_GPL(dac33_dai);
1499 1524
1500static int __devinit dac33_i2c_probe(struct i2c_client *client, 1525static int __devinit dac33_i2c_probe(struct i2c_client *client,
1501 const struct i2c_device_id *id) 1526 const struct i2c_device_id *id)
1502{ 1527{
1503 struct tlv320dac33_platform_data *pdata; 1528 struct tlv320dac33_platform_data *pdata;
1504 struct tlv320dac33_priv *dac33; 1529 struct tlv320dac33_priv *dac33;
1505 struct snd_soc_codec *codec;
1506 int ret, i; 1530 int ret, i;
1507 1531
1508 if (client->dev.platform_data == NULL) { 1532 if (client->dev.platform_data == NULL) {
@@ -1515,33 +1539,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
1515 if (dac33 == NULL) 1539 if (dac33 == NULL)
1516 return -ENOMEM; 1540 return -ENOMEM;
1517 1541
1518 codec = &dac33->codec; 1542 dac33->control_data = client;
1519 snd_soc_codec_set_drvdata(codec, dac33);
1520 codec->control_data = client;
1521
1522 mutex_init(&codec->mutex);
1523 mutex_init(&dac33->mutex); 1543 mutex_init(&dac33->mutex);
1524 spin_lock_init(&dac33->lock); 1544 spin_lock_init(&dac33->lock);
1525 INIT_LIST_HEAD(&codec->dapm_widgets);
1526 INIT_LIST_HEAD(&codec->dapm_paths);
1527
1528 codec->name = "tlv320dac33";
1529 codec->owner = THIS_MODULE;
1530 codec->read = dac33_read_reg_cache;
1531 codec->write = dac33_write_locked;
1532 codec->hw_write = (hw_write_t) i2c_master_send;
1533 codec->bias_level = SND_SOC_BIAS_OFF;
1534 codec->set_bias_level = dac33_set_bias_level;
1535 codec->idle_bias_off = 1;
1536 codec->dai = &dac33_dai;
1537 codec->num_dai = 1;
1538 codec->reg_cache_size = ARRAY_SIZE(dac33_reg);
1539 codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg),
1540 GFP_KERNEL);
1541 if (codec->reg_cache == NULL) {
1542 ret = -ENOMEM;
1543 goto error_reg;
1544 }
1545 1545
1546 i2c_set_clientdata(client, dac33); 1546 i2c_set_clientdata(client, dac33);
1547 1547
@@ -1561,125 +1561,59 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
1561 /* Disable FIFO use by default */ 1561 /* Disable FIFO use by default */
1562 dac33->fifo_mode = DAC33_FIFO_BYPASS; 1562 dac33->fifo_mode = DAC33_FIFO_BYPASS;
1563 1563
1564 tlv320dac33_codec = codec;
1565
1566 codec->dev = &client->dev;
1567 dac33_dai.dev = codec->dev;
1568
1569 /* Check if the reset GPIO number is valid and request it */ 1564 /* Check if the reset GPIO number is valid and request it */
1570 if (dac33->power_gpio >= 0) { 1565 if (dac33->power_gpio >= 0) {
1571 ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset"); 1566 ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset");
1572 if (ret < 0) { 1567 if (ret < 0) {
1573 dev_err(codec->dev, 1568 dev_err(&client->dev,
1574 "Failed to request reset GPIO (%d)\n", 1569 "Failed to request reset GPIO (%d)\n",
1575 dac33->power_gpio); 1570 dac33->power_gpio);
1576 snd_soc_unregister_dai(&dac33_dai); 1571 goto err_gpio;
1577 snd_soc_unregister_codec(codec);
1578 goto error_gpio;
1579 } 1572 }
1580 gpio_direction_output(dac33->power_gpio, 0); 1573 gpio_direction_output(dac33->power_gpio, 0);
1581 } 1574 }
1582 1575
1583 /* Check if the IRQ number is valid and request it */
1584 if (dac33->irq >= 0) {
1585 ret = request_irq(dac33->irq, dac33_interrupt_handler,
1586 IRQF_TRIGGER_RISING | IRQF_DISABLED,
1587 codec->name, codec);
1588 if (ret < 0) {
1589 dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
1590 dac33->irq, ret);
1591 dac33->irq = -1;
1592 }
1593 if (dac33->irq != -1) {
1594 /* Setup work queue */
1595 dac33->dac33_wq =
1596 create_singlethread_workqueue("tlv320dac33");
1597 if (dac33->dac33_wq == NULL) {
1598 free_irq(dac33->irq, &dac33->codec);
1599 ret = -ENOMEM;
1600 goto error_wq;
1601 }
1602
1603 INIT_WORK(&dac33->work, dac33_work);
1604 }
1605 }
1606
1607 for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++) 1576 for (i = 0; i < ARRAY_SIZE(dac33->supplies); i++)
1608 dac33->supplies[i].supply = dac33_supply_names[i]; 1577 dac33->supplies[i].supply = dac33_supply_names[i];
1609 1578
1610 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(dac33->supplies), 1579 ret = regulator_bulk_get(&client->dev, ARRAY_SIZE(dac33->supplies),
1611 dac33->supplies); 1580 dac33->supplies);
1612 1581
1613 if (ret != 0) { 1582 if (ret != 0) {
1614 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 1583 dev_err(&client->dev, "Failed to request supplies: %d\n", ret);
1615 goto err_get; 1584 goto err_get;
1616 } 1585 }
1617 1586
1618 /* Read the tlv320dac33 ID registers */ 1587 ret = snd_soc_register_codec(&client->dev,
1619 ret = dac33_hard_power(codec, 1); 1588 &soc_codec_dev_tlv320dac33, &dac33_dai, 1);
1620 if (ret != 0) { 1589 if (ret < 0)
1621 dev_err(codec->dev, "Failed to power up codec: %d\n", ret); 1590 goto err_register;
1622 goto error_codec;
1623 }
1624 dac33_read_id(codec);
1625 dac33_hard_power(codec, 0);
1626
1627 ret = snd_soc_register_codec(codec);
1628 if (ret != 0) {
1629 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1630 goto error_codec;
1631 }
1632
1633 ret = snd_soc_register_dai(&dac33_dai);
1634 if (ret != 0) {
1635 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1636 snd_soc_unregister_codec(codec);
1637 goto error_codec;
1638 }
1639 1591
1640 return ret; 1592 return ret;
1641 1593err_register:
1642error_codec:
1643 regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); 1594 regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
1644err_get: 1595err_get:
1645 if (dac33->irq >= 0) {
1646 free_irq(dac33->irq, &dac33->codec);
1647 destroy_workqueue(dac33->dac33_wq);
1648 }
1649error_wq:
1650 if (dac33->power_gpio >= 0) 1596 if (dac33->power_gpio >= 0)
1651 gpio_free(dac33->power_gpio); 1597 gpio_free(dac33->power_gpio);
1652error_gpio: 1598err_gpio:
1653 kfree(codec->reg_cache);
1654error_reg:
1655 tlv320dac33_codec = NULL;
1656 kfree(dac33); 1599 kfree(dac33);
1657
1658 return ret; 1600 return ret;
1659} 1601}
1660 1602
1661static int __devexit dac33_i2c_remove(struct i2c_client *client) 1603static int __devexit dac33_i2c_remove(struct i2c_client *client)
1662{ 1604{
1663 struct tlv320dac33_priv *dac33; 1605 struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client);
1664
1665 dac33 = i2c_get_clientdata(client);
1666 1606
1667 if (unlikely(dac33->chip_power)) 1607 if (unlikely(dac33->chip_power))
1668 dac33_hard_power(&dac33->codec, 0); 1608 dac33_hard_power(dac33->codec, 0);
1669 1609
1670 if (dac33->power_gpio >= 0) 1610 if (dac33->power_gpio >= 0)
1671 gpio_free(dac33->power_gpio); 1611 gpio_free(dac33->power_gpio);
1672 if (dac33->irq >= 0)
1673 free_irq(dac33->irq, &dac33->codec);
1674 1612
1675 regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); 1613 regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
1676 1614
1677 destroy_workqueue(dac33->dac33_wq); 1615 snd_soc_unregister_codec(&client->dev);
1678 snd_soc_unregister_dai(&dac33_dai);
1679 snd_soc_unregister_codec(&dac33->codec);
1680 kfree(dac33->codec.reg_cache);
1681 kfree(dac33); 1616 kfree(dac33);
1682 tlv320dac33_codec = NULL;
1683 1617
1684 return 0; 1618 return 0;
1685} 1619}
@@ -1694,7 +1628,7 @@ static const struct i2c_device_id tlv320dac33_i2c_id[] = {
1694 1628
1695static struct i2c_driver tlv320dac33_i2c_driver = { 1629static struct i2c_driver tlv320dac33_i2c_driver = {
1696 .driver = { 1630 .driver = {
1697 .name = "tlv320dac33", 1631 .name = "tlv320dac33-codec",
1698 .owner = THIS_MODULE, 1632 .owner = THIS_MODULE,
1699 }, 1633 },
1700 .probe = dac33_i2c_probe, 1634 .probe = dac33_i2c_probe,
diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h
index eb8ae07f0bd2..7c318b5da437 100644
--- a/sound/soc/codecs/tlv320dac33.h
+++ b/sound/soc/codecs/tlv320dac33.h
@@ -261,7 +261,4 @@
261#define TLV320DAC33_MCLK 0 261#define TLV320DAC33_MCLK 0
262#define TLV320DAC33_SLEEPCLK 1 262#define TLV320DAC33_SLEEPCLK 1
263 263
264extern struct snd_soc_dai dac33_dai;
265extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33;
266
267#endif /* __TLV320DAC33_H */ 264#endif /* __TLV320DAC33_H */
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 99b70e5978a2..329acc1a2074 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -98,16 +98,21 @@ static u8 tpa6130a2_read(int reg)
98 return data->regs[reg]; 98 return data->regs[reg];
99} 99}
100 100
101static void tpa6130a2_initialize(void) 101static int tpa6130a2_initialize(void)
102{ 102{
103 struct tpa6130a2_data *data; 103 struct tpa6130a2_data *data;
104 int i; 104 int i, ret = 0;
105 105
106 BUG_ON(tpa6130a2_client == NULL); 106 BUG_ON(tpa6130a2_client == NULL);
107 data = i2c_get_clientdata(tpa6130a2_client); 107 data = i2c_get_clientdata(tpa6130a2_client);
108 108
109 for (i = 1; i < TPA6130A2_REG_VERSION; i++) 109 for (i = 1; i < TPA6130A2_REG_VERSION; i++) {
110 tpa6130a2_i2c_write(i, data->regs[i]); 110 ret = tpa6130a2_i2c_write(i, data->regs[i]);
111 if (ret < 0)
112 break;
113 }
114
115 return ret;
111} 116}
112 117
113static int tpa6130a2_power(int power) 118static int tpa6130a2_power(int power)
@@ -133,7 +138,16 @@ static int tpa6130a2_power(int power)
133 } 138 }
134 139
135 data->power_state = 1; 140 data->power_state = 1;
136 tpa6130a2_initialize(); 141 ret = tpa6130a2_initialize();
142 if (ret < 0) {
143 dev_err(&tpa6130a2_client->dev,
144 "Failed to initialize chip\n");
145 if (data->power_gpio >= 0)
146 gpio_set_value(data->power_gpio, 0);
147 regulator_disable(data->supply);
148 data->power_state = 0;
149 goto exit;
150 }
137 151
138 /* Clear SWS */ 152 /* Clear SWS */
139 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 153 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
@@ -375,7 +389,9 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
375{ 389{
376 struct tpa6130a2_data *data; 390 struct tpa6130a2_data *data;
377 391
378 BUG_ON(tpa6130a2_client == NULL); 392 if (tpa6130a2_client == NULL)
393 return -ENODEV;
394
379 data = i2c_get_clientdata(tpa6130a2_client); 395 data = i2c_get_clientdata(tpa6130a2_client);
380 396
381 snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, 397 snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 7b618bbff884..cbebec6ba1ba 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -36,7 +36,16 @@
36#include <sound/initval.h> 36#include <sound/initval.h>
37#include <sound/tlv.h> 37#include <sound/tlv.h>
38 38
39#include "twl4030.h" 39/* Register descriptions are here */
40#include <linux/mfd/twl4030-codec.h>
41
42/* Shadow register used by the audio driver */
43#define TWL4030_REG_SW_SHADOW 0x4A
44#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
45
46/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
47#define TWL4030_HFL_EN 0x01
48#define TWL4030_HFR_EN 0x02
40 49
41/* 50/*
42 * twl4030 register cache & default register settings 51 * twl4030 register cache & default register settings
@@ -277,21 +286,19 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec)
277 286
278} 287}
279 288
280static void twl4030_init_chip(struct platform_device *pdev) 289static void twl4030_init_chip(struct snd_soc_codec *codec)
281{ 290{
282 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 291 struct twl4030_codec_audio_data *pdata = dev_get_platdata(codec->dev);
283 struct twl4030_setup_data *setup = socdev->codec_data;
284 struct snd_soc_codec *codec = socdev->card->codec;
285 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 292 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
286 u8 reg, byte; 293 u8 reg, byte;
287 int i = 0; 294 int i = 0;
288 295
289 /* Check defaults, if instructed before anything else */ 296 /* Check defaults, if instructed before anything else */
290 if (setup && setup->check_defaults) 297 if (pdata && pdata->check_defaults)
291 twl4030_check_defaults(codec); 298 twl4030_check_defaults(codec);
292 299
293 /* Reset registers, if no setup data or if instructed to do so */ 300 /* Reset registers, if no setup data or if instructed to do so */
294 if (!setup || (setup && setup->reset_registers)) 301 if (!pdata || (pdata && pdata->reset_registers))
295 twl4030_reset_registers(codec); 302 twl4030_reset_registers(codec);
296 303
297 /* Refresh APLL_CTL register from HW */ 304 /* Refresh APLL_CTL register from HW */
@@ -312,20 +319,14 @@ static void twl4030_init_chip(struct platform_device *pdev)
312 twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32); 319 twl4030_write(codec, TWL4030_REG_ARXR2_APGA_CTL, 0x32);
313 320
314 /* Machine dependent setup */ 321 /* Machine dependent setup */
315 if (!setup) 322 if (!pdata)
316 return; 323 return;
317 324
318 twl4030->digimic_delay = setup->digimic_delay; 325 twl4030->digimic_delay = pdata->digimic_delay;
319
320 /* Configuration for headset ramp delay from setup data */
321 if (setup->sysclk != twl4030->sysclk)
322 dev_warn(codec->dev,
323 "Mismatch in APLL mclk: %u (configured: %u)\n",
324 setup->sysclk, twl4030->sysclk);
325 326
326 reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); 327 reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
327 reg &= ~TWL4030_RAMP_DELAY; 328 reg &= ~TWL4030_RAMP_DELAY;
328 reg |= (setup->ramp_delay_value << 2); 329 reg |= (pdata->ramp_delay_value << 2);
329 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg); 330 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, reg);
330 331
331 /* initiate offset cancellation */ 332 /* initiate offset cancellation */
@@ -333,7 +334,7 @@ static void twl4030_init_chip(struct platform_device *pdev)
333 334
334 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); 335 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
335 reg &= ~TWL4030_OFFSET_CNCL_SEL; 336 reg &= ~TWL4030_OFFSET_CNCL_SEL;
336 reg |= setup->offset_cncl_path; 337 reg |= pdata->offset_cncl_path;
337 twl4030_write(codec, TWL4030_REG_ANAMICL, 338 twl4030_write(codec, TWL4030_REG_ANAMICL,
338 reg | TWL4030_CNCL_OFFSET_START); 339 reg | TWL4030_CNCL_OFFSET_START);
339 340
@@ -718,9 +719,7 @@ static int aif_event(struct snd_soc_dapm_widget *w,
718 719
719static void headset_ramp(struct snd_soc_codec *codec, int ramp) 720static void headset_ramp(struct snd_soc_codec *codec, int ramp)
720{ 721{
721 struct snd_soc_device *socdev = codec->socdev; 722 struct twl4030_codec_audio_data *pdata = codec->dev->platform_data;
722 struct twl4030_setup_data *setup = socdev->codec_data;
723
724 unsigned char hs_gain, hs_pop; 723 unsigned char hs_gain, hs_pop;
725 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 724 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
726 /* Base values for ramp delay calculation: 2^19 - 2^26 */ 725 /* Base values for ramp delay calculation: 2^19 - 2^26 */
@@ -732,9 +731,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
732 731
733 /* Enable external mute control, this dramatically reduces 732 /* Enable external mute control, this dramatically reduces
734 * the pop-noise */ 733 * the pop-noise */
735 if (setup && setup->hs_extmute) { 734 if (pdata && pdata->hs_extmute) {
736 if (setup->set_hs_extmute) { 735 if (pdata->set_hs_extmute) {
737 setup->set_hs_extmute(1); 736 pdata->set_hs_extmute(1);
738 } else { 737 } else {
739 hs_pop |= TWL4030_EXTMUTE; 738 hs_pop |= TWL4030_EXTMUTE;
740 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 739 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
@@ -772,9 +771,9 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp)
772 } 771 }
773 772
774 /* Disable external mute */ 773 /* Disable external mute */
775 if (setup && setup->hs_extmute) { 774 if (pdata && pdata->hs_extmute) {
776 if (setup->set_hs_extmute) { 775 if (pdata->set_hs_extmute) {
777 setup->set_hs_extmute(0); 776 pdata->set_hs_extmute(0);
778 } else { 777 } else {
779 hs_pop &= ~TWL4030_EXTMUTE; 778 hs_pop &= ~TWL4030_EXTMUTE;
780 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 779 twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
@@ -1707,8 +1706,7 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
1707 struct snd_soc_dai *dai) 1706 struct snd_soc_dai *dai)
1708{ 1707{
1709 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1708 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1710 struct snd_soc_device *socdev = rtd->socdev; 1709 struct snd_soc_codec *codec = rtd->codec;
1711 struct snd_soc_codec *codec = socdev->card->codec;
1712 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 1710 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
1713 1711
1714 if (twl4030->master_substream) { 1712 if (twl4030->master_substream) {
@@ -1738,8 +1736,7 @@ static void twl4030_shutdown(struct snd_pcm_substream *substream,
1738 struct snd_soc_dai *dai) 1736 struct snd_soc_dai *dai)
1739{ 1737{
1740 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1738 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1741 struct snd_soc_device *socdev = rtd->socdev; 1739 struct snd_soc_codec *codec = rtd->codec;
1742 struct snd_soc_codec *codec = socdev->card->codec;
1743 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 1740 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
1744 1741
1745 if (twl4030->master_substream == substream) 1742 if (twl4030->master_substream == substream)
@@ -1764,8 +1761,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
1764 struct snd_soc_dai *dai) 1761 struct snd_soc_dai *dai)
1765{ 1762{
1766 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1763 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1767 struct snd_soc_device *socdev = rtd->socdev; 1764 struct snd_soc_codec *codec = rtd->codec;
1768 struct snd_soc_codec *codec = socdev->card->codec;
1769 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 1765 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
1770 u8 mode, old_mode, format, old_format; 1766 u8 mode, old_mode, format, old_format;
1771 1767
@@ -1999,8 +1995,7 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
1999 struct snd_soc_dai *dai) 1995 struct snd_soc_dai *dai)
2000{ 1996{
2001 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1997 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2002 struct snd_soc_device *socdev = rtd->socdev; 1998 struct snd_soc_codec *codec = rtd->codec;
2003 struct snd_soc_codec *codec = socdev->card->codec;
2004 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 1999 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
2005 u8 mode; 2000 u8 mode;
2006 2001
@@ -2033,8 +2028,7 @@ static void twl4030_voice_shutdown(struct snd_pcm_substream *substream,
2033 struct snd_soc_dai *dai) 2028 struct snd_soc_dai *dai)
2034{ 2029{
2035 struct snd_soc_pcm_runtime *rtd = substream->private_data; 2030 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2036 struct snd_soc_device *socdev = rtd->socdev; 2031 struct snd_soc_codec *codec = rtd->codec;
2037 struct snd_soc_codec *codec = socdev->card->codec;
2038 2032
2039 /* Enable voice digital filters */ 2033 /* Enable voice digital filters */
2040 twl4030_voice_enable(codec, substream->stream, 0); 2034 twl4030_voice_enable(codec, substream->stream, 0);
@@ -2044,8 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
2044 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 2038 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
2045{ 2039{
2046 struct snd_soc_pcm_runtime *rtd = substream->private_data; 2040 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2047 struct snd_soc_device *socdev = rtd->socdev; 2041 struct snd_soc_codec *codec = rtd->codec;
2048 struct snd_soc_codec *codec = socdev->card->codec;
2049 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); 2042 struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
2050 u8 old_mode, mode; 2043 u8 old_mode, mode;
2051 2044
@@ -2175,7 +2168,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
2175#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) 2168#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
2176#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) 2169#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
2177 2170
2178static struct snd_soc_dai_ops twl4030_dai_ops = { 2171static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
2179 .startup = twl4030_startup, 2172 .startup = twl4030_startup,
2180 .shutdown = twl4030_shutdown, 2173 .shutdown = twl4030_shutdown,
2181 .hw_params = twl4030_hw_params, 2174 .hw_params = twl4030_hw_params,
@@ -2193,9 +2186,9 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
2193 .set_tristate = twl4030_voice_set_tristate, 2186 .set_tristate = twl4030_voice_set_tristate,
2194}; 2187};
2195 2188
2196struct snd_soc_dai twl4030_dai[] = { 2189static struct snd_soc_dai_driver twl4030_dai[] = {
2197{ 2190{
2198 .name = "twl4030", 2191 .name = "twl4030-hifi",
2199 .playback = { 2192 .playback = {
2200 .stream_name = "HiFi Playback", 2193 .stream_name = "HiFi Playback",
2201 .channels_min = 2, 2194 .channels_min = 2,
@@ -2208,10 +2201,10 @@ struct snd_soc_dai twl4030_dai[] = {
2208 .channels_max = 4, 2201 .channels_max = 4,
2209 .rates = TWL4030_RATES, 2202 .rates = TWL4030_RATES,
2210 .formats = TWL4030_FORMATS,}, 2203 .formats = TWL4030_FORMATS,},
2211 .ops = &twl4030_dai_ops, 2204 .ops = &twl4030_dai_hifi_ops,
2212}, 2205},
2213{ 2206{
2214 .name = "twl4030 Voice", 2207 .name = "twl4030-voice",
2215 .playback = { 2208 .playback = {
2216 .stream_name = "Voice Playback", 2209 .stream_name = "Voice Playback",
2217 .channels_min = 1, 2210 .channels_min = 1,
@@ -2227,164 +2220,91 @@ struct snd_soc_dai twl4030_dai[] = {
2227 .ops = &twl4030_dai_voice_ops, 2220 .ops = &twl4030_dai_voice_ops,
2228}, 2221},
2229}; 2222};
2230EXPORT_SYMBOL_GPL(twl4030_dai);
2231 2223
2232static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state) 2224static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
2233{ 2225{
2234 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2235 struct snd_soc_codec *codec = socdev->card->codec;
2236
2237 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); 2226 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
2238
2239 return 0; 2227 return 0;
2240} 2228}
2241 2229
2242static int twl4030_soc_resume(struct platform_device *pdev) 2230static int twl4030_soc_resume(struct snd_soc_codec *codec)
2243{ 2231{
2244 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2245 struct snd_soc_codec *codec = socdev->card->codec;
2246
2247 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 2232 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2248 return 0; 2233 return 0;
2249} 2234}
2250 2235
2251static struct snd_soc_codec *twl4030_codec; 2236static int twl4030_soc_probe(struct snd_soc_codec *codec)
2252
2253static int twl4030_soc_probe(struct platform_device *pdev)
2254{ 2237{
2255 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2238 struct twl4030_priv *twl4030;
2256 struct snd_soc_codec *codec;
2257 int ret;
2258
2259 BUG_ON(!twl4030_codec);
2260
2261 codec = twl4030_codec;
2262 socdev->card->codec = codec;
2263
2264 twl4030_init_chip(pdev);
2265 2239
2266 /* register pcms */ 2240 twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
2267 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 2241 if (twl4030 == NULL) {
2268 if (ret < 0) { 2242 printk("Can not allocate memroy\n");
2269 dev_err(&pdev->dev, "failed to create pcms\n"); 2243 return -ENOMEM;
2270 return ret;
2271 } 2244 }
2245 snd_soc_codec_set_drvdata(codec, twl4030);
2246 /* Set the defaults, and power up the codec */
2247 twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
2248 codec->idle_bias_off = 1;
2249
2250 twl4030_init_chip(codec);
2272 2251
2273 snd_soc_add_controls(codec, twl4030_snd_controls, 2252 snd_soc_add_controls(codec, twl4030_snd_controls,
2274 ARRAY_SIZE(twl4030_snd_controls)); 2253 ARRAY_SIZE(twl4030_snd_controls));
2275 twl4030_add_widgets(codec); 2254 twl4030_add_widgets(codec);
2276
2277 return 0; 2255 return 0;
2278} 2256}
2279 2257
2280static int twl4030_soc_remove(struct platform_device *pdev) 2258static int twl4030_soc_remove(struct snd_soc_codec *codec)
2281{ 2259{
2282 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2283 struct snd_soc_codec *codec = socdev->card->codec;
2284
2285 /* Reset registers to their chip default before leaving */ 2260 /* Reset registers to their chip default before leaving */
2286 twl4030_reset_registers(codec); 2261 twl4030_reset_registers(codec);
2287 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); 2262 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
2288 snd_soc_free_pcms(socdev);
2289 snd_soc_dapm_free(socdev);
2290
2291 return 0; 2263 return 0;
2292} 2264}
2293 2265
2266static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
2267 .probe = twl4030_soc_probe,
2268 .remove = twl4030_soc_remove,
2269 .suspend = twl4030_soc_suspend,
2270 .resume = twl4030_soc_resume,
2271 .read = twl4030_read_reg_cache,
2272 .write = twl4030_write,
2273 .set_bias_level = twl4030_set_bias_level,
2274 .reg_cache_size = sizeof(twl4030_reg),
2275 .reg_word_size = sizeof(u8),
2276 .reg_cache_default = twl4030_reg,
2277};
2278
2294static int __devinit twl4030_codec_probe(struct platform_device *pdev) 2279static int __devinit twl4030_codec_probe(struct platform_device *pdev)
2295{ 2280{
2296 struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data; 2281 struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data;
2297 struct snd_soc_codec *codec;
2298 struct twl4030_priv *twl4030;
2299 int ret;
2300 2282
2301 if (!pdata) { 2283 if (!pdata) {
2302 dev_err(&pdev->dev, "platform_data is missing\n"); 2284 dev_err(&pdev->dev, "platform_data is missing\n");
2303 return -EINVAL; 2285 return -EINVAL;
2304 } 2286 }
2305 2287
2306 twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); 2288 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030,
2307 if (twl4030 == NULL) { 2289 twl4030_dai, ARRAY_SIZE(twl4030_dai));
2308 dev_err(&pdev->dev, "Can not allocate memroy\n");
2309 return -ENOMEM;
2310 }
2311
2312 codec = &twl4030->codec;
2313 snd_soc_codec_set_drvdata(codec, twl4030);
2314 codec->dev = &pdev->dev;
2315 twl4030_dai[0].dev = &pdev->dev;
2316 twl4030_dai[1].dev = &pdev->dev;
2317
2318 mutex_init(&codec->mutex);
2319 INIT_LIST_HEAD(&codec->dapm_widgets);
2320 INIT_LIST_HEAD(&codec->dapm_paths);
2321
2322 codec->name = "twl4030";
2323 codec->owner = THIS_MODULE;
2324 codec->read = twl4030_read_reg_cache;
2325 codec->write = twl4030_write;
2326 codec->set_bias_level = twl4030_set_bias_level;
2327 codec->idle_bias_off = 1;
2328 codec->dai = twl4030_dai;
2329 codec->num_dai = ARRAY_SIZE(twl4030_dai);
2330 codec->reg_cache_size = sizeof(twl4030_reg);
2331 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
2332 GFP_KERNEL);
2333 if (codec->reg_cache == NULL) {
2334 ret = -ENOMEM;
2335 goto error_cache;
2336 }
2337
2338 platform_set_drvdata(pdev, twl4030);
2339 twl4030_codec = codec;
2340
2341 /* Set the defaults, and power up the codec */
2342 twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
2343 codec->bias_level = SND_SOC_BIAS_OFF;
2344
2345 ret = snd_soc_register_codec(codec);
2346 if (ret != 0) {
2347 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
2348 goto error_codec;
2349 }
2350
2351 ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
2352 if (ret != 0) {
2353 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
2354 snd_soc_unregister_codec(codec);
2355 goto error_codec;
2356 }
2357
2358 return 0;
2359
2360error_codec:
2361 twl4030_codec_enable(codec, 0);
2362 kfree(codec->reg_cache);
2363error_cache:
2364 kfree(twl4030);
2365 return ret;
2366} 2290}
2367 2291
2368static int __devexit twl4030_codec_remove(struct platform_device *pdev) 2292static int __devexit twl4030_codec_remove(struct platform_device *pdev)
2369{ 2293{
2370 struct twl4030_priv *twl4030 = platform_get_drvdata(pdev); 2294 struct twl4030_priv *twl4030 = dev_get_drvdata(&pdev->dev);
2371 2295
2372 snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); 2296 snd_soc_unregister_codec(&pdev->dev);
2373 snd_soc_unregister_codec(&twl4030->codec);
2374 kfree(twl4030->codec.reg_cache);
2375 kfree(twl4030); 2297 kfree(twl4030);
2376
2377 twl4030_codec = NULL;
2378 return 0; 2298 return 0;
2379} 2299}
2380 2300
2381MODULE_ALIAS("platform:twl4030_codec_audio"); 2301MODULE_ALIAS("platform:twl4030-codec");
2382 2302
2383static struct platform_driver twl4030_codec_driver = { 2303static struct platform_driver twl4030_codec_driver = {
2384 .probe = twl4030_codec_probe, 2304 .probe = twl4030_codec_probe,
2385 .remove = __devexit_p(twl4030_codec_remove), 2305 .remove = __devexit_p(twl4030_codec_remove),
2386 .driver = { 2306 .driver = {
2387 .name = "twl4030_codec_audio", 2307 .name = "twl4030-codec",
2388 .owner = THIS_MODULE, 2308 .owner = THIS_MODULE,
2389 }, 2309 },
2390}; 2310};
@@ -2401,14 +2321,6 @@ static void __exit twl4030_exit(void)
2401} 2321}
2402module_exit(twl4030_exit); 2322module_exit(twl4030_exit);
2403 2323
2404struct snd_soc_codec_device soc_codec_dev_twl4030 = {
2405 .probe = twl4030_soc_probe,
2406 .remove = twl4030_soc_remove,
2407 .suspend = twl4030_soc_suspend,
2408 .resume = twl4030_soc_resume,
2409};
2410EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
2411
2412MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); 2324MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
2413MODULE_AUTHOR("Steve Sakoman"); 2325MODULE_AUTHOR("Steve Sakoman");
2414MODULE_LICENSE("GPL"); 2326MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
deleted file mode 100644
index 6c57430f6e24..000000000000
--- a/sound/soc/codecs/twl4030.h
+++ /dev/null
@@ -1,55 +0,0 @@
1/*
2 * ALSA SoC TWL4030 codec driver
3 *
4 * Author: Steve Sakoman <steve@sakoman.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#ifndef __TWL4030_AUDIO_H__
23#define __TWL4030_AUDIO_H__
24
25/* Register descriptions are here */
26#include <linux/mfd/twl4030-codec.h>
27
28/* Shadow register used by the audio driver */
29#define TWL4030_REG_SW_SHADOW 0x4A
30#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
31
32/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
33#define TWL4030_HFL_EN 0x01
34#define TWL4030_HFR_EN 0x02
35
36#define TWL4030_DAI_HIFI 0
37#define TWL4030_DAI_VOICE 1
38
39extern struct snd_soc_dai twl4030_dai[2];
40extern struct snd_soc_codec_device soc_codec_dev_twl4030;
41
42struct twl4030_setup_data {
43 unsigned int ramp_delay_value;
44 unsigned int digimic_delay; /* in ms */
45 unsigned int sysclk;
46 unsigned int offset_cncl_path;
47 unsigned int check_defaults:1;
48 unsigned int reset_registers:1;
49 unsigned int hs_extmute:1;
50 void (*set_hs_extmute)(int mute);
51};
52
53#endif /* End of __TWL4030_AUDIO_H__ */
54
55
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 64a807f1a8a1..10f6e5214511 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -45,7 +45,6 @@
45 45
46/* codec private data */ 46/* codec private data */
47struct twl6040_data { 47struct twl6040_data {
48 struct snd_soc_codec codec;
49 int audpwron; 48 int audpwron;
50 int naudint; 49 int naudint;
51 int codec_powered; 50 int codec_powered;
@@ -770,8 +769,7 @@ static int twl6040_startup(struct snd_pcm_substream *substream,
770 struct snd_soc_dai *dai) 769 struct snd_soc_dai *dai)
771{ 770{
772 struct snd_soc_pcm_runtime *rtd = substream->private_data; 771 struct snd_soc_pcm_runtime *rtd = substream->private_data;
773 struct snd_soc_device *socdev = rtd->socdev; 772 struct snd_soc_codec *codec = rtd->codec;
774 struct snd_soc_codec *codec = socdev->card->codec;
775 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 773 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
776 774
777 if (!priv->sysclk) { 775 if (!priv->sysclk) {
@@ -803,8 +801,7 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
803 struct snd_soc_dai *dai) 801 struct snd_soc_dai *dai)
804{ 802{
805 struct snd_soc_pcm_runtime *rtd = substream->private_data; 803 struct snd_soc_pcm_runtime *rtd = substream->private_data;
806 struct snd_soc_device *socdev = rtd->socdev; 804 struct snd_soc_codec *codec = rtd->codec;
807 struct snd_soc_codec *codec = socdev->card->codec;
808 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 805 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
809 u8 lppllctl; 806 u8 lppllctl;
810 int rate; 807 int rate;
@@ -839,8 +836,7 @@ static int twl6040_trigger(struct snd_pcm_substream *substream,
839 int cmd, struct snd_soc_dai *dai) 836 int cmd, struct snd_soc_dai *dai)
840{ 837{
841 struct snd_soc_pcm_runtime *rtd = substream->private_data; 838 struct snd_soc_pcm_runtime *rtd = substream->private_data;
842 struct snd_soc_device *socdev = rtd->socdev; 839 struct snd_soc_codec *codec = rtd->codec;
843 struct snd_soc_codec *codec = socdev->card->codec;
844 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 840 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
845 841
846 switch (cmd) { 842 switch (cmd) {
@@ -978,8 +974,8 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
978 .set_sysclk = twl6040_set_dai_sysclk, 974 .set_sysclk = twl6040_set_dai_sysclk,
979}; 975};
980 976
981struct snd_soc_dai twl6040_dai = { 977static struct snd_soc_dai_driver twl6040_dai = {
982 .name = "twl6040", 978 .name = "twl6040-hifi",
983 .playback = { 979 .playback = {
984 .stream_name = "Playback", 980 .stream_name = "Playback",
985 .channels_min = 1, 981 .channels_min = 1,
@@ -996,24 +992,17 @@ struct snd_soc_dai twl6040_dai = {
996 }, 992 },
997 .ops = &twl6040_dai_ops, 993 .ops = &twl6040_dai_ops,
998}; 994};
999EXPORT_SYMBOL_GPL(twl6040_dai);
1000 995
1001#ifdef CONFIG_PM 996#ifdef CONFIG_PM
1002static int twl6040_suspend(struct platform_device *pdev, pm_message_t state) 997static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
1003{ 998{
1004 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1005 struct snd_soc_codec *codec = socdev->card->codec;
1006
1007 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); 999 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1008 1000
1009 return 0; 1001 return 0;
1010} 1002}
1011 1003
1012static int twl6040_resume(struct platform_device *pdev) 1004static int twl6040_resume(struct snd_soc_codec *codec)
1013{ 1005{
1014 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1015 struct snd_soc_codec *codec = socdev->card->codec;
1016
1017 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1006 twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1018 1007
1019 return 0; 1008 return 0;
@@ -1023,68 +1012,9 @@ static int twl6040_resume(struct platform_device *pdev)
1023#define twl6040_resume NULL 1012#define twl6040_resume NULL
1024#endif 1013#endif
1025 1014
1026static struct snd_soc_codec *twl6040_codec; 1015static int twl6040_probe(struct snd_soc_codec *codec)
1027
1028static int twl6040_probe(struct platform_device *pdev)
1029{
1030 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1031 struct snd_soc_codec *codec;
1032 int ret = 0;
1033
1034 BUG_ON(!twl6040_codec);
1035
1036 codec = twl6040_codec;
1037 socdev->card->codec = codec;
1038
1039 /* register pcms */
1040 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1041 if (ret < 0) {
1042 dev_err(&pdev->dev, "failed to create pcms\n");
1043 return ret;
1044 }
1045
1046 snd_soc_add_controls(codec, twl6040_snd_controls,
1047 ARRAY_SIZE(twl6040_snd_controls));
1048 twl6040_add_widgets(codec);
1049
1050 if (ret < 0) {
1051 dev_err(&pdev->dev, "failed to register card\n");
1052 goto card_err;
1053 }
1054
1055 return ret;
1056
1057card_err:
1058 snd_soc_free_pcms(socdev);
1059 snd_soc_dapm_free(socdev);
1060 return ret;
1061}
1062
1063static int twl6040_remove(struct platform_device *pdev)
1064{
1065 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1066 struct snd_soc_codec *codec = socdev->card->codec;
1067
1068 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1069 snd_soc_free_pcms(socdev);
1070 snd_soc_dapm_free(socdev);
1071 kfree(codec);
1072
1073 return 0;
1074}
1075
1076struct snd_soc_codec_device soc_codec_dev_twl6040 = {
1077 .probe = twl6040_probe,
1078 .remove = twl6040_remove,
1079 .suspend = twl6040_suspend,
1080 .resume = twl6040_resume,
1081};
1082EXPORT_SYMBOL_GPL(soc_codec_dev_twl6040);
1083
1084static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1085{ 1016{
1086 struct twl4030_codec_data *twl_codec = pdev->dev.platform_data; 1017 struct twl4030_codec_data *twl_codec = codec->dev->platform_data;
1087 struct snd_soc_codec *codec;
1088 struct twl6040_data *priv; 1018 struct twl6040_data *priv;
1089 int audpwron, naudint; 1019 int audpwron, naudint;
1090 int ret = 0; 1020 int ret = 0;
@@ -1092,6 +1022,7 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1092 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL); 1022 priv = kzalloc(sizeof(struct twl6040_data), GFP_KERNEL);
1093 if (priv == NULL) 1023 if (priv == NULL)
1094 return -ENOMEM; 1024 return -ENOMEM;
1025 snd_soc_codec_set_drvdata(codec, priv);
1095 1026
1096 if (twl_codec) { 1027 if (twl_codec) {
1097 audpwron = twl_codec->audpwron_gpio; 1028 audpwron = twl_codec->audpwron_gpio;
@@ -1104,29 +1035,6 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1104 priv->audpwron = audpwron; 1035 priv->audpwron = audpwron;
1105 priv->naudint = naudint; 1036 priv->naudint = naudint;
1106 1037
1107 codec = &priv->codec;
1108 codec->dev = &pdev->dev;
1109 twl6040_dai.dev = &pdev->dev;
1110
1111 codec->name = "twl6040";
1112 codec->owner = THIS_MODULE;
1113 codec->read = twl6040_read_reg_cache;
1114 codec->write = twl6040_write;
1115 codec->set_bias_level = twl6040_set_bias_level;
1116 snd_soc_codec_set_drvdata(codec, priv);
1117 codec->dai = &twl6040_dai;
1118 codec->num_dai = 1;
1119 codec->reg_cache_size = ARRAY_SIZE(twl6040_reg);
1120 codec->reg_cache = kmemdup(twl6040_reg, sizeof(twl6040_reg),
1121 GFP_KERNEL);
1122 if (codec->reg_cache == NULL) {
1123 ret = -ENOMEM;
1124 goto cache_err;
1125 }
1126
1127 mutex_init(&codec->mutex);
1128 INIT_LIST_HEAD(&codec->dapm_widgets);
1129 INIT_LIST_HEAD(&codec->dapm_paths);
1130 init_completion(&priv->ready); 1038 init_completion(&priv->ready);
1131 1039
1132 if (gpio_is_valid(audpwron)) { 1040 if (gpio_is_valid(audpwron)) {
@@ -1169,23 +1077,12 @@ static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1169 if (ret) 1077 if (ret)
1170 goto irq_err; 1078 goto irq_err;
1171 1079
1172 ret = snd_soc_register_codec(codec); 1080 snd_soc_add_controls(codec, twl6040_snd_controls,
1173 if (ret) 1081 ARRAY_SIZE(twl6040_snd_controls));
1174 goto reg_err; 1082 twl6040_add_widgets(codec);
1175
1176 twl6040_codec = codec;
1177
1178 ret = snd_soc_register_dai(&twl6040_dai);
1179 if (ret)
1180 goto dai_err;
1181 1083
1182 return 0; 1084 return 0;
1183 1085
1184dai_err:
1185 snd_soc_unregister_codec(codec);
1186 twl6040_codec = NULL;
1187reg_err:
1188 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1189irq_err: 1086irq_err:
1190 if (naudint) 1087 if (naudint)
1191 free_irq(naudint, codec); 1088 free_irq(naudint, codec);
@@ -1193,36 +1090,57 @@ gpio2_err:
1193 if (gpio_is_valid(audpwron)) 1090 if (gpio_is_valid(audpwron))
1194 gpio_free(audpwron); 1091 gpio_free(audpwron);
1195gpio1_err: 1092gpio1_err:
1196 kfree(codec->reg_cache);
1197cache_err:
1198 kfree(priv); 1093 kfree(priv);
1199 return ret; 1094 return ret;
1200} 1095}
1201 1096
1202static int __devexit twl6040_codec_remove(struct platform_device *pdev) 1097static int twl6040_remove(struct snd_soc_codec *codec)
1203{ 1098{
1204 struct twl6040_data *priv = snd_soc_codec_get_drvdata(twl6040_codec); 1099 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1205 int audpwron = priv->audpwron; 1100 int audpwron = priv->audpwron;
1206 int naudint = priv->naudint; 1101 int naudint = priv->naudint;
1207 1102
1103 twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
1104
1208 if (gpio_is_valid(audpwron)) 1105 if (gpio_is_valid(audpwron))
1209 gpio_free(audpwron); 1106 gpio_free(audpwron);
1210 1107
1211 if (naudint) 1108 if (naudint)
1212 free_irq(naudint, twl6040_codec); 1109 free_irq(naudint, codec);
1213 1110
1214 snd_soc_unregister_dai(&twl6040_dai); 1111 kfree(priv);
1215 snd_soc_unregister_codec(twl6040_codec);
1216 1112
1217 kfree(twl6040_codec); 1113 return 0;
1218 twl6040_codec = NULL; 1114}
1219 1115
1116static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
1117 .probe = twl6040_probe,
1118 .remove = twl6040_remove,
1119 .suspend = twl6040_suspend,
1120 .resume = twl6040_resume,
1121 .read = twl6040_read_reg_cache,
1122 .write = twl6040_write,
1123 .set_bias_level = twl6040_set_bias_level,
1124 .reg_cache_size = ARRAY_SIZE(twl6040_reg),
1125 .reg_word_size = sizeof(u8),
1126 .reg_cache_default = twl6040_reg,
1127};
1128
1129static int __devinit twl6040_codec_probe(struct platform_device *pdev)
1130{
1131 return snd_soc_register_codec(&pdev->dev,
1132 &soc_codec_dev_twl6040, &twl6040_dai, 1);
1133}
1134
1135static int __devexit twl6040_codec_remove(struct platform_device *pdev)
1136{
1137 snd_soc_unregister_codec(&pdev->dev);
1220 return 0; 1138 return 0;
1221} 1139}
1222 1140
1223static struct platform_driver twl6040_codec_driver = { 1141static struct platform_driver twl6040_codec_driver = {
1224 .driver = { 1142 .driver = {
1225 .name = "twl6040_codec", 1143 .name = "twl6040-codec",
1226 .owner = THIS_MODULE, 1144 .owner = THIS_MODULE,
1227 }, 1145 },
1228 .probe = twl6040_codec_probe, 1146 .probe = twl6040_codec_probe,
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index c472070a1da2..f7c77fa58a3c 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -135,7 +135,4 @@
135#define TWL6040_HPPLL_ID 1 135#define TWL6040_HPPLL_ID 1
136#define TWL6040_LPPLL_ID 2 136#define TWL6040_LPPLL_ID 2
137 137
138extern struct snd_soc_dai twl6040_dai;
139extern struct snd_soc_codec_device soc_codec_dev_twl6040;
140
141#endif /* End of __TWL6040_H__ */ 138#endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index f3b4c1d6a82d..7540a509a6f5 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -161,8 +161,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream,
161 struct snd_soc_dai *dai) 161 struct snd_soc_dai *dai)
162{ 162{
163 struct snd_soc_pcm_runtime *rtd = substream->private_data; 163 struct snd_soc_pcm_runtime *rtd = substream->private_data;
164 struct snd_soc_device *socdev = rtd->socdev; 164 struct snd_soc_codec *codec =rtd->codec;
165 struct snd_soc_codec *codec = socdev->card->codec;
166 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); 165 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
167 struct snd_pcm_runtime *master_runtime; 166 struct snd_pcm_runtime *master_runtime;
168 167
@@ -194,8 +193,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream,
194 struct snd_soc_dai *dai) 193 struct snd_soc_dai *dai)
195{ 194{
196 struct snd_soc_pcm_runtime *rtd = substream->private_data; 195 struct snd_soc_pcm_runtime *rtd = substream->private_data;
197 struct snd_soc_device *socdev = rtd->socdev; 196 struct snd_soc_codec *codec = rtd->codec;
198 struct snd_soc_codec *codec = socdev->card->codec;
199 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); 197 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
200 198
201 if (uda134x->master_substream == substream) 199 if (uda134x->master_substream == substream)
@@ -209,8 +207,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
209 struct snd_soc_dai *dai) 207 struct snd_soc_dai *dai)
210{ 208{
211 struct snd_soc_pcm_runtime *rtd = substream->private_data; 209 struct snd_soc_pcm_runtime *rtd = substream->private_data;
212 struct snd_soc_device *socdev = rtd->socdev; 210 struct snd_soc_codec *codec = rtd->codec;
213 struct snd_soc_codec *codec = socdev->card->codec;
214 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); 211 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
215 u8 hw_params; 212 u8 hw_params;
216 213
@@ -364,7 +361,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
364 pd->power(1); 361 pd->power(1);
365 /* Sync reg_cache with the hardware */ 362 /* Sync reg_cache with the hardware */
366 for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) 363 for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
367 codec->write(codec, i, *cache++); 364 codec->driver->write(codec, i, *cache++);
368 } 365 }
369 break; 366 break;
370 case SND_SOC_BIAS_STANDBY: 367 case SND_SOC_BIAS_STANDBY:
@@ -465,8 +462,8 @@ static struct snd_soc_dai_ops uda134x_dai_ops = {
465 .set_fmt = uda134x_set_dai_fmt, 462 .set_fmt = uda134x_set_dai_fmt,
466}; 463};
467 464
468struct snd_soc_dai uda134x_dai = { 465static struct snd_soc_dai_driver uda134x_dai = {
469 .name = "UDA134X", 466 .name = "uda134x-hifi",
470 /* playback capabilities */ 467 /* playback capabilities */
471 .playback = { 468 .playback = {
472 .stream_name = "Playback", 469 .stream_name = "Playback",
@@ -486,27 +483,21 @@ struct snd_soc_dai uda134x_dai = {
486 /* pcm operations */ 483 /* pcm operations */
487 .ops = &uda134x_dai_ops, 484 .ops = &uda134x_dai_ops,
488}; 485};
489EXPORT_SYMBOL(uda134x_dai);
490 486
491 487static int uda134x_soc_probe(struct snd_soc_codec *codec)
492static int uda134x_soc_probe(struct platform_device *pdev)
493{ 488{
494 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
495 struct snd_soc_codec *codec;
496 struct uda134x_priv *uda134x; 489 struct uda134x_priv *uda134x;
497 void *codec_setup_data = socdev->codec_data; 490 struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev);
498 int ret = -ENOMEM; 491 int ret;
499 struct uda134x_platform_data *pd;
500 492
501 printk(KERN_INFO "UDA134X SoC Audio Codec\n"); 493 printk(KERN_INFO "UDA134X SoC Audio Codec\n");
502 494
503 if (!codec_setup_data) { 495 if (!pd) {
504 printk(KERN_ERR "UDA134X SoC codec: " 496 printk(KERN_ERR "UDA134X SoC codec: "
505 "missing L3 bitbang function\n"); 497 "missing L3 bitbang function\n");
506 return -ENODEV; 498 return -ENODEV;
507 } 499 }
508 500
509 pd = codec_setup_data;
510 switch (pd->model) { 501 switch (pd->model) {
511 case UDA134X_UDA1340: 502 case UDA134X_UDA1340:
512 case UDA134X_UDA1341: 503 case UDA134X_UDA1341:
@@ -520,58 +511,22 @@ static int uda134x_soc_probe(struct platform_device *pdev)
520 return -EINVAL; 511 return -EINVAL;
521 } 512 }
522 513
523 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
524 if (socdev->card->codec == NULL)
525 return ret;
526
527 codec = socdev->card->codec;
528
529 uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); 514 uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
530 if (uda134x == NULL) 515 if (uda134x == NULL)
531 goto priv_err; 516 return -ENOMEM;
532 snd_soc_codec_set_drvdata(codec, uda134x); 517 snd_soc_codec_set_drvdata(codec, uda134x);
533 518
534 codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg), 519 codec->control_data = pd;
535 GFP_KERNEL);
536 if (codec->reg_cache == NULL)
537 goto reg_err;
538
539 mutex_init(&codec->mutex);
540
541 codec->reg_cache_size = sizeof(uda134x_reg);
542 codec->reg_cache_step = 1;
543
544 codec->name = "UDA134X";
545 codec->owner = THIS_MODULE;
546 codec->dai = &uda134x_dai;
547 codec->num_dai = 1;
548 codec->read = uda134x_read_reg_cache;
549 codec->write = uda134x_write;
550
551 INIT_LIST_HEAD(&codec->dapm_widgets);
552 INIT_LIST_HEAD(&codec->dapm_paths);
553
554 codec->control_data = codec_setup_data;
555 520
556 if (pd->power) 521 if (pd->power)
557 pd->power(1); 522 pd->power(1);
558 523
559 uda134x_reset(codec); 524 uda134x_reset(codec);
560 525
561 if (pd->is_powered_on_standby) { 526 if (pd->is_powered_on_standby)
562 codec->set_bias_level = NULL;
563 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); 527 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
564 } else { 528 else
565 codec->set_bias_level = uda134x_set_bias_level;
566 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 529 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
567 }
568
569 /* register pcms */
570 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
571 if (ret < 0) {
572 printk(KERN_ERR "UDA134X: failed to register pcms\n");
573 goto pcm_err;
574 }
575 530
576 switch (pd->model) { 531 switch (pd->model) {
577 case UDA134X_UDA1340: 532 case UDA134X_UDA1340:
@@ -590,61 +545,42 @@ static int uda134x_soc_probe(struct platform_device *pdev)
590 default: 545 default:
591 printk(KERN_ERR "%s unknown codec type: %d", 546 printk(KERN_ERR "%s unknown codec type: %d",
592 __func__, pd->model); 547 __func__, pd->model);
593 return -EINVAL; 548 kfree(uda134x);
549 return -EINVAL;
594 } 550 }
595 551
596 if (ret < 0) { 552 if (ret < 0) {
597 printk(KERN_ERR "UDA134X: failed to register controls\n"); 553 printk(KERN_ERR "UDA134X: failed to register controls\n");
598 goto pcm_err; 554 kfree(uda134x);
555 return ret;
599 } 556 }
600 557
601 return 0; 558 return 0;
602
603pcm_err:
604 kfree(codec->reg_cache);
605reg_err:
606 kfree(snd_soc_codec_get_drvdata(codec));
607priv_err:
608 kfree(codec);
609 return ret;
610} 559}
611 560
612/* power down chip */ 561/* power down chip */
613static int uda134x_soc_remove(struct platform_device *pdev) 562static int uda134x_soc_remove(struct snd_soc_codec *codec)
614{ 563{
615 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 564 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
616 struct snd_soc_codec *codec = socdev->card->codec;
617 565
618 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 566 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
619 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); 567 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
620 568
621 snd_soc_free_pcms(socdev); 569 kfree(uda134x);
622 snd_soc_dapm_free(socdev);
623
624 kfree(snd_soc_codec_get_drvdata(codec));
625 kfree(codec->reg_cache);
626 kfree(codec);
627
628 return 0; 570 return 0;
629} 571}
630 572
631#if defined(CONFIG_PM) 573#if defined(CONFIG_PM)
632static int uda134x_soc_suspend(struct platform_device *pdev, 574static int uda134x_soc_suspend(struct snd_soc_codec *codec,
633 pm_message_t state) 575 pm_message_t state)
634{ 576{
635 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
636 struct snd_soc_codec *codec = socdev->card->codec;
637
638 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 577 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
639 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); 578 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
640 return 0; 579 return 0;
641} 580}
642 581
643static int uda134x_soc_resume(struct platform_device *pdev) 582static int uda134x_soc_resume(struct snd_soc_codec *codec)
644{ 583{
645 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
646 struct snd_soc_codec *codec = socdev->card->codec;
647
648 uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); 584 uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
649 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); 585 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
650 return 0; 586 return 0;
@@ -654,25 +590,53 @@ static int uda134x_soc_resume(struct platform_device *pdev)
654#define uda134x_soc_resume NULL 590#define uda134x_soc_resume NULL
655#endif /* CONFIG_PM */ 591#endif /* CONFIG_PM */
656 592
657struct snd_soc_codec_device soc_codec_dev_uda134x = { 593static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
658 .probe = uda134x_soc_probe, 594 .probe = uda134x_soc_probe,
659 .remove = uda134x_soc_remove, 595 .remove = uda134x_soc_remove,
660 .suspend = uda134x_soc_suspend, 596 .suspend = uda134x_soc_suspend,
661 .resume = uda134x_soc_resume, 597 .resume = uda134x_soc_resume,
598 .reg_cache_size = sizeof(uda134x_reg),
599 .reg_word_size = sizeof(u8),
600 .reg_cache_step = 1,
601 .read = uda134x_read_reg_cache,
602 .write = uda134x_write,
603#ifdef POWER_OFF_ON_STANDBY
604 .set_bias_level = uda134x_set_bias_level,
605#endif
606};
607
608static int __devinit uda134x_codec_probe(struct platform_device *pdev)
609{
610 return snd_soc_register_codec(&pdev->dev,
611 &soc_codec_dev_uda134x, &uda134x_dai, 1);
612}
613
614static int __devexit uda134x_codec_remove(struct platform_device *pdev)
615{
616 snd_soc_unregister_codec(&pdev->dev);
617 return 0;
618}
619
620static struct platform_driver uda134x_codec_driver = {
621 .driver = {
622 .name = "uda134x-codec",
623 .owner = THIS_MODULE,
624 },
625 .probe = uda134x_codec_probe,
626 .remove = __devexit_p(uda134x_codec_remove),
662}; 627};
663EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
664 628
665static int __init uda134x_init(void) 629static int __init uda134x_codec_init(void)
666{ 630{
667 return snd_soc_register_dai(&uda134x_dai); 631 return platform_driver_register(&uda134x_codec_driver);
668} 632}
669module_init(uda134x_init); 633module_init(uda134x_codec_init);
670 634
671static void __exit uda134x_exit(void) 635static void __exit uda134x_codec_exit(void)
672{ 636{
673 snd_soc_unregister_dai(&uda134x_dai); 637 platform_driver_unregister(&uda134x_codec_driver);
674} 638}
675module_exit(uda134x_exit); 639module_exit(uda134x_codec_exit);
676 640
677MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); 641MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
678MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); 642MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h
index 205f03b3eaf8..9faae06972b3 100644
--- a/sound/soc/codecs/uda134x.h
+++ b/sound/soc/codecs/uda134x.h
@@ -31,7 +31,4 @@
31#define STATUS0_DAIFMT_MASK (~(7<<1)) 31#define STATUS0_DAIFMT_MASK (~(7<<1))
32#define STATUS0_SYSCLK_MASK (~(3<<4)) 32#define STATUS0_SYSCLK_MASK (~(3<<4))
33 33
34extern struct snd_soc_dai uda134x_dai;
35extern struct snd_soc_codec_device soc_codec_dev_uda134x;
36
37#endif 34#endif
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 2f925a27dcde..0c6c725736c6 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -33,14 +33,13 @@
33 33
34#include "uda1380.h" 34#include "uda1380.h"
35 35
36static struct snd_soc_codec *uda1380_codec;
37
38/* codec private data */ 36/* codec private data */
39struct uda1380_priv { 37struct uda1380_priv {
40 struct snd_soc_codec codec; 38 struct snd_soc_codec *codec;
41 u16 reg_cache[UDA1380_CACHEREGNUM]; 39 u16 reg_cache[UDA1380_CACHEREGNUM];
42 unsigned int dac_clk; 40 unsigned int dac_clk;
43 struct work_struct work; 41 struct work_struct work;
42 void *control_data;
44}; 43};
45 44
46/* 45/*
@@ -131,10 +130,51 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
131 return -EIO; 130 return -EIO;
132} 131}
133 132
134#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0) 133static void uda1380_sync_cache(struct snd_soc_codec *codec)
134{
135 int reg;
136 u8 data[3];
137 u16 *cache = codec->reg_cache;
138
139 /* Sync reg_cache with the hardware */
140 for (reg = 0; reg < UDA1380_MVOL; reg++) {
141 data[0] = reg;
142 data[1] = (cache[reg] & 0xff00) >> 8;
143 data[2] = cache[reg] & 0x00ff;
144 if (codec->hw_write(codec->control_data, data, 3) != 3)
145 dev_err(codec->dev, "%s: write to reg 0x%x failed\n",
146 __func__, reg);
147 }
148}
149
150static int uda1380_reset(struct snd_soc_codec *codec)
151{
152 struct uda1380_platform_data *pdata = codec->dev->platform_data;
153
154 if (gpio_is_valid(pdata->gpio_reset)) {
155 gpio_set_value(pdata->gpio_reset, 1);
156 mdelay(1);
157 gpio_set_value(pdata->gpio_reset, 0);
158 } else {
159 u8 data[3];
160
161 data[0] = UDA1380_RESET;
162 data[1] = 0;
163 data[2] = 0;
164
165 if (codec->hw_write(codec->control_data, data, 3) != 3) {
166 dev_err(codec->dev, "%s: failed\n", __func__);
167 return -EIO;
168 }
169 }
170
171 return 0;
172}
135 173
136static void uda1380_flush_work(struct work_struct *work) 174static void uda1380_flush_work(struct work_struct *work)
137{ 175{
176 struct uda1380_priv *uda1380 = container_of(work, struct uda1380_priv, work);
177 struct snd_soc_codec *uda1380_codec = uda1380->codec;
138 int bit, reg; 178 int bit, reg;
139 179
140 for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) { 180 for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
@@ -145,6 +185,7 @@ static void uda1380_flush_work(struct work_struct *work)
145 uda1380_read_reg_cache(uda1380_codec, reg)); 185 uda1380_read_reg_cache(uda1380_codec, reg));
146 clear_bit(bit, &uda1380_cache_dirty); 186 clear_bit(bit, &uda1380_cache_dirty);
147 } 187 }
188
148} 189}
149 190
150/* declarations of ALSA reg_elem_REAL controls */ 191/* declarations of ALSA reg_elem_REAL controls */
@@ -474,8 +515,7 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
474 struct snd_soc_dai *dai) 515 struct snd_soc_dai *dai)
475{ 516{
476 struct snd_soc_pcm_runtime *rtd = substream->private_data; 517 struct snd_soc_pcm_runtime *rtd = substream->private_data;
477 struct snd_soc_device *socdev = rtd->socdev; 518 struct snd_soc_codec *codec = rtd->codec;
478 struct snd_soc_codec *codec = socdev->card->codec;
479 struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec); 519 struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
480 int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); 520 int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
481 521
@@ -501,8 +541,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
501 struct snd_soc_dai *dai) 541 struct snd_soc_dai *dai)
502{ 542{
503 struct snd_soc_pcm_runtime *rtd = substream->private_data; 543 struct snd_soc_pcm_runtime *rtd = substream->private_data;
504 struct snd_soc_device *socdev = rtd->socdev; 544 struct snd_soc_codec *codec = rtd->codec;
505 struct snd_soc_codec *codec = socdev->card->codec;
506 u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); 545 u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
507 546
508 /* set WSPLL power and divider if running from this clock */ 547 /* set WSPLL power and divider if running from this clock */
@@ -540,8 +579,7 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
540 struct snd_soc_dai *dai) 579 struct snd_soc_dai *dai)
541{ 580{
542 struct snd_soc_pcm_runtime *rtd = substream->private_data; 581 struct snd_soc_pcm_runtime *rtd = substream->private_data;
543 struct snd_soc_device *socdev = rtd->socdev; 582 struct snd_soc_codec *codec = rtd->codec;
544 struct snd_soc_codec *codec = socdev->card->codec;
545 u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); 583 u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
546 584
547 /* shut down WSPLL power if running from this clock */ 585 /* shut down WSPLL power if running from this clock */
@@ -562,18 +600,41 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
562 enum snd_soc_bias_level level) 600 enum snd_soc_bias_level level)
563{ 601{
564 int pm = uda1380_read_reg_cache(codec, UDA1380_PM); 602 int pm = uda1380_read_reg_cache(codec, UDA1380_PM);
603 int reg;
604 struct uda1380_platform_data *pdata = codec->dev->platform_data;
605
606 if (codec->bias_level == level)
607 return 0;
565 608
566 switch (level) { 609 switch (level) {
567 case SND_SOC_BIAS_ON: 610 case SND_SOC_BIAS_ON:
568 case SND_SOC_BIAS_PREPARE: 611 case SND_SOC_BIAS_PREPARE:
612 /* ADC, DAC on */
569 uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm); 613 uda1380_write(codec, UDA1380_PM, R02_PON_BIAS | pm);
570 break; 614 break;
571 case SND_SOC_BIAS_STANDBY: 615 case SND_SOC_BIAS_STANDBY:
572 uda1380_write(codec, UDA1380_PM, R02_PON_BIAS); 616 if (codec->bias_level == SND_SOC_BIAS_OFF) {
573 break; 617 if (gpio_is_valid(pdata->gpio_power)) {
574 case SND_SOC_BIAS_OFF: 618 gpio_set_value(pdata->gpio_power, 1);
619 mdelay(1);
620 uda1380_reset(codec);
621 }
622
623 uda1380_sync_cache(codec);
624 }
575 uda1380_write(codec, UDA1380_PM, 0x0); 625 uda1380_write(codec, UDA1380_PM, 0x0);
576 break; 626 break;
627 case SND_SOC_BIAS_OFF:
628 if (!gpio_is_valid(pdata->gpio_power))
629 break;
630
631 gpio_set_value(pdata->gpio_power, 0);
632
633 /* Mark mixer regs cache dirty to sync them with
634 * codec regs on power on.
635 */
636 for (reg = UDA1380_MVOL; reg < UDA1380_CACHEREGNUM; reg++)
637 set_bit(reg - 0x10, &uda1380_cache_dirty);
577 } 638 }
578 codec->bias_level = level; 639 codec->bias_level = level;
579 return 0; 640 return 0;
@@ -604,9 +665,9 @@ static struct snd_soc_dai_ops uda1380_dai_ops_capture = {
604 .set_fmt = uda1380_set_dai_fmt_capture, 665 .set_fmt = uda1380_set_dai_fmt_capture,
605}; 666};
606 667
607struct snd_soc_dai uda1380_dai[] = { 668static struct snd_soc_dai_driver uda1380_dai[] = {
608{ 669{
609 .name = "UDA1380", 670 .name = "uda1380-hifi",
610 .playback = { 671 .playback = {
611 .stream_name = "Playback", 672 .stream_name = "Playback",
612 .channels_min = 1, 673 .channels_min = 1,
@@ -622,7 +683,7 @@ struct snd_soc_dai uda1380_dai[] = {
622 .ops = &uda1380_dai_ops, 683 .ops = &uda1380_dai_ops,
623}, 684},
624{ /* playback only - dual interface */ 685{ /* playback only - dual interface */
625 .name = "UDA1380", 686 .name = "uda1380-hifi-playback",
626 .playback = { 687 .playback = {
627 .stream_name = "Playback", 688 .stream_name = "Playback",
628 .channels_min = 1, 689 .channels_min = 1,
@@ -633,7 +694,7 @@ struct snd_soc_dai uda1380_dai[] = {
633 .ops = &uda1380_dai_ops_playback, 694 .ops = &uda1380_dai_ops_playback,
634}, 695},
635{ /* capture only - dual interface*/ 696{ /* capture only - dual interface*/
636 .name = "UDA1380", 697 .name = "uda1380-hifi-capture",
637 .capture = { 698 .capture = {
638 .stream_name = "Capture", 699 .stream_name = "Capture",
639 .channels_min = 1, 700 .channels_min = 1,
@@ -644,67 +705,69 @@ struct snd_soc_dai uda1380_dai[] = {
644 .ops = &uda1380_dai_ops_capture, 705 .ops = &uda1380_dai_ops_capture,
645}, 706},
646}; 707};
647EXPORT_SYMBOL_GPL(uda1380_dai);
648 708
649static int uda1380_suspend(struct platform_device *pdev, pm_message_t state) 709static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state)
650{ 710{
651 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
652 struct snd_soc_codec *codec = socdev->card->codec;
653
654 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); 711 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
655 return 0; 712 return 0;
656} 713}
657 714
658static int uda1380_resume(struct platform_device *pdev) 715static int uda1380_resume(struct snd_soc_codec *codec)
659{ 716{
660 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
661 struct snd_soc_codec *codec = socdev->card->codec;
662 int i;
663 u8 data[2];
664 u16 *cache = codec->reg_cache;
665
666 /* Sync reg_cache with the hardware */
667 for (i = 0; i < ARRAY_SIZE(uda1380_reg); i++) {
668 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
669 data[1] = cache[i] & 0x00ff;
670 codec->hw_write(codec->control_data, data, 2);
671 }
672 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 717 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
673 return 0; 718 return 0;
674} 719}
675 720
676static int uda1380_probe(struct platform_device *pdev) 721static int uda1380_probe(struct snd_soc_codec *codec)
677{ 722{
678 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 723 struct uda1380_platform_data *pdata =codec->dev->platform_data;
679 struct snd_soc_codec *codec; 724 struct uda1380_priv *uda1380 = snd_soc_codec_get_drvdata(codec);
680 struct uda1380_platform_data *pdata; 725 int ret;
681 int ret = 0;
682 726
683 if (uda1380_codec == NULL) { 727 uda1380->codec = codec;
684 dev_err(&pdev->dev, "Codec device not registered\n"); 728
685 return -ENODEV; 729 codec->hw_write = (hw_write_t)i2c_master_send;
686 } 730 codec->control_data = uda1380->control_data;
731
732 if (!pdata)
733 return -EINVAL;
687 734
688 socdev->card->codec = uda1380_codec; 735 if (gpio_is_valid(pdata->gpio_reset)) {
689 codec = uda1380_codec; 736 ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
690 pdata = codec->dev->platform_data; 737 if (ret)
738 goto err_out;
739 ret = gpio_direction_output(pdata->gpio_reset, 0);
740 if (ret)
741 goto err_gpio_reset_conf;
742 }
691 743
692 /* register pcms */ 744 if (gpio_is_valid(pdata->gpio_power)) {
693 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 745 ret = gpio_request(pdata->gpio_power, "uda1380 power");
694 if (ret < 0) { 746 if (ret)
695 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 747 goto err_gpio;
696 goto pcm_err; 748 ret = gpio_direction_output(pdata->gpio_power, 0);
749 if (ret)
750 goto err_gpio_power_conf;
751 } else {
752 ret = uda1380_reset(codec);
753 if (ret) {
754 dev_err(codec->dev, "Failed to issue reset\n");
755 goto err_reset;
756 }
697 } 757 }
698 758
759 INIT_WORK(&uda1380->work, uda1380_flush_work);
760
699 /* power on device */ 761 /* power on device */
700 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 762 uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
701 /* set clock input */ 763 /* set clock input */
702 switch (pdata->dac_clk) { 764 switch (pdata->dac_clk) {
703 case UDA1380_DAC_CLK_SYSCLK: 765 case UDA1380_DAC_CLK_SYSCLK:
704 uda1380_write(codec, UDA1380_CLK, 0); 766 uda1380_write_reg_cache(codec, UDA1380_CLK, 0);
705 break; 767 break;
706 case UDA1380_DAC_CLK_WSPLL: 768 case UDA1380_DAC_CLK_WSPLL:
707 uda1380_write(codec, UDA1380_CLK, R00_DAC_CLK); 769 uda1380_write_reg_cache(codec, UDA1380_CLK,
770 R00_DAC_CLK);
708 break; 771 break;
709 } 772 }
710 773
@@ -712,167 +775,73 @@ static int uda1380_probe(struct platform_device *pdev)
712 ARRAY_SIZE(uda1380_snd_controls)); 775 ARRAY_SIZE(uda1380_snd_controls));
713 uda1380_add_widgets(codec); 776 uda1380_add_widgets(codec);
714 777
715 return ret;
716
717pcm_err:
718 return ret;
719}
720
721/* power down chip */
722static int uda1380_remove(struct platform_device *pdev)
723{
724 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
725 struct snd_soc_codec *codec = socdev->card->codec;
726
727 if (codec->control_data)
728 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
729
730 snd_soc_free_pcms(socdev);
731 snd_soc_dapm_free(socdev);
732
733 return 0; 778 return 0;
734}
735
736struct snd_soc_codec_device soc_codec_dev_uda1380 = {
737 .probe = uda1380_probe,
738 .remove = uda1380_remove,
739 .suspend = uda1380_suspend,
740 .resume = uda1380_resume,
741};
742EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
743
744static int uda1380_register(struct uda1380_priv *uda1380)
745{
746 int ret, i;
747 struct snd_soc_codec *codec = &uda1380->codec;
748 struct uda1380_platform_data *pdata = codec->dev->platform_data;
749
750 if (uda1380_codec) {
751 dev_err(codec->dev, "Another UDA1380 is registered\n");
752 return -EINVAL;
753 }
754
755 if (!pdata || !pdata->gpio_power || !pdata->gpio_reset)
756 return -EINVAL;
757
758 ret = gpio_request(pdata->gpio_power, "uda1380 power");
759 if (ret)
760 goto err_out;
761 ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
762 if (ret)
763 goto err_gpio;
764
765 gpio_direction_output(pdata->gpio_power, 1);
766
767 /* we may need to have the clock running here - pH5 */
768 gpio_direction_output(pdata->gpio_reset, 1);
769 udelay(5);
770 gpio_set_value(pdata->gpio_reset, 0);
771
772 mutex_init(&codec->mutex);
773 INIT_LIST_HEAD(&codec->dapm_widgets);
774 INIT_LIST_HEAD(&codec->dapm_paths);
775
776 snd_soc_codec_set_drvdata(codec, uda1380);
777 codec->name = "UDA1380";
778 codec->owner = THIS_MODULE;
779 codec->read = uda1380_read_reg_cache;
780 codec->write = uda1380_write;
781 codec->bias_level = SND_SOC_BIAS_OFF;
782 codec->set_bias_level = uda1380_set_bias_level;
783 codec->dai = uda1380_dai;
784 codec->num_dai = ARRAY_SIZE(uda1380_dai);
785 codec->reg_cache_size = ARRAY_SIZE(uda1380_reg);
786 codec->reg_cache = &uda1380->reg_cache;
787 codec->reg_cache_step = 1;
788
789 memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg));
790
791 ret = uda1380_reset(codec);
792 if (ret < 0) {
793 dev_err(codec->dev, "Failed to issue reset\n");
794 goto err_reset;
795 }
796
797 INIT_WORK(&uda1380->work, uda1380_flush_work);
798 779
799 for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++)
800 uda1380_dai[i].dev = codec->dev;
801
802 uda1380_codec = codec;
803
804 ret = snd_soc_register_codec(codec);
805 if (ret != 0) {
806 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
807 goto err_reset;
808 }
809
810 ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
811 if (ret != 0) {
812 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
813 goto err_dai;
814 }
815
816 return 0;
817
818err_dai:
819 snd_soc_unregister_codec(codec);
820err_reset: 780err_reset:
821 gpio_set_value(pdata->gpio_power, 0); 781err_gpio_power_conf:
822 gpio_free(pdata->gpio_reset); 782 if (gpio_is_valid(pdata->gpio_power))
783 gpio_free(pdata->gpio_power);
784
785err_gpio_reset_conf:
823err_gpio: 786err_gpio:
824 gpio_free(pdata->gpio_power); 787 if (gpio_is_valid(pdata->gpio_reset))
788 gpio_free(pdata->gpio_reset);
825err_out: 789err_out:
826 return ret; 790 return ret;
827} 791}
828 792
829static void uda1380_unregister(struct uda1380_priv *uda1380) 793/* power down chip */
794static int uda1380_remove(struct snd_soc_codec *codec)
830{ 795{
831 struct snd_soc_codec *codec = &uda1380->codec; 796 struct uda1380_platform_data *pdata =codec->dev->platform_data;
832 struct uda1380_platform_data *pdata = codec->dev->platform_data;
833 797
834 snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); 798 uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
835 snd_soc_unregister_codec(&uda1380->codec);
836 799
837 gpio_set_value(pdata->gpio_power, 0);
838 gpio_free(pdata->gpio_reset); 800 gpio_free(pdata->gpio_reset);
839 gpio_free(pdata->gpio_power); 801 gpio_free(pdata->gpio_power);
840 802
841 kfree(uda1380); 803 return 0;
842 uda1380_codec = NULL;
843} 804}
844 805
806static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
807 .probe = uda1380_probe,
808 .remove = uda1380_remove,
809 .suspend = uda1380_suspend,
810 .resume = uda1380_resume,
811 .read = uda1380_read_reg_cache,
812 .write = uda1380_write,
813 .set_bias_level = uda1380_set_bias_level,
814 .reg_cache_size = ARRAY_SIZE(uda1380_reg),
815 .reg_word_size = sizeof(u16),
816 .reg_cache_default = uda1380_reg,
817 .reg_cache_step = 1,
818};
819
845#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 820#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
846static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, 821static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
847 const struct i2c_device_id *id) 822 const struct i2c_device_id *id)
848{ 823{
849 struct uda1380_priv *uda1380; 824 struct uda1380_priv *uda1380;
850 struct snd_soc_codec *codec;
851 int ret; 825 int ret;
852 826
853 uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); 827 uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);
854 if (uda1380 == NULL) 828 if (uda1380 == NULL)
855 return -ENOMEM; 829 return -ENOMEM;
856 830
857 codec = &uda1380->codec;
858 codec->hw_write = (hw_write_t)i2c_master_send;
859
860 i2c_set_clientdata(i2c, uda1380); 831 i2c_set_clientdata(i2c, uda1380);
861 codec->control_data = i2c; 832 uda1380->control_data = i2c;
862 833
863 codec->dev = &i2c->dev; 834 ret = snd_soc_register_codec(&i2c->dev,
864 835 &soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai));
865 ret = uda1380_register(uda1380); 836 if (ret < 0)
866 if (ret != 0)
867 kfree(uda1380); 837 kfree(uda1380);
868
869 return ret; 838 return ret;
870} 839}
871 840
872static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) 841static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
873{ 842{
874 struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c); 843 snd_soc_unregister_codec(&i2c->dev);
875 uda1380_unregister(uda1380); 844 kfree(i2c_get_clientdata(i2c));
876 return 0; 845 return 0;
877} 846}
878 847
@@ -884,7 +853,7 @@ MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
884 853
885static struct i2c_driver uda1380_i2c_driver = { 854static struct i2c_driver uda1380_i2c_driver = {
886 .driver = { 855 .driver = {
887 .name = "UDA1380 I2C Codec", 856 .name = "uda1380-codec",
888 .owner = THIS_MODULE, 857 .owner = THIS_MODULE,
889 }, 858 },
890 .probe = uda1380_i2c_probe, 859 .probe = uda1380_i2c_probe,
diff --git a/sound/soc/codecs/uda1380.h b/sound/soc/codecs/uda1380.h
index 9cefa8a54770..942e3927c72b 100644
--- a/sound/soc/codecs/uda1380.h
+++ b/sound/soc/codecs/uda1380.h
@@ -76,7 +76,4 @@
76#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ 76#define UDA1380_DAI_PLAYBACK 1 /* playback DAI */
77#define UDA1380_DAI_CAPTURE 2 /* capture DAI */ 77#define UDA1380_DAI_CAPTURE 2 /* capture DAI */
78 78
79extern struct snd_soc_dai uda1380_dai[3];
80extern struct snd_soc_codec_device soc_codec_dev_uda1380;
81
82#endif /* _UDA1380_H */ 79#endif /* _UDA1380_H */
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
new file mode 100644
index 000000000000..0c47c788ccdf
--- /dev/null
+++ b/sound/soc/codecs/wl1273.c
@@ -0,0 +1,528 @@
1/*
2 * ALSA SoC WL1273 codec driver
3 *
4 * Author: Matti Aaltonen, <matti.j.aaltonen@nokia.com>
5 *
6 * Copyright: (C) 2010 Nokia Corporation
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/mfd/wl1273-core.h>
25#include <linux/slab.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/soc-dai.h>
29#include <sound/soc-dapm.h>
30#include <sound/initval.h>
31
32#include "wl1273.h"
33
34enum wl1273_mode { WL1273_MODE_BT, WL1273_MODE_FM_RX, WL1273_MODE_FM_TX };
35
36/* codec private data */
37struct wl1273_priv {
38 enum wl1273_mode mode;
39 struct wl1273_core *core;
40 unsigned int channels;
41};
42
43static int snd_wl1273_fm_set_i2s_mode(struct wl1273_core *core,
44 int rate, int width)
45{
46 struct device *dev = &core->i2c_dev->dev;
47 int r = 0;
48 u16 mode;
49
50 dev_dbg(dev, "rate: %d\n", rate);
51 dev_dbg(dev, "width: %d\n", width);
52
53 mutex_lock(&core->lock);
54
55 mode = core->i2s_mode & ~WL1273_IS2_WIDTH & ~WL1273_IS2_RATE;
56
57 switch (rate) {
58 case 48000:
59 mode |= WL1273_IS2_RATE_48K;
60 break;
61 case 44100:
62 mode |= WL1273_IS2_RATE_44_1K;
63 break;
64 case 32000:
65 mode |= WL1273_IS2_RATE_32K;
66 break;
67 case 22050:
68 mode |= WL1273_IS2_RATE_22_05K;
69 break;
70 case 16000:
71 mode |= WL1273_IS2_RATE_16K;
72 break;
73 case 12000:
74 mode |= WL1273_IS2_RATE_12K;
75 break;
76 case 11025:
77 mode |= WL1273_IS2_RATE_11_025;
78 break;
79 case 8000:
80 mode |= WL1273_IS2_RATE_8K;
81 break;
82 default:
83 dev_err(dev, "Sampling rate: %d not supported\n", rate);
84 r = -EINVAL;
85 goto out;
86 }
87
88 switch (width) {
89 case 16:
90 mode |= WL1273_IS2_WIDTH_32;
91 break;
92 case 20:
93 mode |= WL1273_IS2_WIDTH_40;
94 break;
95 case 24:
96 mode |= WL1273_IS2_WIDTH_48;
97 break;
98 case 25:
99 mode |= WL1273_IS2_WIDTH_50;
100 break;
101 case 30:
102 mode |= WL1273_IS2_WIDTH_60;
103 break;
104 case 32:
105 mode |= WL1273_IS2_WIDTH_64;
106 break;
107 case 40:
108 mode |= WL1273_IS2_WIDTH_80;
109 break;
110 case 48:
111 mode |= WL1273_IS2_WIDTH_96;
112 break;
113 case 64:
114 mode |= WL1273_IS2_WIDTH_128;
115 break;
116 default:
117 dev_err(dev, "Data width: %d not supported\n", width);
118 r = -EINVAL;
119 goto out;
120 }
121
122 dev_dbg(dev, "WL1273_I2S_DEF_MODE: 0x%04x\n", WL1273_I2S_DEF_MODE);
123 dev_dbg(dev, "core->i2s_mode: 0x%04x\n", core->i2s_mode);
124 dev_dbg(dev, "mode: 0x%04x\n", mode);
125
126 if (core->i2s_mode != mode) {
127 r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET, mode);
128 if (r)
129 goto out;
130
131 core->i2s_mode = mode;
132 r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
133 WL1273_AUDIO_ENABLE_I2S);
134 if (r)
135 goto out;
136 }
137out:
138 mutex_unlock(&core->lock);
139
140 return r;
141}
142
143static int snd_wl1273_fm_set_channel_number(struct wl1273_core *core,
144 int channel_number)
145{
146 struct i2c_client *client = core->i2c_dev;
147 struct device *dev = &client->dev;
148 int r = 0;
149
150 dev_dbg(dev, "%s\n", __func__);
151
152 mutex_lock(&core->lock);
153
154 if (core->channel_number == channel_number)
155 goto out;
156
157 if (channel_number == 1 && core->mode == WL1273_MODE_RX)
158 r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
159 WL1273_RX_MONO);
160 else if (channel_number == 1 && core->mode == WL1273_MODE_TX)
161 r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
162 WL1273_TX_MONO);
163 else if (channel_number == 2 && core->mode == WL1273_MODE_RX)
164 r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
165 WL1273_RX_STEREO);
166 else if (channel_number == 2 && core->mode == WL1273_MODE_TX)
167 r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
168 WL1273_TX_STEREO);
169 else
170 r = -EINVAL;
171out:
172 mutex_unlock(&core->lock);
173
174 return r;
175}
176
177static int snd_wl1273_get_audio_route(struct snd_kcontrol *kcontrol,
178 struct snd_ctl_elem_value *ucontrol)
179{
180 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
181 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
182
183 ucontrol->value.integer.value[0] = wl1273->mode;
184
185 return 0;
186}
187
188static const char *wl1273_audio_route[] = { "Bt", "FmRx", "FmTx" };
189
190static int snd_wl1273_set_audio_route(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_value *ucontrol)
192{
193 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
194 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
195
196 if (wl1273->mode == ucontrol->value.integer.value[0])
197 return 0;
198
199 /* Do not allow changes while stream is running */
200 if (codec->active)
201 return -EPERM;
202
203 if (ucontrol->value.integer.value[0] < 0 ||
204 ucontrol->value.integer.value[0] >= ARRAY_SIZE(wl1273_audio_route))
205 return -EINVAL;
206
207 wl1273->mode = ucontrol->value.integer.value[0];
208
209 return 1;
210}
211
212static const struct soc_enum wl1273_enum =
213 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_route), wl1273_audio_route);
214
215static int snd_wl1273_fm_audio_get(struct snd_kcontrol *kcontrol,
216 struct snd_ctl_elem_value *ucontrol)
217{
218 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
219 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
220
221 dev_dbg(codec->dev, "%s: enter.\n", __func__);
222
223 ucontrol->value.integer.value[0] = wl1273->core->audio_mode;
224
225 return 0;
226}
227
228static int snd_wl1273_fm_audio_put(struct snd_kcontrol *kcontrol,
229 struct snd_ctl_elem_value *ucontrol)
230{
231 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
232 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
233 int val, r = 0;
234
235 dev_dbg(codec->dev, "%s: enter.\n", __func__);
236
237 val = ucontrol->value.integer.value[0];
238 if (wl1273->core->audio_mode == val)
239 return 0;
240
241 r = wl1273_fm_set_audio(wl1273->core, val);
242 if (r < 0)
243 return r;
244
245 return 1;
246}
247
248static const char *wl1273_audio_strings[] = { "Digital", "Analog" };
249
250static const struct soc_enum wl1273_audio_enum =
251 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(wl1273_audio_strings),
252 wl1273_audio_strings);
253
254static int snd_wl1273_fm_volume_get(struct snd_kcontrol *kcontrol,
255 struct snd_ctl_elem_value *ucontrol)
256{
257 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
258 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
259
260 dev_dbg(codec->dev, "%s: enter.\n", __func__);
261
262 ucontrol->value.integer.value[0] = wl1273->core->volume;
263
264 return 0;
265}
266
267static int snd_wl1273_fm_volume_put(struct snd_kcontrol *kcontrol,
268 struct snd_ctl_elem_value *ucontrol)
269{
270 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
271 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
272 int r;
273
274 dev_dbg(codec->dev, "%s: enter.\n", __func__);
275
276 r = wl1273_fm_set_volume(wl1273->core,
277 ucontrol->value.integer.value[0]);
278 if (r)
279 return r;
280
281 return 1;
282}
283
284static const struct snd_kcontrol_new wl1273_controls[] = {
285 SOC_ENUM_EXT("Codec Mode", wl1273_enum,
286 snd_wl1273_get_audio_route, snd_wl1273_set_audio_route),
287 SOC_ENUM_EXT("Audio Switch", wl1273_audio_enum,
288 snd_wl1273_fm_audio_get, snd_wl1273_fm_audio_put),
289 SOC_SINGLE_EXT("Volume", 0, 0, WL1273_MAX_VOLUME, 0,
290 snd_wl1273_fm_volume_get, snd_wl1273_fm_volume_put),
291};
292
293static int wl1273_startup(struct snd_pcm_substream *substream,
294 struct snd_soc_dai *dai)
295{
296 struct snd_soc_pcm_runtime *rtd = substream->private_data;
297 struct snd_soc_codec *codec = rtd->codec;
298 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
299
300 switch (wl1273->mode) {
301 case WL1273_MODE_BT:
302 snd_pcm_hw_constraint_minmax(substream->runtime,
303 SNDRV_PCM_HW_PARAM_RATE,
304 8000, 8000);
305 snd_pcm_hw_constraint_minmax(substream->runtime,
306 SNDRV_PCM_HW_PARAM_CHANNELS, 1, 1);
307 break;
308 case WL1273_MODE_FM_RX:
309 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
310 pr_err("Cannot play in RX mode.\n");
311 return -EINVAL;
312 }
313 break;
314 case WL1273_MODE_FM_TX:
315 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
316 pr_err("Cannot capture in TX mode.\n");
317 return -EINVAL;
318 }
319 break;
320 default:
321 return -EINVAL;
322 break;
323 }
324
325 return 0;
326}
327
328static int wl1273_hw_params(struct snd_pcm_substream *substream,
329 struct snd_pcm_hw_params *params,
330 struct snd_soc_dai *dai)
331{
332 struct snd_soc_pcm_runtime *rtd = substream->private_data;
333 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(rtd->codec);
334 struct wl1273_core *core = wl1273->core;
335 unsigned int rate, width, r;
336
337 if (params_format(params) != SNDRV_PCM_FORMAT_S16_LE) {
338 pr_err("Only SNDRV_PCM_FORMAT_S16_LE supported.\n");
339 return -EINVAL;
340 }
341
342 rate = params_rate(params);
343 width = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
344
345 if (wl1273->mode == WL1273_MODE_BT) {
346 if (rate != 8000) {
347 pr_err("Rate %d not supported.\n", params_rate(params));
348 return -EINVAL;
349 }
350
351 if (params_channels(params) != 1) {
352 pr_err("Only mono supported.\n");
353 return -EINVAL;
354 }
355
356 return 0;
357 }
358
359 if (wl1273->mode == WL1273_MODE_FM_TX &&
360 substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
361 pr_err("Only playback supported with TX.\n");
362 return -EINVAL;
363 }
364
365 if (wl1273->mode == WL1273_MODE_FM_RX &&
366 substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
367 pr_err("Only capture supported with RX.\n");
368 return -EINVAL;
369 }
370
371 if (wl1273->mode != WL1273_MODE_FM_RX &&
372 wl1273->mode != WL1273_MODE_FM_TX) {
373 pr_err("Unexpected mode: %d.\n", wl1273->mode);
374 return -EINVAL;
375 }
376
377 r = snd_wl1273_fm_set_i2s_mode(core, rate, width);
378 if (r)
379 return r;
380
381 wl1273->channels = params_channels(params);
382 r = snd_wl1273_fm_set_channel_number(core, wl1273->channels);
383 if (r)
384 return r;
385
386 return 0;
387}
388
389static struct snd_soc_dai_ops wl1273_dai_ops = {
390 .startup = wl1273_startup,
391 .hw_params = wl1273_hw_params,
392};
393
394static struct snd_soc_dai_driver wl1273_dai = {
395 .name = "wl1273-fm",
396 .playback = {
397 .stream_name = "Playback",
398 .channels_min = 1,
399 .channels_max = 2,
400 .rates = SNDRV_PCM_RATE_8000_48000,
401 .formats = SNDRV_PCM_FMTBIT_S16_LE},
402 .capture = {
403 .stream_name = "Capture",
404 .channels_min = 1,
405 .channels_max = 2,
406 .rates = SNDRV_PCM_RATE_8000_48000,
407 .formats = SNDRV_PCM_FMTBIT_S16_LE},
408 .ops = &wl1273_dai_ops,
409};
410
411/* Audio interface format for the soc_card driver */
412int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt)
413{
414 struct wl1273_priv *wl1273;
415
416 if (codec == NULL || fmt == NULL)
417 return -EINVAL;
418
419 wl1273 = snd_soc_codec_get_drvdata(codec);
420
421 switch (wl1273->mode) {
422 case WL1273_MODE_FM_RX:
423 case WL1273_MODE_FM_TX:
424 *fmt = SND_SOC_DAIFMT_I2S |
425 SND_SOC_DAIFMT_NB_NF |
426 SND_SOC_DAIFMT_CBM_CFM;
427
428 break;
429 case WL1273_MODE_BT:
430 *fmt = SND_SOC_DAIFMT_DSP_A |
431 SND_SOC_DAIFMT_IB_NF |
432 SND_SOC_DAIFMT_CBM_CFM;
433
434 break;
435 default:
436 return -EINVAL;
437 }
438
439 return 0;
440}
441EXPORT_SYMBOL_GPL(wl1273_get_format);
442
443static int wl1273_probe(struct snd_soc_codec *codec)
444{
445 struct wl1273_core **core = codec->dev->platform_data;
446 struct wl1273_priv *wl1273;
447 int r;
448
449 dev_dbg(codec->dev, "%s.\n", __func__);
450
451 if (!core) {
452 dev_err(codec->dev, "Platform data is missing.\n");
453 return -EINVAL;
454 }
455
456 wl1273 = kzalloc(sizeof(struct wl1273_priv), GFP_KERNEL);
457 if (wl1273 == NULL) {
458 dev_err(codec->dev, "Cannot allocate memory.\n");
459 return -ENOMEM;
460 }
461
462 wl1273->mode = WL1273_MODE_BT;
463 wl1273->core = *core;
464
465 snd_soc_codec_set_drvdata(codec, wl1273);
466 mutex_init(&codec->mutex);
467
468 r = snd_soc_add_controls(codec, wl1273_controls,
469 ARRAY_SIZE(wl1273_controls));
470 if (r)
471 kfree(wl1273);
472
473 return r;
474}
475
476static int wl1273_remove(struct snd_soc_codec *codec)
477{
478 struct wl1273_priv *wl1273 = snd_soc_codec_get_drvdata(codec);
479
480 dev_dbg(codec->dev, "%s\n", __func__);
481 kfree(wl1273);
482
483 return 0;
484}
485
486static struct snd_soc_codec_driver soc_codec_dev_wl1273 = {
487 .probe = wl1273_probe,
488 .remove = wl1273_remove,
489};
490
491static int __devinit wl1273_platform_probe(struct platform_device *pdev)
492{
493 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wl1273,
494 &wl1273_dai, 1);
495}
496
497static int __devexit wl1273_platform_remove(struct platform_device *pdev)
498{
499 snd_soc_unregister_codec(&pdev->dev);
500 return 0;
501}
502
503MODULE_ALIAS("platform:wl1273-codec");
504
505static struct platform_driver wl1273_platform_driver = {
506 .driver = {
507 .name = "wl1273-codec",
508 .owner = THIS_MODULE,
509 },
510 .probe = wl1273_platform_probe,
511 .remove = __devexit_p(wl1273_platform_remove),
512};
513
514static int __init wl1273_init(void)
515{
516 return platform_driver_register(&wl1273_platform_driver);
517}
518module_init(wl1273_init);
519
520static void __exit wl1273_exit(void)
521{
522 platform_driver_unregister(&wl1273_platform_driver);
523}
524module_exit(wl1273_exit);
525
526MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
527MODULE_DESCRIPTION("ASoC WL1273 codec driver");
528MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wl1273.h b/sound/soc/codecs/wl1273.h
new file mode 100644
index 000000000000..14ed027fdcfc
--- /dev/null
+++ b/sound/soc/codecs/wl1273.h
@@ -0,0 +1,101 @@
1/*
2 * sound/soc/codec/wl1273.h
3 *
4 * ALSA SoC WL1273 codec driver
5 *
6 * Copyright (C) Nokia Corporation
7 * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __WL1273_CODEC_H__
26#define __WL1273_CODEC_H__
27
28/* I2S protocol, left channel first, data width 16 bits */
29#define WL1273_PCM_DEF_MODE 0x00
30
31/* Rx */
32#define WL1273_AUDIO_ENABLE_I2S (1 << 0)
33#define WL1273_AUDIO_ENABLE_ANALOG (1 << 1)
34
35/* Tx */
36#define WL1273_AUDIO_IO_SET_ANALOG 0
37#define WL1273_AUDIO_IO_SET_I2S 1
38
39#define WL1273_POWER_SET_OFF 0
40#define WL1273_POWER_SET_FM (1 << 0)
41#define WL1273_POWER_SET_RDS (1 << 1)
42#define WL1273_POWER_SET_RETENTION (1 << 4)
43
44#define WL1273_PUPD_SET_OFF 0x00
45#define WL1273_PUPD_SET_ON 0x01
46#define WL1273_PUPD_SET_RETENTION 0x10
47
48/* I2S mode */
49#define WL1273_IS2_WIDTH_32 0x0
50#define WL1273_IS2_WIDTH_40 0x1
51#define WL1273_IS2_WIDTH_22_23 0x2
52#define WL1273_IS2_WIDTH_23_22 0x3
53#define WL1273_IS2_WIDTH_48 0x4
54#define WL1273_IS2_WIDTH_50 0x5
55#define WL1273_IS2_WIDTH_60 0x6
56#define WL1273_IS2_WIDTH_64 0x7
57#define WL1273_IS2_WIDTH_80 0x8
58#define WL1273_IS2_WIDTH_96 0x9
59#define WL1273_IS2_WIDTH_128 0xa
60#define WL1273_IS2_WIDTH 0xf
61
62#define WL1273_IS2_FORMAT_STD (0x0 << 4)
63#define WL1273_IS2_FORMAT_LEFT (0x1 << 4)
64#define WL1273_IS2_FORMAT_RIGHT (0x2 << 4)
65#define WL1273_IS2_FORMAT_USER (0x3 << 4)
66
67#define WL1273_IS2_MASTER (0x0 << 6)
68#define WL1273_IS2_SLAVEW (0x1 << 6)
69
70#define WL1273_IS2_TRI_AFTER_SENDING (0x0 << 7)
71#define WL1273_IS2_TRI_ALWAYS_ACTIVE (0x1 << 7)
72
73#define WL1273_IS2_SDOWS_RR (0x0 << 8)
74#define WL1273_IS2_SDOWS_RF (0x1 << 8)
75#define WL1273_IS2_SDOWS_FR (0x2 << 8)
76#define WL1273_IS2_SDOWS_FF (0x3 << 8)
77
78#define WL1273_IS2_TRI_OPT (0x0 << 10)
79#define WL1273_IS2_TRI_ALWAYS (0x1 << 10)
80
81#define WL1273_IS2_RATE_48K (0x0 << 12)
82#define WL1273_IS2_RATE_44_1K (0x1 << 12)
83#define WL1273_IS2_RATE_32K (0x2 << 12)
84#define WL1273_IS2_RATE_22_05K (0x4 << 12)
85#define WL1273_IS2_RATE_16K (0x5 << 12)
86#define WL1273_IS2_RATE_12K (0x8 << 12)
87#define WL1273_IS2_RATE_11_025 (0x9 << 12)
88#define WL1273_IS2_RATE_8K (0xa << 12)
89#define WL1273_IS2_RATE (0xf << 12)
90
91#define WL1273_I2S_DEF_MODE (WL1273_IS2_WIDTH_32 | \
92 WL1273_IS2_FORMAT_STD | \
93 WL1273_IS2_MASTER | \
94 WL1273_IS2_TRI_AFTER_SENDING | \
95 WL1273_IS2_SDOWS_RR | \
96 WL1273_IS2_TRI_OPT | \
97 WL1273_IS2_RATE_48K)
98
99int wl1273_get_format(struct snd_soc_codec *codec, unsigned int *fmt);
100
101#endif /* End of __WL1273_CODEC_H__ */
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h
index c18e261c3c7f..0b6f056f73cc 100644
--- a/sound/soc/codecs/wm2000.h
+++ b/sound/soc/codecs/wm2000.h
@@ -16,9 +16,6 @@ struct wm2000_setup_data {
16 16
17extern int wm2000_add_controls(struct snd_soc_codec *codec); 17extern int wm2000_add_controls(struct snd_soc_codec *codec);
18 18
19extern struct snd_soc_dai wm2000_dai;
20extern struct snd_soc_codec_device soc_codec_dev_wm2000;
21
22#define WM2000_REG_SYS_START 0x8000 19#define WM2000_REG_SYS_START 0x8000
23#define WM2000_REG_SPEECH_CLARITY 0x8fef 20#define WM2000_REG_SPEECH_CLARITY 0x8fef
24#define WM2000_REG_SYS_WATCHDOG 0x8ff6 21#define WM2000_REG_SYS_WATCHDOG 0x8ff6
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 0221ca79b3ae..f4f1fba38eb9 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1321,20 +1321,14 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,
1321 return 0; 1321 return 0;
1322} 1322}
1323 1323
1324static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) 1324static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state)
1325{ 1325{
1326 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1327 struct snd_soc_codec *codec = socdev->card->codec;
1328
1329 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); 1326 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
1330 return 0; 1327 return 0;
1331} 1328}
1332 1329
1333static int wm8350_resume(struct platform_device *pdev) 1330static int wm8350_resume(struct snd_soc_codec *codec)
1334{ 1331{
1335 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1336 struct snd_soc_codec *codec = socdev->card->codec;
1337
1338 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1332 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1339 1333
1340 return 0; 1334 return 0;
@@ -1489,24 +1483,74 @@ int wm8350_mic_jack_detect(struct snd_soc_codec *codec,
1489} 1483}
1490EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect); 1484EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect);
1491 1485
1492static struct snd_soc_codec *wm8350_codec; 1486#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000)
1487
1488#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
1489 SNDRV_PCM_FMTBIT_S20_3LE |\
1490 SNDRV_PCM_FMTBIT_S24_LE)
1491
1492static struct snd_soc_dai_ops wm8350_dai_ops = {
1493 .hw_params = wm8350_pcm_hw_params,
1494 .digital_mute = wm8350_mute,
1495 .trigger = wm8350_pcm_trigger,
1496 .set_fmt = wm8350_set_dai_fmt,
1497 .set_sysclk = wm8350_set_dai_sysclk,
1498 .set_pll = wm8350_set_fll,
1499 .set_clkdiv = wm8350_set_clkdiv,
1500};
1501
1502static struct snd_soc_dai_driver wm8350_dai = {
1503 .name = "wm8350-hifi",
1504 .playback = {
1505 .stream_name = "Playback",
1506 .channels_min = 1,
1507 .channels_max = 2,
1508 .rates = WM8350_RATES,
1509 .formats = WM8350_FORMATS,
1510 },
1511 .capture = {
1512 .stream_name = "Capture",
1513 .channels_min = 1,
1514 .channels_max = 2,
1515 .rates = WM8350_RATES,
1516 .formats = WM8350_FORMATS,
1517 },
1518 .ops = &wm8350_dai_ops,
1519};
1493 1520
1494static int wm8350_probe(struct platform_device *pdev) 1521static int wm8350_codec_probe(struct snd_soc_codec *codec)
1495{ 1522{
1496 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1523 struct wm8350 *wm8350 = dev_get_platdata(codec->dev);
1497 struct snd_soc_codec *codec;
1498 struct wm8350 *wm8350;
1499 struct wm8350_data *priv; 1524 struct wm8350_data *priv;
1500 int ret;
1501 struct wm8350_output *out1; 1525 struct wm8350_output *out1;
1502 struct wm8350_output *out2; 1526 struct wm8350_output *out2;
1527 int ret, i;
1503 1528
1504 BUG_ON(!wm8350_codec); 1529 if (wm8350->codec.platform_data == NULL) {
1530 dev_err(codec->dev, "No audio platform data supplied\n");
1531 return -EINVAL;
1532 }
1533
1534 priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
1535 if (priv == NULL)
1536 return -ENOMEM;
1537 snd_soc_codec_set_drvdata(codec, priv);
1538
1539 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
1540 priv->supplies[i].supply = supply_names[i];
1541
1542 ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
1543 priv->supplies);
1544 if (ret != 0)
1545 goto err_priv;
1546
1547 wm8350->codec.codec = codec;
1548 codec->control_data = wm8350;
1505 1549
1506 socdev->card->codec = wm8350_codec; 1550 /* Put the codec into reset if it wasn't already */
1507 codec = socdev->card->codec; 1551 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
1508 wm8350 = codec->control_data; 1552
1509 priv = snd_soc_codec_get_drvdata(codec); 1553 INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
1510 1554
1511 /* Enable the codec */ 1555 /* Enable the codec */
1512 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); 1556 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
@@ -1557,11 +1601,6 @@ static int wm8350_probe(struct platform_device *pdev)
1557 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD, 1601 wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_MICD,
1558 wm8350_mic_handler, 0, "Microphone detect", priv); 1602 wm8350_mic_handler, 0, "Microphone detect", priv);
1559 1603
1560 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1561 if (ret < 0) {
1562 dev_err(&pdev->dev, "failed to create pcms\n");
1563 return ret;
1564 }
1565 1604
1566 snd_soc_add_controls(codec, wm8350_snd_controls, 1605 snd_soc_add_controls(codec, wm8350_snd_controls,
1567 ARRAY_SIZE(wm8350_snd_controls)); 1606 ARRAY_SIZE(wm8350_snd_controls));
@@ -1570,14 +1609,16 @@ static int wm8350_probe(struct platform_device *pdev)
1570 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1609 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1571 1610
1572 return 0; 1611 return 0;
1612
1613err_priv:
1614 kfree(priv);
1615 return ret;
1573} 1616}
1574 1617
1575static int wm8350_remove(struct platform_device *pdev) 1618static int wm8350_codec_remove(struct snd_soc_codec *codec)
1576{ 1619{
1577 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1578 struct snd_soc_codec *codec = socdev->card->codec;
1579 struct wm8350 *wm8350 = codec->control_data;
1580 struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec); 1620 struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
1621 struct wm8350 *wm8350 = dev_get_platdata(codec->dev);
1581 int ret; 1622 int ret;
1582 1623
1583 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, 1624 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,
@@ -1607,134 +1648,30 @@ static int wm8350_remove(struct platform_device *pdev)
1607 1648
1608 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); 1649 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
1609 1650
1651 regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
1652 kfree(priv);
1610 return 0; 1653 return 0;
1611} 1654}
1612 1655
1613#define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) 1656static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
1614 1657 .probe = wm8350_codec_probe,
1615#define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ 1658 .remove = wm8350_codec_remove,
1616 SNDRV_PCM_FMTBIT_S20_3LE |\
1617 SNDRV_PCM_FMTBIT_S24_LE)
1618
1619static struct snd_soc_dai_ops wm8350_dai_ops = {
1620 .hw_params = wm8350_pcm_hw_params,
1621 .digital_mute = wm8350_mute,
1622 .trigger = wm8350_pcm_trigger,
1623 .set_fmt = wm8350_set_dai_fmt,
1624 .set_sysclk = wm8350_set_dai_sysclk,
1625 .set_pll = wm8350_set_fll,
1626 .set_clkdiv = wm8350_set_clkdiv,
1627};
1628
1629struct snd_soc_dai wm8350_dai = {
1630 .name = "WM8350",
1631 .playback = {
1632 .stream_name = "Playback",
1633 .channels_min = 1,
1634 .channels_max = 2,
1635 .rates = WM8350_RATES,
1636 .formats = WM8350_FORMATS,
1637 },
1638 .capture = {
1639 .stream_name = "Capture",
1640 .channels_min = 1,
1641 .channels_max = 2,
1642 .rates = WM8350_RATES,
1643 .formats = WM8350_FORMATS,
1644 },
1645 .ops = &wm8350_dai_ops,
1646};
1647EXPORT_SYMBOL_GPL(wm8350_dai);
1648
1649struct snd_soc_codec_device soc_codec_dev_wm8350 = {
1650 .probe = wm8350_probe,
1651 .remove = wm8350_remove,
1652 .suspend = wm8350_suspend, 1659 .suspend = wm8350_suspend,
1653 .resume = wm8350_resume, 1660 .resume = wm8350_resume,
1661 .read = wm8350_codec_read,
1662 .write = wm8350_codec_write,
1663 .set_bias_level = wm8350_set_bias_level,
1654}; 1664};
1655EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350);
1656 1665
1657static __devinit int wm8350_codec_probe(struct platform_device *pdev) 1666static int __devinit wm8350_probe(struct platform_device *pdev)
1658{ 1667{
1659 struct wm8350 *wm8350 = platform_get_drvdata(pdev); 1668 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8350,
1660 struct wm8350_data *priv; 1669 &wm8350_dai, 1);
1661 struct snd_soc_codec *codec;
1662 int ret, i;
1663
1664 if (wm8350->codec.platform_data == NULL) {
1665 dev_err(&pdev->dev, "No audio platform data supplied\n");
1666 return -EINVAL;
1667 }
1668
1669 priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
1670 if (priv == NULL)
1671 return -ENOMEM;
1672
1673 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
1674 priv->supplies[i].supply = supply_names[i];
1675
1676 ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
1677 priv->supplies);
1678 if (ret != 0)
1679 goto err_priv;
1680
1681 codec = &priv->codec;
1682 wm8350->codec.codec = codec;
1683
1684 wm8350_dai.dev = &pdev->dev;
1685
1686 mutex_init(&codec->mutex);
1687 INIT_LIST_HEAD(&codec->dapm_widgets);
1688 INIT_LIST_HEAD(&codec->dapm_paths);
1689 codec->dev = &pdev->dev;
1690 codec->name = "WM8350";
1691 codec->owner = THIS_MODULE;
1692 codec->read = wm8350_codec_read;
1693 codec->write = wm8350_codec_write;
1694 codec->bias_level = SND_SOC_BIAS_OFF;
1695 codec->set_bias_level = wm8350_set_bias_level;
1696 codec->dai = &wm8350_dai;
1697 codec->num_dai = 1;
1698 codec->reg_cache_size = WM8350_MAX_REGISTER;
1699 snd_soc_codec_set_drvdata(codec, priv);
1700 codec->control_data = wm8350;
1701
1702 /* Put the codec into reset if it wasn't already */
1703 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
1704
1705 INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work);
1706 ret = snd_soc_register_codec(codec);
1707 if (ret != 0)
1708 goto err_supply;
1709
1710 wm8350_codec = codec;
1711
1712 ret = snd_soc_register_dai(&wm8350_dai);
1713 if (ret != 0)
1714 goto err_codec;
1715 return 0;
1716
1717err_codec:
1718 snd_soc_unregister_codec(codec);
1719err_supply:
1720 regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
1721err_priv:
1722 kfree(priv);
1723 wm8350_codec = NULL;
1724 return ret;
1725} 1670}
1726 1671
1727static int __devexit wm8350_codec_remove(struct platform_device *pdev) 1672static int __devexit wm8350_remove(struct platform_device *pdev)
1728{ 1673{
1729 struct wm8350 *wm8350 = platform_get_drvdata(pdev); 1674 snd_soc_unregister_codec(&pdev->dev);
1730 struct snd_soc_codec *codec = wm8350->codec.codec;
1731 struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);
1732
1733 snd_soc_unregister_dai(&wm8350_dai);
1734 snd_soc_unregister_codec(codec);
1735 regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
1736 kfree(priv);
1737 wm8350_codec = NULL;
1738 return 0; 1675 return 0;
1739} 1676}
1740 1677
@@ -1743,8 +1680,8 @@ static struct platform_driver wm8350_codec_driver = {
1743 .name = "wm8350-codec", 1680 .name = "wm8350-codec",
1744 .owner = THIS_MODULE, 1681 .owner = THIS_MODULE,
1745 }, 1682 },
1746 .probe = wm8350_codec_probe, 1683 .probe = wm8350_probe,
1747 .remove = __devexit_p(wm8350_codec_remove), 1684 .remove = __devexit_p(wm8350_remove),
1748}; 1685};
1749 1686
1750static __init int wm8350_init(void) 1687static __init int wm8350_init(void)
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h
index 9ed0467c71db..74108eb82938 100644
--- a/sound/soc/codecs/wm8350.h
+++ b/sound/soc/codecs/wm8350.h
@@ -15,9 +15,6 @@
15#include <sound/soc.h> 15#include <sound/soc.h>
16#include <linux/mfd/wm8350/audio.h> 16#include <linux/mfd/wm8350/audio.h>
17 17
18extern struct snd_soc_dai wm8350_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8350;
20
21enum wm8350_jack { 18enum wm8350_jack {
22 WM8350_JDL = 1, 19 WM8350_JDL = 1,
23 WM8350_JDR = 2, 20 WM8350_JDR = 2,
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index 8f294066b0ed..850299786e02 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -65,7 +65,7 @@ static struct regulator_bulk_data power[] = {
65 65
66/* codec private data */ 66/* codec private data */
67struct wm8400_priv { 67struct wm8400_priv {
68 struct snd_soc_codec codec; 68 struct snd_soc_codec *codec;
69 struct wm8400 *wm8400; 69 struct wm8400 *wm8400;
70 u16 fake_register; 70 u16 fake_register;
71 unsigned int sysclk; 71 unsigned int sysclk;
@@ -1163,8 +1163,7 @@ static int wm8400_hw_params(struct snd_pcm_substream *substream,
1163 struct snd_soc_dai *dai) 1163 struct snd_soc_dai *dai)
1164{ 1164{
1165 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1165 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1166 struct snd_soc_device *socdev = rtd->socdev; 1166 struct snd_soc_codec *codec = rtd->codec;
1167 struct snd_soc_codec *codec = socdev->card->codec;
1168 u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1); 1167 u16 audio1 = wm8400_read(codec, WM8400_AUDIO_INTERFACE_1);
1169 1168
1170 audio1 &= ~WM8400_AIF_WL_MASK; 1169 audio1 &= ~WM8400_AIF_WL_MASK;
@@ -1332,10 +1331,9 @@ static struct snd_soc_dai_ops wm8400_dai_ops = {
1332 * 1. ADC/DAC on Primary Interface 1331 * 1. ADC/DAC on Primary Interface
1333 * 2. ADC on Primary Interface/DAC on secondary 1332 * 2. ADC on Primary Interface/DAC on secondary
1334 */ 1333 */
1335struct snd_soc_dai wm8400_dai = { 1334static struct snd_soc_dai_driver wm8400_dai = {
1336/* ADC/DAC on primary */ 1335/* ADC/DAC on primary */
1337 .name = "WM8400 ADC/DAC Primary", 1336 .name = "wm8400-hifi",
1338 .id = 1,
1339 .playback = { 1337 .playback = {
1340 .stream_name = "Playback", 1338 .stream_name = "Playback",
1341 .channels_min = 1, 1339 .channels_min = 1,
@@ -1352,147 +1350,53 @@ struct snd_soc_dai wm8400_dai = {
1352 }, 1350 },
1353 .ops = &wm8400_dai_ops, 1351 .ops = &wm8400_dai_ops,
1354}; 1352};
1355EXPORT_SYMBOL_GPL(wm8400_dai);
1356 1353
1357static int wm8400_suspend(struct platform_device *pdev, pm_message_t state) 1354static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state)
1358{ 1355{
1359 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1360 struct snd_soc_codec *codec = socdev->card->codec;
1361
1362 wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF); 1356 wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
1363 1357
1364 return 0; 1358 return 0;
1365} 1359}
1366 1360
1367static int wm8400_resume(struct platform_device *pdev) 1361static int wm8400_resume(struct snd_soc_codec *codec)
1368{ 1362{
1369 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1370 struct snd_soc_codec *codec = socdev->card->codec;
1371
1372 wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1363 wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1373 1364
1374 return 0; 1365 return 0;
1375} 1366}
1376 1367
1377static struct snd_soc_codec *wm8400_codec;
1378
1379static int wm8400_probe(struct platform_device *pdev)
1380{
1381 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1382 struct snd_soc_codec *codec;
1383 int ret;
1384
1385 if (!wm8400_codec) {
1386 dev_err(&pdev->dev, "wm8400 not yet discovered\n");
1387 return -ENODEV;
1388 }
1389 codec = wm8400_codec;
1390
1391 socdev->card->codec = codec;
1392
1393 /* register pcms */
1394 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1395 if (ret < 0) {
1396 dev_err(&pdev->dev, "failed to create pcms\n");
1397 goto pcm_err;
1398 }
1399
1400 wm8400_add_controls(codec);
1401 wm8400_add_widgets(codec);
1402
1403pcm_err:
1404 return ret;
1405}
1406
1407/* power down chip */
1408static int wm8400_remove(struct platform_device *pdev)
1409{
1410 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1411
1412 snd_soc_free_pcms(socdev);
1413 snd_soc_dapm_free(socdev);
1414
1415 return 0;
1416}
1417
1418struct snd_soc_codec_device soc_codec_dev_wm8400 = {
1419 .probe = wm8400_probe,
1420 .remove = wm8400_remove,
1421 .suspend = wm8400_suspend,
1422 .resume = wm8400_resume,
1423};
1424
1425static void wm8400_probe_deferred(struct work_struct *work) 1368static void wm8400_probe_deferred(struct work_struct *work)
1426{ 1369{
1427 struct wm8400_priv *priv = container_of(work, struct wm8400_priv, 1370 struct wm8400_priv *priv = container_of(work, struct wm8400_priv,
1428 work); 1371 work);
1429 struct snd_soc_codec *codec = &priv->codec; 1372 struct snd_soc_codec *codec = priv->codec;
1430 int ret;
1431 1373
1432 /* charge output caps */ 1374 /* charge output caps */
1433 wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1375 wm8400_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1434
1435 /* We're done, tell the subsystem. */
1436 ret = snd_soc_register_codec(codec);
1437 if (ret != 0) {
1438 dev_err(priv->wm8400->dev,
1439 "Failed to register codec: %d\n", ret);
1440 goto err;
1441 }
1442
1443 ret = snd_soc_register_dai(&wm8400_dai);
1444 if (ret != 0) {
1445 dev_err(priv->wm8400->dev,
1446 "Failed to register DAI: %d\n", ret);
1447 goto err_codec;
1448 }
1449
1450 return;
1451
1452err_codec:
1453 snd_soc_unregister_codec(codec);
1454err:
1455 wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
1456} 1376}
1457 1377
1458static int wm8400_codec_probe(struct platform_device *dev) 1378static int wm8400_codec_probe(struct snd_soc_codec *codec)
1459{ 1379{
1380 struct wm8400 *wm8400 = dev_get_platdata(codec->dev);
1460 struct wm8400_priv *priv; 1381 struct wm8400_priv *priv;
1461 int ret; 1382 int ret;
1462 u16 reg; 1383 u16 reg;
1463 struct snd_soc_codec *codec;
1464 1384
1465 priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL); 1385 priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL);
1466 if (priv == NULL) 1386 if (priv == NULL)
1467 return -ENOMEM; 1387 return -ENOMEM;
1468 1388
1469 codec = &priv->codec;
1470 snd_soc_codec_set_drvdata(codec, priv); 1389 snd_soc_codec_set_drvdata(codec, priv);
1471 codec->control_data = dev_get_drvdata(&dev->dev); 1390 codec->control_data = priv->wm8400 = wm8400;
1472 priv->wm8400 = dev_get_drvdata(&dev->dev); 1391 priv->codec = codec;
1473 1392
1474 ret = regulator_bulk_get(priv->wm8400->dev, 1393 ret = regulator_bulk_get(wm8400->dev,
1475 ARRAY_SIZE(power), &power[0]); 1394 ARRAY_SIZE(power), &power[0]);
1476 if (ret != 0) { 1395 if (ret != 0) {
1477 dev_err(&dev->dev, "Failed to get regulators: %d\n", ret); 1396 dev_err(codec->dev, "Failed to get regulators: %d\n", ret);
1478 goto err; 1397 goto err;
1479 } 1398 }
1480 1399
1481 codec->dev = &dev->dev;
1482 wm8400_dai.dev = &dev->dev;
1483
1484 codec->name = "WM8400";
1485 codec->owner = THIS_MODULE;
1486 codec->read = wm8400_read;
1487 codec->write = wm8400_write;
1488 codec->bias_level = SND_SOC_BIAS_OFF;
1489 codec->set_bias_level = wm8400_set_bias_level;
1490 codec->dai = &wm8400_dai;
1491 codec->num_dai = 1;
1492 codec->reg_cache_size = WM8400_REGISTER_COUNT;
1493 mutex_init(&codec->mutex);
1494 INIT_LIST_HEAD(&codec->dapm_widgets);
1495 INIT_LIST_HEAD(&codec->dapm_paths);
1496 INIT_WORK(&priv->work, wm8400_probe_deferred); 1400 INIT_WORK(&priv->work, wm8400_probe_deferred);
1497 1401
1498 wm8400_codec_reset(codec); 1402 wm8400_codec_reset(codec);
@@ -1511,65 +1415,78 @@ static int wm8400_codec_probe(struct platform_device *dev)
1511 wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1415 wm8400_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
1512 wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); 1416 wm8400_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
1513 1417
1514 wm8400_codec = codec;
1515
1516 if (!schedule_work(&priv->work)) { 1418 if (!schedule_work(&priv->work)) {
1517 ret = -EINVAL; 1419 ret = -EINVAL;
1518 goto err_regulator; 1420 goto err_regulator;
1519 } 1421 }
1520 1422 wm8400_add_controls(codec);
1423 wm8400_add_widgets(codec);
1521 return 0; 1424 return 0;
1522 1425
1523err_regulator: 1426err_regulator:
1524 wm8400_codec = NULL;
1525 regulator_bulk_free(ARRAY_SIZE(power), power); 1427 regulator_bulk_free(ARRAY_SIZE(power), power);
1526err: 1428err:
1527 kfree(priv); 1429 kfree(priv);
1528 return ret; 1430 return ret;
1529} 1431}
1530 1432
1531static int __exit wm8400_codec_remove(struct platform_device *dev) 1433static int wm8400_codec_remove(struct snd_soc_codec *codec)
1532{ 1434{
1533 struct wm8400_priv *priv = snd_soc_codec_get_drvdata(wm8400_codec); 1435 struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec);
1534 u16 reg; 1436 u16 reg;
1535 1437
1536 snd_soc_unregister_dai(&wm8400_dai); 1438 reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
1537 snd_soc_unregister_codec(wm8400_codec); 1439 wm8400_write(codec, WM8400_POWER_MANAGEMENT_1,
1538
1539 reg = wm8400_read(wm8400_codec, WM8400_POWER_MANAGEMENT_1);
1540 wm8400_write(wm8400_codec, WM8400_POWER_MANAGEMENT_1,
1541 reg & (~WM8400_CODEC_ENA)); 1440 reg & (~WM8400_CODEC_ENA));
1542 1441
1543 regulator_bulk_free(ARRAY_SIZE(power), power); 1442 regulator_bulk_free(ARRAY_SIZE(power), power);
1544 kfree(priv); 1443 kfree(priv);
1545 1444
1546 wm8400_codec = NULL; 1445 return 0;
1446}
1447
1448static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
1449 .probe = wm8400_codec_probe,
1450 .remove = wm8400_codec_remove,
1451 .suspend = wm8400_suspend,
1452 .resume = wm8400_resume,
1453 .read = wm8400_read,
1454 .write = wm8400_write,
1455 .set_bias_level = wm8400_set_bias_level,
1456};
1457
1458static int __devinit wm8400_probe(struct platform_device *pdev)
1459{
1460 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8400,
1461 &wm8400_dai, 1);
1462}
1547 1463
1464static int __devexit wm8400_remove(struct platform_device *pdev)
1465{
1466 snd_soc_unregister_codec(&pdev->dev);
1548 return 0; 1467 return 0;
1549} 1468}
1550 1469
1551static struct platform_driver wm8400_codec_driver = { 1470static struct platform_driver wm8400_codec_driver = {
1552 .driver = { 1471 .driver = {
1553 .name = "wm8400-codec", 1472 .name = "wm8400-codec",
1554 .owner = THIS_MODULE, 1473 .owner = THIS_MODULE,
1555 }, 1474 },
1556 .probe = wm8400_codec_probe, 1475 .probe = wm8400_probe,
1557 .remove = __exit_p(wm8400_codec_remove), 1476 .remove = __devexit_p(wm8400_remove),
1558}; 1477};
1559 1478
1560static int __init wm8400_codec_init(void) 1479static __init int wm8400_init(void)
1561{ 1480{
1562 return platform_driver_register(&wm8400_codec_driver); 1481 return platform_driver_register(&wm8400_codec_driver);
1563} 1482}
1564module_init(wm8400_codec_init); 1483module_init(wm8400_init);
1565 1484
1566static void __exit wm8400_codec_exit(void) 1485static __exit void wm8400_exit(void)
1567{ 1486{
1568 platform_driver_unregister(&wm8400_codec_driver); 1487 platform_driver_unregister(&wm8400_codec_driver);
1569} 1488}
1570module_exit(wm8400_codec_exit); 1489module_exit(wm8400_exit);
1571
1572EXPORT_SYMBOL_GPL(soc_codec_dev_wm8400);
1573 1490
1574MODULE_DESCRIPTION("ASoC WM8400 driver"); 1491MODULE_DESCRIPTION("ASoC WM8400 driver");
1575MODULE_AUTHOR("Mark Brown"); 1492MODULE_AUTHOR("Mark Brown");
diff --git a/sound/soc/codecs/wm8400.h b/sound/soc/codecs/wm8400.h
index 79c5934d4776..521adb193870 100644
--- a/sound/soc/codecs/wm8400.h
+++ b/sound/soc/codecs/wm8400.h
@@ -56,7 +56,4 @@
56#define WM8400_BCLK_DIV_44 (0xE << 1) 56#define WM8400_BCLK_DIV_44 (0xE << 1)
57#define WM8400_BCLK_DIV_48 (0xF << 1) 57#define WM8400_BCLK_DIV_48 (0xF << 1)
58 58
59extern struct snd_soc_dai wm8400_dai;
60extern struct snd_soc_codec_device soc_codec_dev_wm8400;
61
62#endif 59#endif
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 0f7bcb61071a..8f107095760e 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -29,10 +29,6 @@
29 29
30#include "wm8510.h" 30#include "wm8510.h"
31 31
32#define WM8510_VERSION "0.6"
33
34struct snd_soc_codec_device soc_codec_dev_wm8510;
35
36/* 32/*
37 * wm8510 register cache 33 * wm8510 register cache
38 * We can't read the WM8510 register space when we are 34 * We can't read the WM8510 register space when we are
@@ -61,6 +57,11 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
61 57
62#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) 58#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
63 59
60/* codec private data */
61struct wm8510_priv {
62 enum snd_soc_control_type control_type;
63};
64
64static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; 65static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
65static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; 66static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
66static const char *wm8510_alc[] = { "ALC", "Limiter" }; 67static const char *wm8510_alc[] = { "ALC", "Limiter" };
@@ -403,8 +404,7 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
403 struct snd_soc_dai *dai) 404 struct snd_soc_dai *dai)
404{ 405{
405 struct snd_soc_pcm_runtime *rtd = substream->private_data; 406 struct snd_soc_pcm_runtime *rtd = substream->private_data;
406 struct snd_soc_device *socdev = rtd->socdev; 407 struct snd_soc_codec *codec = rtd->codec;
407 struct snd_soc_codec *codec = socdev->card->codec;
408 u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; 408 u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
409 u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; 409 u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
410 410
@@ -514,8 +514,8 @@ static struct snd_soc_dai_ops wm8510_dai_ops = {
514 .set_pll = wm8510_set_dai_pll, 514 .set_pll = wm8510_set_dai_pll,
515}; 515};
516 516
517struct snd_soc_dai wm8510_dai = { 517static struct snd_soc_dai_driver wm8510_dai = {
518 .name = "WM8510 HiFi", 518 .name = "wm8510-hifi",
519 .playback = { 519 .playback = {
520 .stream_name = "Playback", 520 .stream_name = "Playback",
521 .channels_min = 2, 521 .channels_min = 2,
@@ -531,21 +531,15 @@ struct snd_soc_dai wm8510_dai = {
531 .ops = &wm8510_dai_ops, 531 .ops = &wm8510_dai_ops,
532 .symmetric_rates = 1, 532 .symmetric_rates = 1,
533}; 533};
534EXPORT_SYMBOL_GPL(wm8510_dai);
535 534
536static int wm8510_suspend(struct platform_device *pdev, pm_message_t state) 535static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
537{ 536{
538 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
539 struct snd_soc_codec *codec = socdev->card->codec;
540
541 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); 537 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
542 return 0; 538 return 0;
543} 539}
544 540
545static int wm8510_resume(struct platform_device *pdev) 541static int wm8510_resume(struct snd_soc_codec *codec)
546{ 542{
547 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
548 struct snd_soc_codec *codec = socdev->card->codec;
549 int i; 543 int i;
550 u8 data[2]; 544 u8 data[2];
551 u16 *cache = codec->reg_cache; 545 u16 *cache = codec->reg_cache;
@@ -561,256 +555,158 @@ static int wm8510_resume(struct platform_device *pdev)
561 return 0; 555 return 0;
562} 556}
563 557
564/* 558static int wm8510_probe(struct snd_soc_codec *codec)
565 * initialise the WM8510 driver
566 * register the mixer and dsp interfaces with the kernel
567 */
568static int wm8510_init(struct snd_soc_device *socdev,
569 enum snd_soc_control_type control)
570{ 559{
571 struct snd_soc_codec *codec = socdev->card->codec; 560 struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
572 int ret = 0; 561 int ret;
573
574 codec->name = "WM8510";
575 codec->owner = THIS_MODULE;
576 codec->set_bias_level = wm8510_set_bias_level;
577 codec->dai = &wm8510_dai;
578 codec->num_dai = 1;
579 codec->reg_cache_size = ARRAY_SIZE(wm8510_reg);
580 codec->reg_cache = kmemdup(wm8510_reg, sizeof(wm8510_reg), GFP_KERNEL);
581
582 if (codec->reg_cache == NULL)
583 return -ENOMEM;
584 562
585 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 563 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type);
586 if (ret < 0) { 564 if (ret < 0) {
587 printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", 565 printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret);
588 ret); 566 return ret;
589 goto err;
590 } 567 }
591 568
592 wm8510_reset(codec); 569 wm8510_reset(codec);
593 570
594 /* register pcms */
595 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
596 if (ret < 0) {
597 printk(KERN_ERR "wm8510: failed to create pcms\n");
598 goto err;
599 }
600
601 /* power on device */ 571 /* power on device */
602 codec->bias_level = SND_SOC_BIAS_OFF;
603 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 572 wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
604 snd_soc_add_controls(codec, wm8510_snd_controls, 573 snd_soc_add_controls(codec, wm8510_snd_controls,
605 ARRAY_SIZE(wm8510_snd_controls)); 574 ARRAY_SIZE(wm8510_snd_controls));
606 wm8510_add_widgets(codec); 575 wm8510_add_widgets(codec);
607 576
608 return ret; 577 return ret;
609
610err:
611 kfree(codec->reg_cache);
612 return ret;
613} 578}
614 579
615static struct snd_soc_device *wm8510_socdev; 580/* power down chip */
581static int wm8510_remove(struct snd_soc_codec *codec)
582{
583 struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec);
616 584
617#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 585 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
586 kfree(wm8510);
587 return 0;
588}
618 589
619/* 590static struct snd_soc_codec_driver soc_codec_dev_wm8510 = {
620 * WM8510 2 wire address is 0x1a 591 .probe = wm8510_probe,
621 */ 592 .remove = wm8510_remove,
593 .suspend = wm8510_suspend,
594 .resume = wm8510_resume,
595 .set_bias_level = wm8510_set_bias_level,
596 .reg_cache_size = ARRAY_SIZE(wm8510_reg),
597 .reg_word_size = sizeof(u16),
598 .reg_cache_default =wm8510_reg,
599};
622 600
623static int wm8510_i2c_probe(struct i2c_client *i2c, 601#if defined(CONFIG_SPI_MASTER)
624 const struct i2c_device_id *id) 602static int __devinit wm8510_spi_probe(struct spi_device *spi)
625{ 603{
626 struct snd_soc_device *socdev = wm8510_socdev; 604 struct wm8510_priv *wm8510;
627 struct snd_soc_codec *codec = socdev->card->codec;
628 int ret; 605 int ret;
629 606
630 i2c_set_clientdata(i2c, codec); 607 wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL);
631 codec->control_data = i2c; 608 if (wm8510 == NULL)
609 return -ENOMEM;
632 610
633 ret = wm8510_init(socdev, SND_SOC_I2C); 611 wm8510->control_type = SND_SOC_SPI;
634 if (ret < 0) 612 spi_set_drvdata(spi, wm8510);
635 pr_err("failed to initialise WM8510\n");
636 613
614 ret = snd_soc_register_codec(&spi->dev,
615 &soc_codec_dev_wm8510, &wm8510_dai, 1);
616 if (ret < 0)
617 kfree(wm8510);
637 return ret; 618 return ret;
638} 619}
639 620
640static int wm8510_i2c_remove(struct i2c_client *client) 621static int __devexit wm8510_spi_remove(struct spi_device *spi)
641{ 622{
642 struct snd_soc_codec *codec = i2c_get_clientdata(client); 623 snd_soc_unregister_codec(&spi->dev);
643 kfree(codec->reg_cache);
644 return 0; 624 return 0;
645} 625}
646 626
647static const struct i2c_device_id wm8510_i2c_id[] = { 627static struct spi_driver wm8510_spi_driver = {
648 { "wm8510", 0 },
649 { }
650};
651MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
652
653static struct i2c_driver wm8510_i2c_driver = {
654 .driver = { 628 .driver = {
655 .name = "WM8510 I2C Codec", 629 .name = "wm8510",
656 .owner = THIS_MODULE, 630 .owner = THIS_MODULE,
657 }, 631 },
658 .probe = wm8510_i2c_probe, 632 .probe = wm8510_spi_probe,
659 .remove = wm8510_i2c_remove, 633 .remove = __devexit_p(wm8510_spi_remove),
660 .id_table = wm8510_i2c_id,
661}; 634};
635#endif /* CONFIG_SPI_MASTER */
662 636
663static int wm8510_add_i2c_device(struct platform_device *pdev, 637#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
664 const struct wm8510_setup_data *setup) 638static __devinit int wm8510_i2c_probe(struct i2c_client *i2c,
639 const struct i2c_device_id *id)
665{ 640{
666 struct i2c_board_info info; 641 struct wm8510_priv *wm8510;
667 struct i2c_adapter *adapter;
668 struct i2c_client *client;
669 int ret; 642 int ret;
670 643
671 ret = i2c_add_driver(&wm8510_i2c_driver); 644 wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL);
672 if (ret != 0) { 645 if (wm8510 == NULL)
673 dev_err(&pdev->dev, "can't add i2c driver\n"); 646 return -ENOMEM;
674 return ret;
675 }
676
677 memset(&info, 0, sizeof(struct i2c_board_info));
678 info.addr = setup->i2c_address;
679 strlcpy(info.type, "wm8510", I2C_NAME_SIZE);
680
681 adapter = i2c_get_adapter(setup->i2c_bus);
682 if (!adapter) {
683 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
684 setup->i2c_bus);
685 goto err_driver;
686 }
687
688 client = i2c_new_device(adapter, &info);
689 i2c_put_adapter(adapter);
690 if (!client) {
691 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
692 (unsigned int)info.addr);
693 goto err_driver;
694 }
695
696 return 0;
697
698err_driver:
699 i2c_del_driver(&wm8510_i2c_driver);
700 return -ENODEV;
701}
702#endif
703
704#if defined(CONFIG_SPI_MASTER)
705static int __devinit wm8510_spi_probe(struct spi_device *spi)
706{
707 struct snd_soc_device *socdev = wm8510_socdev;
708 struct snd_soc_codec *codec = socdev->card->codec;
709 int ret;
710 647
711 codec->control_data = spi; 648 i2c_set_clientdata(i2c, wm8510);
649 wm8510->control_type = SND_SOC_I2C;
712 650
713 ret = wm8510_init(socdev, SND_SOC_SPI); 651 ret = snd_soc_register_codec(&i2c->dev,
652 &soc_codec_dev_wm8510, &wm8510_dai, 1);
714 if (ret < 0) 653 if (ret < 0)
715 dev_err(&spi->dev, "failed to initialise WM8510\n"); 654 kfree(wm8510);
716
717 return ret; 655 return ret;
718} 656}
719 657
720static int __devexit wm8510_spi_remove(struct spi_device *spi) 658static __devexit int wm8510_i2c_remove(struct i2c_client *client)
721{ 659{
660 snd_soc_unregister_codec(&client->dev);
722 return 0; 661 return 0;
723} 662}
724 663
725static struct spi_driver wm8510_spi_driver = { 664static const struct i2c_device_id wm8510_i2c_id[] = {
665 { "wm8510", 0 },
666 { }
667};
668MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
669
670static struct i2c_driver wm8510_i2c_driver = {
726 .driver = { 671 .driver = {
727 .name = "wm8510", 672 .name = "wm8510-codec",
728 .bus = &spi_bus_type, 673 .owner = THIS_MODULE,
729 .owner = THIS_MODULE,
730 }, 674 },
731 .probe = wm8510_spi_probe, 675 .probe = wm8510_i2c_probe,
732 .remove = __devexit_p(wm8510_spi_remove), 676 .remove = __devexit_p(wm8510_i2c_remove),
677 .id_table = wm8510_i2c_id,
733}; 678};
734#endif /* CONFIG_SPI_MASTER */ 679#endif
735 680
736static int wm8510_probe(struct platform_device *pdev) 681static int __init wm8510_modinit(void)
737{ 682{
738 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
739 struct wm8510_setup_data *setup;
740 struct snd_soc_codec *codec;
741 int ret = 0; 683 int ret = 0;
742
743 pr_info("WM8510 Audio Codec %s", WM8510_VERSION);
744
745 setup = socdev->codec_data;
746 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
747 if (codec == NULL)
748 return -ENOMEM;
749
750 socdev->card->codec = codec;
751 mutex_init(&codec->mutex);
752 INIT_LIST_HEAD(&codec->dapm_widgets);
753 INIT_LIST_HEAD(&codec->dapm_paths);
754
755 wm8510_socdev = socdev;
756#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 684#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
757 if (setup->i2c_address) { 685 ret = i2c_add_driver(&wm8510_i2c_driver);
758 ret = wm8510_add_i2c_device(pdev, setup); 686 if (ret != 0) {
687 printk(KERN_ERR "Failed to register WM8510 I2C driver: %d\n",
688 ret);
759 } 689 }
760#endif 690#endif
761#if defined(CONFIG_SPI_MASTER) 691#if defined(CONFIG_SPI_MASTER)
762 if (setup->spi) { 692 ret = spi_register_driver(&wm8510_spi_driver);
763 ret = spi_register_driver(&wm8510_spi_driver); 693 if (ret != 0) {
764 if (ret != 0) 694 printk(KERN_ERR "Failed to register WM8510 SPI driver: %d\n",
765 printk(KERN_ERR "can't add spi driver"); 695 ret);
766 } 696 }
767#endif 697#endif
768
769 if (ret != 0)
770 kfree(codec);
771 return ret; 698 return ret;
772} 699}
700module_init(wm8510_modinit);
773 701
774/* power down chip */ 702static void __exit wm8510_exit(void)
775static int wm8510_remove(struct platform_device *pdev)
776{ 703{
777 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
778 struct snd_soc_codec *codec = socdev->card->codec;
779
780 if (codec->control_data)
781 wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
782
783 snd_soc_free_pcms(socdev);
784 snd_soc_dapm_free(socdev);
785#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 704#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
786 i2c_unregister_device(codec->control_data);
787 i2c_del_driver(&wm8510_i2c_driver); 705 i2c_del_driver(&wm8510_i2c_driver);
788#endif 706#endif
789#if defined(CONFIG_SPI_MASTER) 707#if defined(CONFIG_SPI_MASTER)
790 spi_unregister_driver(&wm8510_spi_driver); 708 spi_unregister_driver(&wm8510_spi_driver);
791#endif 709#endif
792 kfree(codec);
793
794 return 0;
795}
796
797struct snd_soc_codec_device soc_codec_dev_wm8510 = {
798 .probe = wm8510_probe,
799 .remove = wm8510_remove,
800 .suspend = wm8510_suspend,
801 .resume = wm8510_resume,
802};
803EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
804
805static int __init wm8510_modinit(void)
806{
807 return snd_soc_register_dai(&wm8510_dai);
808}
809module_init(wm8510_modinit);
810
811static void __exit wm8510_exit(void)
812{
813 snd_soc_unregister_dai(&wm8510_dai);
814} 710}
815module_exit(wm8510_exit); 711module_exit(wm8510_exit);
816 712
diff --git a/sound/soc/codecs/wm8510.h b/sound/soc/codecs/wm8510.h
index bdefcf5c69ff..b3e26ed9f2d0 100644
--- a/sound/soc/codecs/wm8510.h
+++ b/sound/soc/codecs/wm8510.h
@@ -99,7 +99,4 @@ struct wm8510_setup_data {
99 unsigned short i2c_address; 99 unsigned short i2c_address;
100}; 100};
101 101
102extern struct snd_soc_dai wm8510_dai;
103extern struct snd_soc_codec_device soc_codec_dev_wm8510;
104
105#endif 102#endif
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 0ad039b4adf5..712ef7c76f90 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -30,9 +30,6 @@
30 30
31#include "wm8523.h" 31#include "wm8523.h"
32 32
33static struct snd_soc_codec *wm8523_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8523;
35
36#define WM8523_NUM_SUPPLIES 2 33#define WM8523_NUM_SUPPLIES 2
37static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { 34static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
38 "AVDD", 35 "AVDD",
@@ -43,7 +40,7 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
43 40
44/* codec private data */ 41/* codec private data */
45struct wm8523_priv { 42struct wm8523_priv {
46 struct snd_soc_codec codec; 43 enum snd_soc_control_type control_type;
47 u16 reg_cache[WM8523_REGISTER_COUNT]; 44 u16 reg_cache[WM8523_REGISTER_COUNT];
48 struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; 45 struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
49 unsigned int sysclk; 46 unsigned int sysclk;
@@ -162,8 +159,7 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
162 struct snd_soc_dai *dai) 159 struct snd_soc_dai *dai)
163{ 160{
164 struct snd_soc_pcm_runtime *rtd = substream->private_data; 161 struct snd_soc_pcm_runtime *rtd = substream->private_data;
165 struct snd_soc_device *socdev = rtd->socdev; 162 struct snd_soc_codec *codec = rtd->codec;
166 struct snd_soc_codec *codec = socdev->card->codec;
167 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); 163 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
168 int i; 164 int i;
169 u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); 165 u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1);
@@ -387,8 +383,8 @@ static struct snd_soc_dai_ops wm8523_dai_ops = {
387 .set_fmt = wm8523_set_dai_fmt, 383 .set_fmt = wm8523_set_dai_fmt,
388}; 384};
389 385
390struct snd_soc_dai wm8523_dai = { 386static struct snd_soc_dai_driver wm8523_dai = {
391 .name = "WM8523", 387 .name = "wm8523-hifi",
392 .playback = { 388 .playback = {
393 .stream_name = "Playback", 389 .stream_name = "Playback",
394 .channels_min = 2, /* Mono modes not yet supported */ 390 .channels_min = 2, /* Mono modes not yet supported */
@@ -398,25 +394,17 @@ struct snd_soc_dai wm8523_dai = {
398 }, 394 },
399 .ops = &wm8523_dai_ops, 395 .ops = &wm8523_dai_ops,
400}; 396};
401EXPORT_SYMBOL_GPL(wm8523_dai);
402 397
403#ifdef CONFIG_PM 398#ifdef CONFIG_PM
404static int wm8523_suspend(struct platform_device *pdev, pm_message_t state) 399static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state)
405{ 400{
406 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
407 struct snd_soc_codec *codec = socdev->card->codec;
408
409 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); 401 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
410 return 0; 402 return 0;
411} 403}
412 404
413static int wm8523_resume(struct platform_device *pdev) 405static int wm8523_resume(struct snd_soc_codec *codec)
414{ 406{
415 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
416 struct snd_soc_codec *codec = socdev->card->codec;
417
418 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 407 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
419
420 return 0; 408 return 0;
421} 409}
422#else 410#else
@@ -424,93 +412,20 @@ static int wm8523_resume(struct platform_device *pdev)
424#define wm8523_resume NULL 412#define wm8523_resume NULL
425#endif 413#endif
426 414
427static int wm8523_probe(struct platform_device *pdev) 415static int wm8523_probe(struct snd_soc_codec *codec)
428{
429 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
430 struct snd_soc_codec *codec;
431 int ret = 0;
432
433 if (wm8523_codec == NULL) {
434 dev_err(&pdev->dev, "Codec device not registered\n");
435 return -ENODEV;
436 }
437
438 socdev->card->codec = wm8523_codec;
439 codec = wm8523_codec;
440
441 /* register pcms */
442 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
443 if (ret < 0) {
444 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
445 goto pcm_err;
446 }
447
448 snd_soc_add_controls(codec, wm8523_snd_controls,
449 ARRAY_SIZE(wm8523_snd_controls));
450 wm8523_add_widgets(codec);
451
452 return ret;
453
454pcm_err:
455 return ret;
456}
457
458static int wm8523_remove(struct platform_device *pdev)
459{
460 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
461
462 snd_soc_free_pcms(socdev);
463 snd_soc_dapm_free(socdev);
464
465 return 0;
466}
467
468struct snd_soc_codec_device soc_codec_dev_wm8523 = {
469 .probe = wm8523_probe,
470 .remove = wm8523_remove,
471 .suspend = wm8523_suspend,
472 .resume = wm8523_resume,
473};
474EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523);
475
476static int wm8523_register(struct wm8523_priv *wm8523,
477 enum snd_soc_control_type control)
478{ 416{
479 int ret; 417 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
480 struct snd_soc_codec *codec = &wm8523->codec; 418 int ret, i;
481 int i;
482
483 if (wm8523_codec) {
484 dev_err(codec->dev, "Another WM8523 is registered\n");
485 ret = -EINVAL;
486 goto err;
487 }
488
489 mutex_init(&codec->mutex);
490 INIT_LIST_HEAD(&codec->dapm_widgets);
491 INIT_LIST_HEAD(&codec->dapm_paths);
492
493 snd_soc_codec_set_drvdata(codec, wm8523);
494 codec->name = "WM8523";
495 codec->owner = THIS_MODULE;
496 codec->bias_level = SND_SOC_BIAS_OFF;
497 codec->set_bias_level = wm8523_set_bias_level;
498 codec->dai = &wm8523_dai;
499 codec->num_dai = 1;
500 codec->reg_cache_size = WM8523_REGISTER_COUNT;
501 codec->reg_cache = &wm8523->reg_cache;
502 codec->volatile_register = wm8523_volatile_register;
503 419
420 codec->hw_write = (hw_write_t)i2c_master_send;
504 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; 421 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
505 wm8523->rate_constraint.count = 422 wm8523->rate_constraint.count =
506 ARRAY_SIZE(wm8523->rate_constraint_list); 423 ARRAY_SIZE(wm8523->rate_constraint_list);
507 424
508 memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); 425 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type);
509
510 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
511 if (ret != 0) { 426 if (ret != 0) {
512 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 427 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
513 goto err; 428 return ret;
514 } 429 }
515 430
516 for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) 431 for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++)
@@ -520,7 +435,7 @@ static int wm8523_register(struct wm8523_priv *wm8523,
520 wm8523->supplies); 435 wm8523->supplies);
521 if (ret != 0) { 436 if (ret != 0) {
522 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 437 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
523 goto err; 438 return ret;
524 } 439 }
525 440
526 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), 441 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies),
@@ -555,8 +470,6 @@ static int wm8523_register(struct wm8523_priv *wm8523,
555 goto err_enable; 470 goto err_enable;
556 } 471 }
557 472
558 wm8523_dai.dev = codec->dev;
559
560 /* Change some default settings - latch VU and enable ZC */ 473 /* Change some default settings - latch VU and enable ZC */
561 wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; 474 wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
562 wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; 475 wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
@@ -566,69 +479,67 @@ static int wm8523_register(struct wm8523_priv *wm8523,
566 /* Bias level configuration will have done an extra enable */ 479 /* Bias level configuration will have done an extra enable */
567 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 480 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
568 481
569 wm8523_codec = codec; 482 snd_soc_add_controls(codec, wm8523_snd_controls,
570 483 ARRAY_SIZE(wm8523_snd_controls));
571 ret = snd_soc_register_codec(codec); 484 wm8523_add_widgets(codec);
572 if (ret != 0) {
573 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
574 goto err_enable;
575 }
576
577 ret = snd_soc_register_dai(&wm8523_dai);
578 if (ret != 0) {
579 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
580 goto err_codec;
581 }
582 485
583 return 0; 486 return 0;
584 487
585err_codec:
586 snd_soc_unregister_codec(codec);
587err_enable: 488err_enable:
588 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 489 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
589err_get: 490err_get:
590 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 491 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
591err: 492
592 kfree(wm8523);
593 return ret; 493 return ret;
594} 494}
595 495
596static void wm8523_unregister(struct wm8523_priv *wm8523) 496static int wm8523_remove(struct snd_soc_codec *codec)
597{ 497{
598 wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF); 498 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
499
500 wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
599 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); 501 regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
600 snd_soc_unregister_dai(&wm8523_dai); 502 return 0;
601 snd_soc_unregister_codec(&wm8523->codec);
602 kfree(wm8523);
603 wm8523_codec = NULL;
604} 503}
605 504
505static struct snd_soc_codec_driver soc_codec_dev_wm8523 = {
506 .probe = wm8523_probe,
507 .remove = wm8523_remove,
508 .suspend = wm8523_suspend,
509 .resume = wm8523_resume,
510 .set_bias_level = wm8523_set_bias_level,
511 .reg_cache_size = WM8523_REGISTER_COUNT,
512 .reg_word_size = sizeof(u16),
513 .reg_cache_default = wm8523_reg,
514 .volatile_register = wm8523_volatile_register,
515};
516
606#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 517#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
607static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, 518static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
608 const struct i2c_device_id *id) 519 const struct i2c_device_id *id)
609{ 520{
610 struct wm8523_priv *wm8523; 521 struct wm8523_priv *wm8523;
611 struct snd_soc_codec *codec; 522 int ret;
612 523
613 wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); 524 wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL);
614 if (wm8523 == NULL) 525 if (wm8523 == NULL)
615 return -ENOMEM; 526 return -ENOMEM;
616 527
617 codec = &wm8523->codec;
618 codec->hw_write = (hw_write_t)i2c_master_send;
619
620 i2c_set_clientdata(i2c, wm8523); 528 i2c_set_clientdata(i2c, wm8523);
621 codec->control_data = i2c; 529 wm8523->control_type = SND_SOC_I2C;
622 530
623 codec->dev = &i2c->dev; 531 ret = snd_soc_register_codec(&i2c->dev,
532 &soc_codec_dev_wm8523, &wm8523_dai, 1);
533 if (ret < 0)
534 kfree(wm8523);
535 return ret;
624 536
625 return wm8523_register(wm8523, SND_SOC_I2C);
626} 537}
627 538
628static __devexit int wm8523_i2c_remove(struct i2c_client *client) 539static __devexit int wm8523_i2c_remove(struct i2c_client *client)
629{ 540{
630 struct wm8523_priv *wm8523 = i2c_get_clientdata(client); 541 snd_soc_unregister_codec(&client->dev);
631 wm8523_unregister(wm8523); 542 kfree(i2c_get_clientdata(client));
632 return 0; 543 return 0;
633} 544}
634 545
@@ -640,7 +551,7 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
640 551
641static struct i2c_driver wm8523_i2c_driver = { 552static struct i2c_driver wm8523_i2c_driver = {
642 .driver = { 553 .driver = {
643 .name = "WM8523", 554 .name = "wm8523-codec",
644 .owner = THIS_MODULE, 555 .owner = THIS_MODULE,
645 }, 556 },
646 .probe = wm8523_i2c_probe, 557 .probe = wm8523_i2c_probe,
diff --git a/sound/soc/codecs/wm8523.h b/sound/soc/codecs/wm8523.h
index 1aa9ce3e1357..4d5b1eb8f2fc 100644
--- a/sound/soc/codecs/wm8523.h
+++ b/sound/soc/codecs/wm8523.h
@@ -154,7 +154,4 @@
154#define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ 154#define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */
155#define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ 155#define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */
156 156
157extern struct snd_soc_dai wm8523_dai;
158extern struct snd_soc_codec_device soc_codec_dev_wm8523;
159
160#endif 157#endif
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 72deeabef4fe..a2e0ed59b376 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -94,6 +94,8 @@
94 94
95#define WM8580_MAX_REGISTER 0x35 95#define WM8580_MAX_REGISTER 0x35
96 96
97#define WM8580_DACOSR 0x40
98
97/* PLLB4 (register 7h) */ 99/* PLLB4 (register 7h) */
98#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60 100#define WM8580_PLLB4_MCLKOUTSRC_MASK 0x60
99#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20 101#define WM8580_PLLB4_MCLKOUTSRC_PLLA 0x20
@@ -112,19 +114,7 @@
112 114
113/* AIF control 1 (registers 9h-bh) */ 115/* AIF control 1 (registers 9h-bh) */
114#define WM8580_AIF_RATE_MASK 0x7 116#define WM8580_AIF_RATE_MASK 0x7
115#define WM8580_AIF_RATE_128 0x0
116#define WM8580_AIF_RATE_192 0x1
117#define WM8580_AIF_RATE_256 0x2
118#define WM8580_AIF_RATE_384 0x3
119#define WM8580_AIF_RATE_512 0x4
120#define WM8580_AIF_RATE_768 0x5
121#define WM8580_AIF_RATE_1152 0x6
122
123#define WM8580_AIF_BCLKSEL_MASK 0x18 117#define WM8580_AIF_BCLKSEL_MASK 0x18
124#define WM8580_AIF_BCLKSEL_64 0x00
125#define WM8580_AIF_BCLKSEL_128 0x08
126#define WM8580_AIF_BCLKSEL_256 0x10
127#define WM8580_AIF_BCLKSEL_SYSCLK 0x18
128 118
129#define WM8580_AIF_MS 0x20 119#define WM8580_AIF_MS 0x20
130 120
@@ -199,11 +189,12 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = {
199 189
200/* codec private data */ 190/* codec private data */
201struct wm8580_priv { 191struct wm8580_priv {
202 struct snd_soc_codec codec; 192 enum snd_soc_control_type control_type;
203 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; 193 struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES];
204 u16 reg_cache[WM8580_MAX_REGISTER + 1]; 194 u16 reg_cache[WM8580_MAX_REGISTER + 1];
205 struct pll_state a; 195 struct pll_state a;
206 struct pll_state b; 196 struct pll_state b;
197 int sysclk[2];
207}; 198};
208 199
209static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); 200static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1);
@@ -273,8 +264,8 @@ SOC_SINGLE("DAC1 Switch", WM8580_DAC_CONTROL5, 0, 1, 1),
273SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1), 264SOC_SINGLE("DAC2 Switch", WM8580_DAC_CONTROL5, 1, 1, 1),
274SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1), 265SOC_SINGLE("DAC3 Switch", WM8580_DAC_CONTROL5, 2, 1, 1),
275 266
276SOC_DOUBLE("ADC Mute Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 0), 267SOC_DOUBLE("Capture Switch", WM8580_ADC_CONTROL1, 0, 1, 1, 1),
277SOC_SINGLE("ADC High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0), 268SOC_SINGLE("Capture High-Pass Filter Switch", WM8580_ADC_CONTROL1, 4, 1, 0),
278}; 269};
279 270
280static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = { 271static const struct snd_soc_dapm_widget wm8580_dapm_widgets[] = {
@@ -476,6 +467,10 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
476 return 0; 467 return 0;
477} 468}
478 469
470static const int wm8580_sysclk_ratios[] = {
471 128, 192, 256, 384, 512, 768, 1152,
472};
473
479/* 474/*
480 * Set PCM DAI bit size and sample rate. 475 * Set PCM DAI bit size and sample rate.
481 */ 476 */
@@ -484,29 +479,68 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
484 struct snd_soc_dai *dai) 479 struct snd_soc_dai *dai)
485{ 480{
486 struct snd_soc_pcm_runtime *rtd = substream->private_data; 481 struct snd_soc_pcm_runtime *rtd = substream->private_data;
487 struct snd_soc_device *socdev = rtd->socdev; 482 struct snd_soc_codec *codec = rtd->codec;
488 struct snd_soc_codec *codec = socdev->card->codec; 483 struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
489 u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); 484 u16 paifa = 0;
485 u16 paifb = 0;
486 int i, ratio, osr;
490 487
491 paifb &= ~WM8580_AIF_LENGTH_MASK;
492 /* bit size */ 488 /* bit size */
493 switch (params_format(params)) { 489 switch (params_format(params)) {
494 case SNDRV_PCM_FORMAT_S16_LE: 490 case SNDRV_PCM_FORMAT_S16_LE:
491 paifa |= 0x8;
495 break; 492 break;
496 case SNDRV_PCM_FORMAT_S20_3LE: 493 case SNDRV_PCM_FORMAT_S20_3LE:
494 paifa |= 0x10;
497 paifb |= WM8580_AIF_LENGTH_20; 495 paifb |= WM8580_AIF_LENGTH_20;
498 break; 496 break;
499 case SNDRV_PCM_FORMAT_S24_LE: 497 case SNDRV_PCM_FORMAT_S24_LE:
498 paifa |= 0x10;
500 paifb |= WM8580_AIF_LENGTH_24; 499 paifb |= WM8580_AIF_LENGTH_24;
501 break; 500 break;
502 case SNDRV_PCM_FORMAT_S32_LE: 501 case SNDRV_PCM_FORMAT_S32_LE:
502 paifa |= 0x10;
503 paifb |= WM8580_AIF_LENGTH_24; 503 paifb |= WM8580_AIF_LENGTH_24;
504 break; 504 break;
505 default: 505 default:
506 return -EINVAL; 506 return -EINVAL;
507 } 507 }
508 508
509 snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); 509 /* Look up the SYSCLK ratio; accept only exact matches */
510 ratio = wm8580->sysclk[dai->id] / params_rate(params);
511 for (i = 0; i < ARRAY_SIZE(wm8580_sysclk_ratios); i++)
512 if (ratio == wm8580_sysclk_ratios[i])
513 break;
514 if (i == ARRAY_SIZE(wm8580_sysclk_ratios)) {
515 dev_err(codec->dev, "Invalid clock ratio %d/%d\n",
516 wm8580->sysclk[dai->id], params_rate(params));
517 return -EINVAL;
518 }
519 paifa |= i;
520 dev_dbg(codec->dev, "Running at %dfs with %dHz clock\n",
521 wm8580_sysclk_ratios[i], wm8580->sysclk[dai->driver->id]);
522
523 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
524 switch (ratio) {
525 case 128:
526 case 192:
527 osr = WM8580_DACOSR;
528 dev_dbg(codec->dev, "Selecting 64x OSR\n");
529 break;
530 default:
531 osr = 0;
532 dev_dbg(codec->dev, "Selecting 128x OSR\n");
533 break;
534 }
535
536 snd_soc_update_bits(codec, WM8580_PAIF3, WM8580_DACOSR, osr);
537 }
538
539 snd_soc_update_bits(codec, WM8580_PAIF1 + dai->driver->id,
540 WM8580_AIF_RATE_MASK | WM8580_AIF_BCLKSEL_MASK,
541 paifa);
542 snd_soc_update_bits(codec, WM8580_PAIF3 + dai->driver->id,
543 WM8580_AIF_LENGTH_MASK, paifb);
510 return 0; 544 return 0;
511} 545}
512 546
@@ -518,8 +552,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
518 unsigned int aifb; 552 unsigned int aifb;
519 int can_invert_lrclk; 553 int can_invert_lrclk;
520 554
521 aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); 555 aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->driver->id);
522 aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); 556 aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->driver->id);
523 557
524 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); 558 aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP);
525 559
@@ -585,8 +619,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
585 return -EINVAL; 619 return -EINVAL;
586 } 620 }
587 621
588 snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); 622 snd_soc_write(codec, WM8580_PAIF1 + codec_dai->driver->id, aifa);
589 snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); 623 snd_soc_write(codec, WM8580_PAIF3 + codec_dai->driver->id, aifb);
590 624
591 return 0; 625 return 0;
592} 626}
@@ -624,28 +658,6 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
624 snd_soc_write(codec, WM8580_PLLB4, reg); 658 snd_soc_write(codec, WM8580_PLLB4, reg);
625 break; 659 break;
626 660
627 case WM8580_DAC_CLKSEL:
628 reg = snd_soc_read(codec, WM8580_CLKSEL);
629 reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK;
630
631 switch (div) {
632 case WM8580_CLKSRC_MCLK:
633 break;
634
635 case WM8580_CLKSRC_PLLA:
636 reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLA;
637 break;
638
639 case WM8580_CLKSRC_PLLB:
640 reg |= WM8580_CLKSEL_DAC_CLKSEL_PLLB;
641 break;
642
643 default:
644 return -EINVAL;
645 }
646 snd_soc_write(codec, WM8580_CLKSEL, reg);
647 break;
648
649 case WM8580_CLKOUTSRC: 661 case WM8580_CLKOUTSRC:
650 reg = snd_soc_read(codec, WM8580_PLLB4); 662 reg = snd_soc_read(codec, WM8580_PLLB4);
651 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; 663 reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK;
@@ -679,6 +691,55 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
679 return 0; 691 return 0;
680} 692}
681 693
694static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,
695 unsigned int freq, int dir)
696{
697 struct snd_soc_codec *codec = dai->codec;
698 struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
699 int sel, sel_mask, sel_shift;
700
701 switch (dai->driver->id) {
702 case WM8580_DAI_PAIFRX:
703 sel_mask = 0x3;
704 sel_shift = 0;
705 break;
706
707 case WM8580_DAI_PAIFTX:
708 sel_mask = 0xc;
709 sel_shift = 2;
710 break;
711
712 default:
713 BUG_ON("Unknown DAI driver ID\n");
714 return -EINVAL;
715 }
716
717 switch (clk_id) {
718 case WM8580_CLKSRC_ADCMCLK:
719 if (dai->id != WM8580_DAI_PAIFTX)
720 return -EINVAL;
721 sel = 0 << sel_shift;
722 break;
723 case WM8580_CLKSRC_PLLA:
724 sel = 1 << sel_shift;
725 break;
726 case WM8580_CLKSRC_PLLB:
727 sel = 2 << sel_shift;
728 break;
729 case WM8580_CLKSRC_MCLK:
730 sel = 3 << sel_shift;
731 break;
732 default:
733 dev_err(codec->dev, "Unknown clock %d\n", clk_id);
734 return -EINVAL;
735 }
736
737 /* We really should validate PLL settings but not yet */
738 wm8580->sysclk[dai->id] = freq;
739
740 return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel);
741}
742
682static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) 743static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
683{ 744{
684 struct snd_soc_codec *codec = codec_dai->codec; 745 struct snd_soc_codec *codec = codec_dai->codec;
@@ -732,6 +793,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
732 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 793 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
733 794
734static struct snd_soc_dai_ops wm8580_dai_ops_playback = { 795static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
796 .set_sysclk = wm8580_set_sysclk,
735 .hw_params = wm8580_paif_hw_params, 797 .hw_params = wm8580_paif_hw_params,
736 .set_fmt = wm8580_set_paif_dai_fmt, 798 .set_fmt = wm8580_set_paif_dai_fmt,
737 .set_clkdiv = wm8580_set_dai_clkdiv, 799 .set_clkdiv = wm8580_set_dai_clkdiv,
@@ -740,16 +802,17 @@ static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
740}; 802};
741 803
742static struct snd_soc_dai_ops wm8580_dai_ops_capture = { 804static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
805 .set_sysclk = wm8580_set_sysclk,
743 .hw_params = wm8580_paif_hw_params, 806 .hw_params = wm8580_paif_hw_params,
744 .set_fmt = wm8580_set_paif_dai_fmt, 807 .set_fmt = wm8580_set_paif_dai_fmt,
745 .set_clkdiv = wm8580_set_dai_clkdiv, 808 .set_clkdiv = wm8580_set_dai_clkdiv,
746 .set_pll = wm8580_set_dai_pll, 809 .set_pll = wm8580_set_dai_pll,
747}; 810};
748 811
749struct snd_soc_dai wm8580_dai[] = { 812static struct snd_soc_dai_driver wm8580_dai[] = {
750 { 813 {
751 .name = "WM8580 PAIFRX", 814 .name = "wm8580-hifi-playback",
752 .id = 0, 815 .id = WM8580_DAI_PAIFRX,
753 .playback = { 816 .playback = {
754 .stream_name = "Playback", 817 .stream_name = "Playback",
755 .channels_min = 1, 818 .channels_min = 1,
@@ -760,8 +823,8 @@ struct snd_soc_dai wm8580_dai[] = {
760 .ops = &wm8580_dai_ops_playback, 823 .ops = &wm8580_dai_ops_playback,
761 }, 824 },
762 { 825 {
763 .name = "WM8580 PAIFTX", 826 .name = "wm8580-hifi-capture",
764 .id = 1, 827 .id = WM8580_DAI_PAIFTX,
765 .capture = { 828 .capture = {
766 .stream_name = "Capture", 829 .stream_name = "Capture",
767 .channels_min = 2, 830 .channels_min = 2,
@@ -772,90 +835,16 @@ struct snd_soc_dai wm8580_dai[] = {
772 .ops = &wm8580_dai_ops_capture, 835 .ops = &wm8580_dai_ops_capture,
773 }, 836 },
774}; 837};
775EXPORT_SYMBOL_GPL(wm8580_dai);
776
777static struct snd_soc_codec *wm8580_codec;
778 838
779static int wm8580_probe(struct platform_device *pdev) 839static int wm8580_probe(struct snd_soc_codec *codec)
780{ 840{
781 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 841 struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
782 struct snd_soc_codec *codec; 842 int ret = 0,i;
783 int ret = 0;
784
785 if (wm8580_codec == NULL) {
786 dev_err(&pdev->dev, "Codec device not registered\n");
787 return -ENODEV;
788 }
789
790 socdev->card->codec = wm8580_codec;
791 codec = wm8580_codec;
792
793 /* register pcms */
794 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
795 if (ret < 0) {
796 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
797 goto pcm_err;
798 }
799
800 snd_soc_add_controls(codec, wm8580_snd_controls,
801 ARRAY_SIZE(wm8580_snd_controls));
802 wm8580_add_widgets(codec);
803
804 return ret;
805
806pcm_err:
807 return ret;
808}
809
810/* power down chip */
811static int wm8580_remove(struct platform_device *pdev)
812{
813 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
814
815 snd_soc_free_pcms(socdev);
816 snd_soc_dapm_free(socdev);
817
818 return 0;
819}
820
821struct snd_soc_codec_device soc_codec_dev_wm8580 = {
822 .probe = wm8580_probe,
823 .remove = wm8580_remove,
824};
825EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
826
827static int wm8580_register(struct wm8580_priv *wm8580,
828 enum snd_soc_control_type control)
829{
830 int ret, i;
831 struct snd_soc_codec *codec = &wm8580->codec;
832
833 if (wm8580_codec) {
834 dev_err(codec->dev, "Another WM8580 is registered\n");
835 ret = -EINVAL;
836 goto err;
837 }
838
839 mutex_init(&codec->mutex);
840 INIT_LIST_HEAD(&codec->dapm_widgets);
841 INIT_LIST_HEAD(&codec->dapm_paths);
842
843 snd_soc_codec_set_drvdata(codec, wm8580);
844 codec->name = "WM8580";
845 codec->owner = THIS_MODULE;
846 codec->bias_level = SND_SOC_BIAS_OFF;
847 codec->set_bias_level = wm8580_set_bias_level;
848 codec->dai = wm8580_dai;
849 codec->num_dai = ARRAY_SIZE(wm8580_dai);
850 codec->reg_cache_size = ARRAY_SIZE(wm8580->reg_cache);
851 codec->reg_cache = &wm8580->reg_cache;
852
853 memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg));
854 843
855 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 844 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type);
856 if (ret < 0) { 845 if (ret < 0) {
857 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 846 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
858 goto err; 847 return ret;
859 } 848 }
860 849
861 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) 850 for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++)
@@ -865,7 +854,7 @@ static int wm8580_register(struct wm8580_priv *wm8580,
865 wm8580->supplies); 854 wm8580->supplies);
866 if (ret != 0) { 855 if (ret != 0) {
867 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 856 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
868 goto err; 857 return ret;
869 } 858 }
870 859
871 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), 860 ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies),
@@ -882,74 +871,68 @@ static int wm8580_register(struct wm8580_priv *wm8580,
882 goto err_regulator_enable; 871 goto err_regulator_enable;
883 } 872 }
884 873
885 for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++)
886 wm8580_dai[i].dev = codec->dev;
887
888 wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 874 wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
889 875
890 wm8580_codec = codec; 876 snd_soc_add_controls(codec, wm8580_snd_controls,
891 877 ARRAY_SIZE(wm8580_snd_controls));
892 ret = snd_soc_register_codec(codec); 878 wm8580_add_widgets(codec);
893 if (ret != 0) {
894 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
895 goto err_regulator_enable;
896 }
897
898 ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
899 if (ret != 0) {
900 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
901 goto err_codec;
902 }
903 879
904 return 0; 880 return 0;
905 881
906err_codec:
907 snd_soc_unregister_codec(codec);
908err_regulator_enable: 882err_regulator_enable:
909 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); 883 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
910err_regulator_get: 884err_regulator_get:
911 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); 885 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
912err:
913 kfree(wm8580);
914 return ret; 886 return ret;
915} 887}
916 888
917static void wm8580_unregister(struct wm8580_priv *wm8580) 889/* power down chip */
890static int wm8580_remove(struct snd_soc_codec *codec)
918{ 891{
919 wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); 892 struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
920 snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); 893
921 snd_soc_unregister_codec(&wm8580->codec); 894 wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF);
895
922 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); 896 regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
923 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); 897 regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies);
924 kfree(wm8580); 898
925 wm8580_codec = NULL; 899 return 0;
926} 900}
927 901
902static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
903 .probe = wm8580_probe,
904 .remove = wm8580_remove,
905 .set_bias_level = wm8580_set_bias_level,
906 .reg_cache_size = ARRAY_SIZE(wm8580_reg),
907 .reg_word_size = sizeof(u16),
908 .reg_cache_default = &wm8580_reg,
909};
910
928#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 911#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
929static int wm8580_i2c_probe(struct i2c_client *i2c, 912static int wm8580_i2c_probe(struct i2c_client *i2c,
930 const struct i2c_device_id *id) 913 const struct i2c_device_id *id)
931{ 914{
932 struct wm8580_priv *wm8580; 915 struct wm8580_priv *wm8580;
933 struct snd_soc_codec *codec; 916 int ret;
934 917
935 wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); 918 wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL);
936 if (wm8580 == NULL) 919 if (wm8580 == NULL)
937 return -ENOMEM; 920 return -ENOMEM;
938 921
939 codec = &wm8580->codec;
940
941 i2c_set_clientdata(i2c, wm8580); 922 i2c_set_clientdata(i2c, wm8580);
942 codec->control_data = i2c; 923 wm8580->control_type = SND_SOC_I2C;
943 924
944 codec->dev = &i2c->dev; 925 ret = snd_soc_register_codec(&i2c->dev,
945 926 &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai));
946 return wm8580_register(wm8580, SND_SOC_I2C); 927 if (ret < 0)
928 kfree(wm8580);
929 return ret;
947} 930}
948 931
949static int wm8580_i2c_remove(struct i2c_client *client) 932static int wm8580_i2c_remove(struct i2c_client *client)
950{ 933{
951 struct wm8580_priv *wm8580 = i2c_get_clientdata(client); 934 snd_soc_unregister_codec(&client->dev);
952 wm8580_unregister(wm8580); 935 kfree(i2c_get_clientdata(client));
953 return 0; 936 return 0;
954} 937}
955 938
@@ -961,7 +944,7 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
961 944
962static struct i2c_driver wm8580_i2c_driver = { 945static struct i2c_driver wm8580_i2c_driver = {
963 .driver = { 946 .driver = {
964 .name = "wm8580", 947 .name = "wm8580-codec",
965 .owner = THIS_MODULE, 948 .owner = THIS_MODULE,
966 }, 949 },
967 .probe = wm8580_i2c_probe, 950 .probe = wm8580_i2c_probe,
@@ -972,7 +955,7 @@ static struct i2c_driver wm8580_i2c_driver = {
972 955
973static int __init wm8580_modinit(void) 956static int __init wm8580_modinit(void)
974{ 957{
975 int ret; 958 int ret = 0;
976 959
977#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 960#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
978 ret = i2c_add_driver(&wm8580_i2c_driver); 961 ret = i2c_add_driver(&wm8580_i2c_driver);
@@ -981,7 +964,7 @@ static int __init wm8580_modinit(void)
981 } 964 }
982#endif 965#endif
983 966
984 return 0; 967 return ret;
985} 968}
986module_init(wm8580_modinit); 969module_init(wm8580_modinit);
987 970
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h
index 0dfb5ddde6a2..1d34656d0dcb 100644
--- a/sound/soc/codecs/wm8580.h
+++ b/sound/soc/codecs/wm8580.h
@@ -19,20 +19,17 @@
19#define WM8580_PLLB 2 19#define WM8580_PLLB 2
20 20
21#define WM8580_MCLK 1 21#define WM8580_MCLK 1
22#define WM8580_DAC_CLKSEL 2 22#define WM8580_CLKOUTSRC 2
23#define WM8580_CLKOUTSRC 3
24 23
25#define WM8580_CLKSRC_MCLK 1 24#define WM8580_CLKSRC_MCLK 1
26#define WM8580_CLKSRC_PLLA 2 25#define WM8580_CLKSRC_PLLA 2
27#define WM8580_CLKSRC_PLLB 3 26#define WM8580_CLKSRC_PLLB 3
28#define WM8580_CLKSRC_OSC 4 27#define WM8580_CLKSRC_OSC 4
29#define WM8580_CLKSRC_NONE 5 28#define WM8580_CLKSRC_NONE 5
29#define WM8580_CLKSRC_ADCMCLK 6
30 30
31#define WM8580_DAI_PAIFRX 0 31#define WM8580_DAI_PAIFRX 0
32#define WM8580_DAI_PAIFTX 1 32#define WM8580_DAI_PAIFTX 1
33 33
34extern struct snd_soc_dai wm8580_dai[];
35extern struct snd_soc_codec_device soc_codec_dev_wm8580;
36
37#endif 34#endif
38 35
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index e2dba07f0260..54fbd76c8bca 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -31,11 +31,9 @@
31 31
32#include "wm8711.h" 32#include "wm8711.h"
33 33
34static struct snd_soc_codec *wm8711_codec;
35
36/* codec private data */ 34/* codec private data */
37struct wm8711_priv { 35struct wm8711_priv {
38 struct snd_soc_codec codec; 36 enum snd_soc_control_type bus_type;
39 u16 reg_cache[WM8711_CACHEREGNUM]; 37 u16 reg_cache[WM8711_CACHEREGNUM];
40 unsigned int sysclk; 38 unsigned int sysclk;
41}; 39};
@@ -163,7 +161,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,
163 struct snd_soc_dai *dai) 161 struct snd_soc_dai *dai)
164{ 162{
165 struct snd_soc_codec *codec = dai->codec; 163 struct snd_soc_codec *codec = dai->codec;
166 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); 164 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
167 u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc; 165 u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
168 int i = get_coeff(wm8711->sysclk, params_rate(params)); 166 int i = get_coeff(wm8711->sysclk, params_rate(params));
169 u16 srate = (coeff_div[i].sr << 2) | 167 u16 srate = (coeff_div[i].sr << 2) |
@@ -227,7 +225,7 @@ static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai,
227 int clk_id, unsigned int freq, int dir) 225 int clk_id, unsigned int freq, int dir)
228{ 226{
229 struct snd_soc_codec *codec = codec_dai->codec; 227 struct snd_soc_codec *codec = codec_dai->codec;
230 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); 228 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
231 229
232 switch (freq) { 230 switch (freq) {
233 case 11289600: 231 case 11289600:
@@ -338,8 +336,8 @@ static struct snd_soc_dai_ops wm8711_ops = {
338 .set_fmt = wm8711_set_dai_fmt, 336 .set_fmt = wm8711_set_dai_fmt,
339}; 337};
340 338
341struct snd_soc_dai wm8711_dai = { 339static struct snd_soc_dai_driver wm8711_dai = {
342 .name = "WM8711", 340 .name = "wm8711-hifi",
343 .playback = { 341 .playback = {
344 .stream_name = "Playback", 342 .stream_name = "Playback",
345 .channels_min = 1, 343 .channels_min = 1,
@@ -349,22 +347,16 @@ struct snd_soc_dai wm8711_dai = {
349 }, 347 },
350 .ops = &wm8711_ops, 348 .ops = &wm8711_ops,
351}; 349};
352EXPORT_SYMBOL_GPL(wm8711_dai);
353 350
354static int wm8711_suspend(struct platform_device *pdev, pm_message_t state) 351static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
355{ 352{
356 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
357 struct snd_soc_codec *codec = socdev->card->codec;
358
359 snd_soc_write(codec, WM8711_ACTIVE, 0x0); 353 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
360 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF); 354 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
361 return 0; 355 return 0;
362} 356}
363 357
364static int wm8711_resume(struct platform_device *pdev) 358static int wm8711_resume(struct snd_soc_codec *codec)
365{ 359{
366 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
367 struct snd_soc_codec *codec = socdev->card->codec;
368 int i; 360 int i;
369 u8 data[2]; 361 u8 data[2];
370 u16 *cache = codec->reg_cache; 362 u16 *cache = codec->reg_cache;
@@ -380,99 +372,23 @@ static int wm8711_resume(struct platform_device *pdev)
380 return 0; 372 return 0;
381} 373}
382 374
383static int wm8711_probe(struct platform_device *pdev) 375static int wm8711_probe(struct snd_soc_codec *codec)
384{ 376{
385 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 377 struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
386 struct snd_soc_codec *codec; 378 int ret, reg;
387 int ret = 0;
388
389 if (wm8711_codec == NULL) {
390 dev_err(&pdev->dev, "Codec device not registered\n");
391 return -ENODEV;
392 }
393
394 socdev->card->codec = wm8711_codec;
395 codec = wm8711_codec;
396
397 /* register pcms */
398 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
399 if (ret < 0) {
400 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
401 goto pcm_err;
402 }
403
404 snd_soc_add_controls(codec, wm8711_snd_controls,
405 ARRAY_SIZE(wm8711_snd_controls));
406 wm8711_add_widgets(codec);
407
408 return ret;
409
410pcm_err:
411 return ret;
412}
413
414/* power down chip */
415static int wm8711_remove(struct platform_device *pdev)
416{
417 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
418
419 snd_soc_free_pcms(socdev);
420 snd_soc_dapm_free(socdev);
421
422 return 0;
423}
424
425struct snd_soc_codec_device soc_codec_dev_wm8711 = {
426 .probe = wm8711_probe,
427 .remove = wm8711_remove,
428 .suspend = wm8711_suspend,
429 .resume = wm8711_resume,
430};
431EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711);
432
433static int wm8711_register(struct wm8711_priv *wm8711,
434 enum snd_soc_control_type control)
435{
436 int ret;
437 struct snd_soc_codec *codec = &wm8711->codec;
438 u16 reg;
439
440 if (wm8711_codec) {
441 dev_err(codec->dev, "Another WM8711 is registered\n");
442 ret = -EINVAL;
443 goto err;
444 }
445
446 mutex_init(&codec->mutex);
447 INIT_LIST_HEAD(&codec->dapm_widgets);
448 INIT_LIST_HEAD(&codec->dapm_paths);
449
450 snd_soc_codec_set_drvdata(codec, wm8711);
451 codec->name = "WM8711";
452 codec->owner = THIS_MODULE;
453 codec->bias_level = SND_SOC_BIAS_OFF;
454 codec->set_bias_level = wm8711_set_bias_level;
455 codec->dai = &wm8711_dai;
456 codec->num_dai = 1;
457 codec->reg_cache_size = WM8711_CACHEREGNUM;
458 codec->reg_cache = &wm8711->reg_cache;
459
460 memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg));
461 379
462 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 380 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);
463 if (ret < 0) { 381 if (ret < 0) {
464 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 382 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
465 goto err; 383 return ret;
466 } 384 }
467 385
468 ret = wm8711_reset(codec); 386 ret = wm8711_reset(codec);
469 if (ret < 0) { 387 if (ret < 0) {
470 dev_err(codec->dev, "Failed to issue reset\n"); 388 dev_err(codec->dev, "Failed to issue reset\n");
471 goto err; 389 return ret;
472 } 390 }
473 391
474 wm8711_dai.dev = codec->dev;
475
476 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 392 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
477 393
478 /* Latch the update bits */ 394 /* Latch the update bits */
@@ -481,70 +397,62 @@ static int wm8711_register(struct wm8711_priv *wm8711,
481 reg = snd_soc_read(codec, WM8711_ROUT1V); 397 reg = snd_soc_read(codec, WM8711_ROUT1V);
482 snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100); 398 snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
483 399
484 wm8711_codec = codec; 400 snd_soc_add_controls(codec, wm8711_snd_controls,
485 401 ARRAY_SIZE(wm8711_snd_controls));
486 ret = snd_soc_register_codec(codec); 402 wm8711_add_widgets(codec);
487 if (ret != 0) {
488 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
489 goto err;
490 }
491
492 ret = snd_soc_register_dai(&wm8711_dai);
493 if (ret != 0) {
494 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
495 goto err_codec;
496 }
497
498 return 0;
499 403
500err_codec:
501 snd_soc_unregister_codec(codec);
502err:
503 kfree(wm8711);
504 return ret; 404 return ret;
405
505} 406}
506 407
507static void wm8711_unregister(struct wm8711_priv *wm8711) 408/* power down chip */
409static int wm8711_remove(struct snd_soc_codec *codec)
508{ 410{
509 wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF); 411 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
510 snd_soc_unregister_dai(&wm8711_dai); 412 return 0;
511 snd_soc_unregister_codec(&wm8711->codec);
512 kfree(wm8711);
513 wm8711_codec = NULL;
514} 413}
515 414
415static struct snd_soc_codec_driver soc_codec_dev_wm8711 = {
416 .probe = wm8711_probe,
417 .remove = wm8711_remove,
418 .suspend = wm8711_suspend,
419 .resume = wm8711_resume,
420 .set_bias_level = wm8711_set_bias_level,
421 .reg_cache_size = ARRAY_SIZE(wm8711_reg),
422 .reg_word_size = sizeof(u16),
423 .reg_cache_default = wm8711_reg,
424};
425
516#if defined(CONFIG_SPI_MASTER) 426#if defined(CONFIG_SPI_MASTER)
517static int __devinit wm8711_spi_probe(struct spi_device *spi) 427static int __devinit wm8711_spi_probe(struct spi_device *spi)
518{ 428{
519 struct snd_soc_codec *codec;
520 struct wm8711_priv *wm8711; 429 struct wm8711_priv *wm8711;
430 int ret;
521 431
522 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); 432 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
523 if (wm8711 == NULL) 433 if (wm8711 == NULL)
524 return -ENOMEM; 434 return -ENOMEM;
525 435
526 codec = &wm8711->codec; 436 spi_set_drvdata(spi, wm8711);
527 codec->control_data = spi; 437 wm8711->bus_type = SND_SOC_SPI;
528 codec->dev = &spi->dev;
529 438
530 dev_set_drvdata(&spi->dev, wm8711); 439 ret = snd_soc_register_codec(&spi->dev,
531 440 &soc_codec_dev_wm8711, &wm8711_dai, 1);
532 return wm8711_register(wm8711, SND_SOC_SPI); 441 if (ret < 0)
442 kfree(wm8711);
443 return ret;
533} 444}
534 445
535static int __devexit wm8711_spi_remove(struct spi_device *spi) 446static int __devexit wm8711_spi_remove(struct spi_device *spi)
536{ 447{
537 struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev); 448 snd_soc_unregister_codec(&spi->dev);
538 449 kfree(spi_get_drvdata(spi));
539 wm8711_unregister(wm8711);
540
541 return 0; 450 return 0;
542} 451}
543 452
544static struct spi_driver wm8711_spi_driver = { 453static struct spi_driver wm8711_spi_driver = {
545 .driver = { 454 .driver = {
546 .name = "wm8711", 455 .name = "wm8711-codec",
547 .bus = &spi_bus_type,
548 .owner = THIS_MODULE, 456 .owner = THIS_MODULE,
549 }, 457 },
550 .probe = wm8711_spi_probe, 458 .probe = wm8711_spi_probe,
@@ -553,31 +461,30 @@ static struct spi_driver wm8711_spi_driver = {
553#endif /* CONFIG_SPI_MASTER */ 461#endif /* CONFIG_SPI_MASTER */
554 462
555#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 463#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
556static __devinit int wm8711_i2c_probe(struct i2c_client *i2c, 464static __devinit int wm8711_i2c_probe(struct i2c_client *client,
557 const struct i2c_device_id *id) 465 const struct i2c_device_id *id)
558{ 466{
559 struct wm8711_priv *wm8711; 467 struct wm8711_priv *wm8711;
560 struct snd_soc_codec *codec; 468 int ret;
561 469
562 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); 470 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
563 if (wm8711 == NULL) 471 if (wm8711 == NULL)
564 return -ENOMEM; 472 return -ENOMEM;
565 473
566 codec = &wm8711->codec; 474 i2c_set_clientdata(client, wm8711);
567 codec->hw_write = (hw_write_t)i2c_master_send; 475 wm8711->bus_type = SND_SOC_I2C;
568
569 i2c_set_clientdata(i2c, wm8711);
570 codec->control_data = i2c;
571 476
572 codec->dev = &i2c->dev; 477 ret = snd_soc_register_codec(&client->dev,
573 478 &soc_codec_dev_wm8711, &wm8711_dai, 1);
574 return wm8711_register(wm8711, SND_SOC_I2C); 479 if (ret < 0)
480 kfree(wm8711);
481 return ret;
575} 482}
576 483
577static __devexit int wm8711_i2c_remove(struct i2c_client *client) 484static __devexit int wm8711_i2c_remove(struct i2c_client *client)
578{ 485{
579 struct wm8711_priv *wm8711 = i2c_get_clientdata(client); 486 snd_soc_unregister_codec(&client->dev);
580 wm8711_unregister(wm8711); 487 kfree(i2c_get_clientdata(client));
581 return 0; 488 return 0;
582} 489}
583 490
@@ -589,7 +496,7 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
589 496
590static struct i2c_driver wm8711_i2c_driver = { 497static struct i2c_driver wm8711_i2c_driver = {
591 .driver = { 498 .driver = {
592 .name = "WM8711 I2C Codec", 499 .name = "wm8711-codec",
593 .owner = THIS_MODULE, 500 .owner = THIS_MODULE,
594 }, 501 },
595 .probe = wm8711_i2c_probe, 502 .probe = wm8711_i2c_probe,
diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h
index 381e84a43816..a61db985499f 100644
--- a/sound/soc/codecs/wm8711.h
+++ b/sound/soc/codecs/wm8711.h
@@ -36,7 +36,4 @@ struct wm8711_setup_data {
36 unsigned short i2c_address; 36 unsigned short i2c_address;
37}; 37};
38 38
39extern struct snd_soc_dai wm8711_dai;
40extern struct snd_soc_codec_device soc_codec_dev_wm8711;
41
42#endif 39#endif
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
index 9d1df2628136..748808285119 100644
--- a/sound/soc/codecs/wm8727.c
+++ b/sound/soc/codecs/wm8727.c
@@ -23,7 +23,6 @@
23#include <sound/initval.h> 23#include <sound/initval.h>
24#include <sound/soc.h> 24#include <sound/soc.h>
25 25
26#include "wm8727.h"
27/* 26/*
28 * Note this is a simple chip with no configuration interface, sample rate is 27 * Note this is a simple chip with no configuration interface, sample rate is
29 * determined automatically by examining the Master clock and Bit clock ratios 28 * determined automatically by examining the Master clock and Bit clock ratios
@@ -33,8 +32,8 @@
33 SNDRV_PCM_RATE_192000) 32 SNDRV_PCM_RATE_192000)
34 33
35 34
36struct snd_soc_dai wm8727_dai = { 35static struct snd_soc_dai_driver wm8727_dai = {
37 .name = "WM8727", 36 .name = "wm8727-hifi",
38 .playback = { 37 .playback = {
39 .stream_name = "Playback", 38 .stream_name = "Playback",
40 .channels_min = 2, 39 .channels_min = 2,
@@ -43,103 +42,18 @@ struct snd_soc_dai wm8727_dai = {
43 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, 42 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
44 }, 43 },
45}; 44};
46EXPORT_SYMBOL_GPL(wm8727_dai);
47 45
48static struct snd_soc_codec *wm8727_codec; 46static struct snd_soc_codec_driver soc_codec_dev_wm8727;
49 47
50static int wm8727_soc_probe(struct platform_device *pdev) 48static __devinit int wm8727_probe(struct platform_device *pdev)
51{ 49{
52 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 50 return snd_soc_register_codec(&pdev->dev,
53 int ret = 0; 51 &soc_codec_dev_wm8727, &wm8727_dai, 1);
54
55 BUG_ON(!wm8727_codec);
56
57 socdev->card->codec = wm8727_codec;
58
59 /* register pcms */
60 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
61 if (ret < 0) {
62 printk(KERN_ERR "wm8727: failed to create pcms\n");
63 goto pcm_err;
64 }
65
66 return ret;
67
68pcm_err:
69 kfree(socdev->card->codec);
70 socdev->card->codec = NULL;
71 return ret;
72}
73
74static int wm8727_soc_remove(struct platform_device *pdev)
75{
76 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
77
78 snd_soc_free_pcms(socdev);
79
80 return 0;
81}
82
83struct snd_soc_codec_device soc_codec_dev_wm8727 = {
84 .probe = wm8727_soc_probe,
85 .remove = wm8727_soc_remove,
86};
87EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727);
88
89
90static __devinit int wm8727_platform_probe(struct platform_device *pdev)
91{
92 struct snd_soc_codec *codec;
93 int ret;
94
95 if (wm8727_codec) {
96 dev_err(&pdev->dev, "Another WM8727 is registered\n");
97 return -EBUSY;
98 }
99
100 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
101 if (codec == NULL)
102 return -ENOMEM;
103 wm8727_codec = codec;
104
105 platform_set_drvdata(pdev, codec);
106
107 mutex_init(&codec->mutex);
108 codec->dev = &pdev->dev;
109 codec->name = "WM8727";
110 codec->owner = THIS_MODULE;
111 codec->dai = &wm8727_dai;
112 codec->num_dai = 1;
113 INIT_LIST_HEAD(&codec->dapm_widgets);
114 INIT_LIST_HEAD(&codec->dapm_paths);
115
116 wm8727_dai.dev = &pdev->dev;
117
118 ret = snd_soc_register_codec(codec);
119 if (ret != 0) {
120 dev_err(&pdev->dev, "Failed to register CODEC: %d\n", ret);
121 goto err;
122 }
123
124 ret = snd_soc_register_dai(&wm8727_dai);
125 if (ret != 0) {
126 dev_err(&pdev->dev, "Failed to register DAI: %d\n", ret);
127 goto err_codec;
128 }
129
130 return 0;
131
132err_codec:
133 snd_soc_unregister_codec(codec);
134err:
135 kfree(codec);
136 return ret;
137} 52}
138 53
139static int __devexit wm8727_platform_remove(struct platform_device *pdev) 54static int __devexit wm8727_remove(struct platform_device *pdev)
140{ 55{
141 snd_soc_unregister_dai(&wm8727_dai); 56 snd_soc_unregister_codec(&pdev->dev);
142 snd_soc_unregister_codec(platform_get_drvdata(pdev));
143 return 0; 57 return 0;
144} 58}
145 59
@@ -149,8 +63,8 @@ static struct platform_driver wm8727_codec_driver = {
149 .owner = THIS_MODULE, 63 .owner = THIS_MODULE,
150 }, 64 },
151 65
152 .probe = wm8727_platform_probe, 66 .probe = wm8727_probe,
153 .remove = __devexit_p(wm8727_platform_remove), 67 .remove = __devexit_p(wm8727_remove),
154}; 68};
155 69
156static int __init wm8727_init(void) 70static int __init wm8727_init(void)
diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h
deleted file mode 100644
index ee19aa71bcdc..000000000000
--- a/sound/soc/codecs/wm8727.h
+++ /dev/null
@@ -1,21 +0,0 @@
1/*
2 * wm8727.h
3 *
4 * Created on: 15-Oct-2009
5 * Author: neil.jones@imgtec.com
6 *
7 * Copyright (C) 2009 Imagination Technologies Ltd.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#ifndef WM8727_H_
16#define WM8727_H_
17
18extern struct snd_soc_dai wm8727_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8727;
20
21#endif /* WM8727_H_ */
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 34be2d2b69ef..075f35e4f4cb 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -29,8 +29,6 @@
29 29
30#include "wm8728.h" 30#include "wm8728.h"
31 31
32struct snd_soc_codec_device soc_codec_dev_wm8728;
33
34/* 32/*
35 * We can't read the WM8728 register space so we cache them instead. 33 * We can't read the WM8728 register space so we cache them instead.
36 * Note that the defaults here aren't the physical defaults, we latch 34 * Note that the defaults here aren't the physical defaults, we latch
@@ -44,6 +42,11 @@ static const u16 wm8728_reg_defaults[] = {
44 0x100, 42 0x100,
45}; 43};
46 44
45/* codec private data */
46struct wm8728_priv {
47 enum snd_soc_control_type control_type;
48};
49
47static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); 50static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
48 51
49static const struct snd_kcontrol_new wm8728_snd_controls[] = { 52static const struct snd_kcontrol_new wm8728_snd_controls[] = {
@@ -96,8 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
96 struct snd_soc_dai *dai) 99 struct snd_soc_dai *dai)
97{ 100{
98 struct snd_soc_pcm_runtime *rtd = substream->private_data; 101 struct snd_soc_pcm_runtime *rtd = substream->private_data;
99 struct snd_soc_device *socdev = rtd->socdev; 102 struct snd_soc_codec *codec = rtd->codec;
100 struct snd_soc_codec *codec = socdev->card->codec;
101 u16 dac = snd_soc_read(codec, WM8728_DACCTL); 103 u16 dac = snd_soc_read(codec, WM8728_DACCTL);
102 104
103 dac &= ~0x18; 105 dac &= ~0x18;
@@ -210,8 +212,8 @@ static struct snd_soc_dai_ops wm8728_dai_ops = {
210 .set_fmt = wm8728_set_dai_fmt, 212 .set_fmt = wm8728_set_dai_fmt,
211}; 213};
212 214
213struct snd_soc_dai wm8728_dai = { 215static struct snd_soc_dai_driver wm8728_dai = {
214 .name = "WM8728", 216 .name = "wm8728-hifi",
215 .playback = { 217 .playback = {
216 .stream_name = "Playback", 218 .stream_name = "Playback",
217 .channels_min = 2, 219 .channels_min = 2,
@@ -221,63 +223,31 @@ struct snd_soc_dai wm8728_dai = {
221 }, 223 },
222 .ops = &wm8728_dai_ops, 224 .ops = &wm8728_dai_ops,
223}; 225};
224EXPORT_SYMBOL_GPL(wm8728_dai);
225 226
226static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) 227static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state)
227{ 228{
228 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
229 struct snd_soc_codec *codec = socdev->card->codec;
230
231 wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); 229 wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
232 230
233 return 0; 231 return 0;
234} 232}
235 233
236static int wm8728_resume(struct platform_device *pdev) 234static int wm8728_resume(struct snd_soc_codec *codec)
237{ 235{
238 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
239 struct snd_soc_codec *codec = socdev->card->codec;
240
241 wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 236 wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
242 237
243 return 0; 238 return 0;
244} 239}
245 240
246/* 241static int wm8728_probe(struct snd_soc_codec *codec)
247 * initialise the WM8728 driver
248 * register the mixer and dsp interfaces with the kernel
249 */
250static int wm8728_init(struct snd_soc_device *socdev,
251 enum snd_soc_control_type control)
252{ 242{
253 struct snd_soc_codec *codec = socdev->card->codec; 243 struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec);
254 int ret = 0; 244 int ret;
255
256 codec->name = "WM8728";
257 codec->owner = THIS_MODULE;
258 codec->set_bias_level = wm8728_set_bias_level;
259 codec->dai = &wm8728_dai;
260 codec->num_dai = 1;
261 codec->bias_level = SND_SOC_BIAS_OFF;
262 codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults);
263 codec->reg_cache = kmemdup(wm8728_reg_defaults,
264 sizeof(wm8728_reg_defaults),
265 GFP_KERNEL);
266 if (codec->reg_cache == NULL)
267 return -ENOMEM;
268 245
269 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 246 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type);
270 if (ret < 0) { 247 if (ret < 0) {
271 printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", 248 printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
272 ret); 249 ret);
273 goto err; 250 return ret;
274 }
275
276 /* register pcms */
277 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
278 if (ret < 0) {
279 printk(KERN_ERR "wm8728: failed to create pcms\n");
280 goto err;
281 } 251 }
282 252
283 /* power on device */ 253 /* power on device */
@@ -288,215 +258,136 @@ static int wm8728_init(struct snd_soc_device *socdev,
288 wm8728_add_widgets(codec); 258 wm8728_add_widgets(codec);
289 259
290 return ret; 260 return ret;
291
292err:
293 kfree(codec->reg_cache);
294 return ret;
295} 261}
296 262
297static struct snd_soc_device *wm8728_socdev; 263static int wm8728_remove(struct snd_soc_codec *codec)
298 264{
299#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 265 wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
266 return 0;
267}
300 268
301/* 269static struct snd_soc_codec_driver soc_codec_dev_wm8728 = {
302 * WM8728 2 wire address is determined by GPIO5 270 .probe = wm8728_probe,
303 * state during powerup. 271 .remove = wm8728_remove,
304 * low = 0x1a 272 .suspend = wm8728_suspend,
305 * high = 0x1b 273 .resume = wm8728_resume,
306 */ 274 .set_bias_level = wm8728_set_bias_level,
275 .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults),
276 .reg_word_size = sizeof(u16),
277 .reg_cache_default = wm8728_reg_defaults,
278};
307 279
308static int wm8728_i2c_probe(struct i2c_client *i2c, 280#if defined(CONFIG_SPI_MASTER)
309 const struct i2c_device_id *id) 281static int __devinit wm8728_spi_probe(struct spi_device *spi)
310{ 282{
311 struct snd_soc_device *socdev = wm8728_socdev; 283 struct wm8728_priv *wm8728;
312 struct snd_soc_codec *codec = socdev->card->codec;
313 int ret; 284 int ret;
314 285
315 i2c_set_clientdata(i2c, codec); 286 wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL);
316 codec->control_data = i2c; 287 if (wm8728 == NULL)
288 return -ENOMEM;
289
290 wm8728->control_type = SND_SOC_SPI;
291 spi_set_drvdata(spi, wm8728);
317 292
318 ret = wm8728_init(socdev, SND_SOC_I2C); 293 ret = snd_soc_register_codec(&spi->dev,
294 &soc_codec_dev_wm8728, &wm8728_dai, 1);
319 if (ret < 0) 295 if (ret < 0)
320 pr_err("failed to initialise WM8728\n"); 296 kfree(wm8728);
321
322 return ret; 297 return ret;
323} 298}
324 299
325static int wm8728_i2c_remove(struct i2c_client *client) 300static int __devexit wm8728_spi_remove(struct spi_device *spi)
326{ 301{
327 struct snd_soc_codec *codec = i2c_get_clientdata(client); 302 snd_soc_unregister_codec(&spi->dev);
328 kfree(codec->reg_cache); 303 kfree(spi_get_drvdata(spi));
329 return 0; 304 return 0;
330} 305}
331 306
332static const struct i2c_device_id wm8728_i2c_id[] = { 307static struct spi_driver wm8728_spi_driver = {
333 { "wm8728", 0 },
334 { }
335};
336MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
337
338static struct i2c_driver wm8728_i2c_driver = {
339 .driver = { 308 .driver = {
340 .name = "WM8728 I2C Codec", 309 .name = "wm8728-codec",
341 .owner = THIS_MODULE, 310 .owner = THIS_MODULE,
342 }, 311 },
343 .probe = wm8728_i2c_probe, 312 .probe = wm8728_spi_probe,
344 .remove = wm8728_i2c_remove, 313 .remove = __devexit_p(wm8728_spi_remove),
345 .id_table = wm8728_i2c_id,
346}; 314};
315#endif /* CONFIG_SPI_MASTER */
347 316
348static int wm8728_add_i2c_device(struct platform_device *pdev, 317#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
349 const struct wm8728_setup_data *setup) 318static __devinit int wm8728_i2c_probe(struct i2c_client *i2c,
319 const struct i2c_device_id *id)
350{ 320{
351 struct i2c_board_info info; 321 struct wm8728_priv *wm8728;
352 struct i2c_adapter *adapter;
353 struct i2c_client *client;
354 int ret; 322 int ret;
355 323
356 ret = i2c_add_driver(&wm8728_i2c_driver); 324 wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL);
357 if (ret != 0) { 325 if (wm8728 == NULL)
358 dev_err(&pdev->dev, "can't add i2c driver\n"); 326 return -ENOMEM;
359 return ret;
360 }
361
362 memset(&info, 0, sizeof(struct i2c_board_info));
363 info.addr = setup->i2c_address;
364 strlcpy(info.type, "wm8728", I2C_NAME_SIZE);
365
366 adapter = i2c_get_adapter(setup->i2c_bus);
367 if (!adapter) {
368 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
369 setup->i2c_bus);
370 goto err_driver;
371 }
372
373 client = i2c_new_device(adapter, &info);
374 i2c_put_adapter(adapter);
375 if (!client) {
376 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
377 (unsigned int)info.addr);
378 goto err_driver;
379 }
380
381 return 0;
382
383err_driver:
384 i2c_del_driver(&wm8728_i2c_driver);
385 return -ENODEV;
386}
387#endif
388
389#if defined(CONFIG_SPI_MASTER)
390static int __devinit wm8728_spi_probe(struct spi_device *spi)
391{
392 struct snd_soc_device *socdev = wm8728_socdev;
393 struct snd_soc_codec *codec = socdev->card->codec;
394 int ret;
395 327
396 codec->control_data = spi; 328 i2c_set_clientdata(i2c, wm8728);
329 wm8728->control_type = SND_SOC_I2C;
397 330
398 ret = wm8728_init(socdev, SND_SOC_SPI); 331 ret = snd_soc_register_codec(&i2c->dev,
332 &soc_codec_dev_wm8728, &wm8728_dai, 1);
399 if (ret < 0) 333 if (ret < 0)
400 dev_err(&spi->dev, "failed to initialise WM8728\n"); 334 kfree(wm8728);
401
402 return ret; 335 return ret;
403} 336}
404 337
405static int __devexit wm8728_spi_remove(struct spi_device *spi) 338static __devexit int wm8728_i2c_remove(struct i2c_client *client)
406{ 339{
340 snd_soc_unregister_codec(&client->dev);
341 kfree(i2c_get_clientdata(client));
407 return 0; 342 return 0;
408} 343}
409 344
410static struct spi_driver wm8728_spi_driver = { 345static const struct i2c_device_id wm8728_i2c_id[] = {
346 { "wm8728", 0 },
347 { }
348};
349MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
350
351static struct i2c_driver wm8728_i2c_driver = {
411 .driver = { 352 .driver = {
412 .name = "wm8728", 353 .name = "wm8728-codec",
413 .bus = &spi_bus_type, 354 .owner = THIS_MODULE,
414 .owner = THIS_MODULE,
415 }, 355 },
416 .probe = wm8728_spi_probe, 356 .probe = wm8728_i2c_probe,
417 .remove = __devexit_p(wm8728_spi_remove), 357 .remove = __devexit_p(wm8728_i2c_remove),
358 .id_table = wm8728_i2c_id,
418}; 359};
419#endif /* CONFIG_SPI_MASTER */ 360#endif
420 361
421static int wm8728_probe(struct platform_device *pdev) 362static int __init wm8728_modinit(void)
422{ 363{
423 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
424 struct wm8728_setup_data *setup;
425 struct snd_soc_codec *codec;
426 int ret = 0; 364 int ret = 0;
427
428 setup = socdev->codec_data;
429 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
430 if (codec == NULL)
431 return -ENOMEM;
432
433 socdev->card->codec = codec;
434 mutex_init(&codec->mutex);
435 INIT_LIST_HEAD(&codec->dapm_widgets);
436 INIT_LIST_HEAD(&codec->dapm_paths);
437
438 wm8728_socdev = socdev;
439 ret = -ENODEV;
440
441#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 365#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
442 if (setup->i2c_address) { 366 ret = i2c_add_driver(&wm8728_i2c_driver);
443 ret = wm8728_add_i2c_device(pdev, setup); 367 if (ret != 0) {
368 printk(KERN_ERR "Failed to register wm8728 I2C driver: %d\n",
369 ret);
444 } 370 }
445#endif 371#endif
446#if defined(CONFIG_SPI_MASTER) 372#if defined(CONFIG_SPI_MASTER)
447 if (setup->spi) { 373 ret = spi_register_driver(&wm8728_spi_driver);
448 ret = spi_register_driver(&wm8728_spi_driver); 374 if (ret != 0) {
449 if (ret != 0) 375 printk(KERN_ERR "Failed to register wm8728 SPI driver: %d\n",
450 printk(KERN_ERR "can't add spi driver"); 376 ret);
451 } 377 }
452#endif 378#endif
453
454 if (ret != 0)
455 kfree(codec);
456
457 return ret; 379 return ret;
458} 380}
381module_init(wm8728_modinit);
459 382
460/* power down chip */ 383static void __exit wm8728_exit(void)
461static int wm8728_remove(struct platform_device *pdev)
462{ 384{
463 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
464 struct snd_soc_codec *codec = socdev->card->codec;
465
466 if (codec->control_data)
467 wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
468
469 snd_soc_free_pcms(socdev);
470 snd_soc_dapm_free(socdev);
471#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 385#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
472 i2c_unregister_device(codec->control_data);
473 i2c_del_driver(&wm8728_i2c_driver); 386 i2c_del_driver(&wm8728_i2c_driver);
474#endif 387#endif
475#if defined(CONFIG_SPI_MASTER) 388#if defined(CONFIG_SPI_MASTER)
476 spi_unregister_driver(&wm8728_spi_driver); 389 spi_unregister_driver(&wm8728_spi_driver);
477#endif 390#endif
478 kfree(codec);
479
480 return 0;
481}
482
483struct snd_soc_codec_device soc_codec_dev_wm8728 = {
484 .probe = wm8728_probe,
485 .remove = wm8728_remove,
486 .suspend = wm8728_suspend,
487 .resume = wm8728_resume,
488};
489EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728);
490
491static int __init wm8728_modinit(void)
492{
493 return snd_soc_register_dai(&wm8728_dai);
494}
495module_init(wm8728_modinit);
496
497static void __exit wm8728_exit(void)
498{
499 snd_soc_unregister_dai(&wm8728_dai);
500} 391}
501module_exit(wm8728_exit); 392module_exit(wm8728_exit);
502 393
diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h
index d269c132474b..8aea362ffd47 100644
--- a/sound/soc/codecs/wm8728.h
+++ b/sound/soc/codecs/wm8728.h
@@ -18,13 +18,4 @@
18#define WM8728_DACCTL 0x02 18#define WM8728_DACCTL 0x02
19#define WM8728_IFCTL 0x03 19#define WM8728_IFCTL 0x03
20 20
21struct wm8728_setup_data {
22 int spi;
23 int i2c_bus;
24 unsigned short i2c_address;
25};
26
27extern struct snd_soc_dai wm8728_dai;
28extern struct snd_soc_codec_device soc_codec_dev_wm8728;
29
30#endif 21#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 0ab9b6355297..631385802eb4 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -32,9 +32,6 @@
32 32
33#include "wm8731.h" 33#include "wm8731.h"
34 34
35static struct snd_soc_codec *wm8731_codec;
36struct snd_soc_codec_device soc_codec_dev_wm8731;
37
38#define WM8731_NUM_SUPPLIES 4 35#define WM8731_NUM_SUPPLIES 4
39static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = { 36static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
40 "AVDD", 37 "AVDD",
@@ -45,10 +42,11 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
45 42
46/* codec private data */ 43/* codec private data */
47struct wm8731_priv { 44struct wm8731_priv {
48 struct snd_soc_codec codec; 45 enum snd_soc_control_type control_type;
49 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES]; 46 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
50 u16 reg_cache[WM8731_CACHEREGNUM]; 47 u16 reg_cache[WM8731_CACHEREGNUM];
51 unsigned int sysclk; 48 unsigned int sysclk;
49 int sysclk_type;
52}; 50};
53 51
54 52
@@ -113,6 +111,7 @@ static const struct snd_kcontrol_new wm8731_input_mux_controls =
113SOC_DAPM_ENUM("Input Select", wm8731_enum[0]); 111SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
114 112
115static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = { 113static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
114SND_SOC_DAPM_SUPPLY("OSC", WM8731_PWR, 5, 1, NULL, 0),
116SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, 115SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
117 &wm8731_output_mixer_controls[0], 116 &wm8731_output_mixer_controls[0],
118 ARRAY_SIZE(wm8731_output_mixer_controls)), 117 ARRAY_SIZE(wm8731_output_mixer_controls)),
@@ -130,7 +129,18 @@ SND_SOC_DAPM_INPUT("RLINEIN"),
130SND_SOC_DAPM_INPUT("LLINEIN"), 129SND_SOC_DAPM_INPUT("LLINEIN"),
131}; 130};
132 131
132static int wm8731_check_osc(struct snd_soc_dapm_widget *source,
133 struct snd_soc_dapm_widget *sink)
134{
135 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(source->codec);
136
137 return wm8731->sysclk_type == WM8731_SYSCLK_MCLK;
138}
139
133static const struct snd_soc_dapm_route intercon[] = { 140static const struct snd_soc_dapm_route intercon[] = {
141 {"DAC", NULL, "OSC", wm8731_check_osc},
142 {"ADC", NULL, "OSC", wm8731_check_osc},
143
134 /* output mixer */ 144 /* output mixer */
135 {"Output Mixer", "Line Bypass Switch", "Line Input"}, 145 {"Output Mixer", "Line Bypass Switch", "Line Input"},
136 {"Output Mixer", "HiFi Playback Switch", "DAC"}, 146 {"Output Mixer", "HiFi Playback Switch", "DAC"},
@@ -222,9 +232,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
222 struct snd_pcm_hw_params *params, 232 struct snd_pcm_hw_params *params,
223 struct snd_soc_dai *dai) 233 struct snd_soc_dai *dai)
224{ 234{
225 struct snd_soc_pcm_runtime *rtd = substream->private_data; 235 struct snd_soc_codec *codec = dai->codec;
226 struct snd_soc_device *socdev = rtd->socdev;
227 struct snd_soc_codec *codec = socdev->card->codec;
228 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); 236 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
229 u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; 237 u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
230 int i = get_coeff(wm8731->sysclk, params_rate(params)); 238 int i = get_coeff(wm8731->sysclk, params_rate(params));
@@ -252,9 +260,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
252static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, 260static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
253 struct snd_soc_dai *dai) 261 struct snd_soc_dai *dai)
254{ 262{
255 struct snd_soc_pcm_runtime *rtd = substream->private_data; 263 struct snd_soc_codec *codec = dai->codec;
256 struct snd_soc_device *socdev = rtd->socdev;
257 struct snd_soc_codec *codec = socdev->card->codec;
258 264
259 /* set active */ 265 /* set active */
260 snd_soc_write(codec, WM8731_ACTIVE, 0x0001); 266 snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
@@ -265,9 +271,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
265static void wm8731_shutdown(struct snd_pcm_substream *substream, 271static void wm8731_shutdown(struct snd_pcm_substream *substream,
266 struct snd_soc_dai *dai) 272 struct snd_soc_dai *dai)
267{ 273{
268 struct snd_soc_pcm_runtime *rtd = substream->private_data; 274 struct snd_soc_codec *codec = dai->codec;
269 struct snd_soc_device *socdev = rtd->socdev;
270 struct snd_soc_codec *codec = socdev->card->codec;
271 275
272 /* deactivate */ 276 /* deactivate */
273 if (!codec->active) { 277 if (!codec->active) {
@@ -294,6 +298,15 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
294 struct snd_soc_codec *codec = codec_dai->codec; 298 struct snd_soc_codec *codec = codec_dai->codec;
295 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); 299 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
296 300
301 switch (clk_id) {
302 case WM8731_SYSCLK_XTAL:
303 case WM8731_SYSCLK_MCLK:
304 wm8731->sysclk_type = clk_id;
305 break;
306 default:
307 return -EINVAL;
308 }
309
297 switch (freq) { 310 switch (freq) {
298 case 11289600: 311 case 11289600:
299 case 12000000: 312 case 12000000:
@@ -301,9 +314,14 @@ static int wm8731_set_dai_sysclk(struct snd_soc_dai *codec_dai,
301 case 16934400: 314 case 16934400:
302 case 18432000: 315 case 18432000:
303 wm8731->sysclk = freq; 316 wm8731->sysclk = freq;
304 return 0; 317 break;
318 default:
319 return -EINVAL;
305 } 320 }
306 return -EINVAL; 321
322 snd_soc_dapm_sync(codec);
323
324 return 0;
307} 325}
308 326
309 327
@@ -428,8 +446,8 @@ static struct snd_soc_dai_ops wm8731_dai_ops = {
428 .set_fmt = wm8731_set_dai_fmt, 446 .set_fmt = wm8731_set_dai_fmt,
429}; 447};
430 448
431struct snd_soc_dai wm8731_dai = { 449static struct snd_soc_dai_driver wm8731_dai = {
432 .name = "WM8731", 450 .name = "wm8731-hifi",
433 .playback = { 451 .playback = {
434 .stream_name = "Playback", 452 .stream_name = "Playback",
435 .channels_min = 1, 453 .channels_min = 1,
@@ -445,24 +463,17 @@ struct snd_soc_dai wm8731_dai = {
445 .ops = &wm8731_dai_ops, 463 .ops = &wm8731_dai_ops,
446 .symmetric_rates = 1, 464 .symmetric_rates = 1,
447}; 465};
448EXPORT_SYMBOL_GPL(wm8731_dai);
449 466
450#ifdef CONFIG_PM 467#ifdef CONFIG_PM
451static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) 468static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state)
452{ 469{
453 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
454 struct snd_soc_codec *codec = socdev->card->codec;
455
456 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 470 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
457 471
458 return 0; 472 return 0;
459} 473}
460 474
461static int wm8731_resume(struct platform_device *pdev) 475static int wm8731_resume(struct snd_soc_codec *codec)
462{ 476{
463 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
464 struct snd_soc_codec *codec = socdev->card->codec;
465
466 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 477 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
467 478
468 return 0; 479 return 0;
@@ -472,88 +483,15 @@ static int wm8731_resume(struct platform_device *pdev)
472#define wm8731_resume NULL 483#define wm8731_resume NULL
473#endif 484#endif
474 485
475static int wm8731_probe(struct platform_device *pdev) 486static int wm8731_probe(struct snd_soc_codec *codec)
476{ 487{
477 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 488 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
478 struct snd_soc_codec *codec; 489 int ret = 0, i;
479 int ret = 0;
480
481 if (wm8731_codec == NULL) {
482 dev_err(&pdev->dev, "Codec device not registered\n");
483 return -ENODEV;
484 }
485
486 socdev->card->codec = wm8731_codec;
487 codec = wm8731_codec;
488
489 /* register pcms */
490 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
491 if (ret < 0) {
492 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
493 goto pcm_err;
494 }
495
496 snd_soc_add_controls(codec, wm8731_snd_controls,
497 ARRAY_SIZE(wm8731_snd_controls));
498 wm8731_add_widgets(codec);
499
500 return ret;
501
502pcm_err:
503 return ret;
504}
505
506/* power down chip */
507static int wm8731_remove(struct platform_device *pdev)
508{
509 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
510
511 snd_soc_free_pcms(socdev);
512 snd_soc_dapm_free(socdev);
513
514 return 0;
515}
516
517struct snd_soc_codec_device soc_codec_dev_wm8731 = {
518 .probe = wm8731_probe,
519 .remove = wm8731_remove,
520 .suspend = wm8731_suspend,
521 .resume = wm8731_resume,
522};
523EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
524
525static int wm8731_register(struct wm8731_priv *wm8731,
526 enum snd_soc_control_type control)
527{
528 int ret, i;
529 struct snd_soc_codec *codec = &wm8731->codec;
530
531 if (wm8731_codec) {
532 dev_err(codec->dev, "Another WM8731 is registered\n");
533 ret = -EINVAL;
534 goto err;
535 }
536
537 mutex_init(&codec->mutex);
538 INIT_LIST_HEAD(&codec->dapm_widgets);
539 INIT_LIST_HEAD(&codec->dapm_paths);
540
541 snd_soc_codec_set_drvdata(codec, wm8731);
542 codec->name = "WM8731";
543 codec->owner = THIS_MODULE;
544 codec->bias_level = SND_SOC_BIAS_OFF;
545 codec->set_bias_level = wm8731_set_bias_level;
546 codec->dai = &wm8731_dai;
547 codec->num_dai = 1;
548 codec->reg_cache_size = WM8731_CACHEREGNUM;
549 codec->reg_cache = &wm8731->reg_cache;
550
551 memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
552 490
553 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 491 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);
554 if (ret < 0) { 492 if (ret < 0) {
555 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 493 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
556 goto err; 494 return ret;
557 } 495 }
558 496
559 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) 497 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
@@ -563,7 +501,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
563 wm8731->supplies); 501 wm8731->supplies);
564 if (ret != 0) { 502 if (ret != 0) {
565 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 503 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
566 goto err; 504 return ret;
567 } 505 }
568 506
569 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), 507 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
@@ -579,8 +517,6 @@ static int wm8731_register(struct wm8731_priv *wm8731,
579 goto err_regulator_enable; 517 goto err_regulator_enable;
580 } 518 }
581 519
582 wm8731_dai.dev = codec->dev;
583
584 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 520 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
585 521
586 /* Latch the update bits */ 522 /* Latch the update bits */
@@ -592,79 +528,78 @@ static int wm8731_register(struct wm8731_priv *wm8731,
592 /* Disable bypass path by default */ 528 /* Disable bypass path by default */
593 snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); 529 snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
594 530
595 wm8731_codec = codec; 531 snd_soc_add_controls(codec, wm8731_snd_controls,
596 532 ARRAY_SIZE(wm8731_snd_controls));
597 ret = snd_soc_register_codec(codec); 533 wm8731_add_widgets(codec);
598 if (ret != 0) {
599 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
600 goto err_regulator_enable;
601 }
602
603 ret = snd_soc_register_dai(&wm8731_dai);
604 if (ret != 0) {
605 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
606 snd_soc_unregister_codec(codec);
607 goto err_codec;
608 }
609 534
610 /* Regulators will have been enabled by bias management */ 535 /* Regulators will have been enabled by bias management */
611 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 536 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
612 537
613 return 0; 538 return 0;
614 539
615err_codec:
616 snd_soc_unregister_codec(codec);
617err_regulator_enable: 540err_regulator_enable:
618 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 541 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
619err_regulator_get: 542err_regulator_get:
620 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 543 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
621err: 544
622 kfree(wm8731); 545 kfree(wm8731);
623 return ret; 546 return ret;
624} 547}
625 548
626static void wm8731_unregister(struct wm8731_priv *wm8731) 549/* power down chip */
550static int wm8731_remove(struct snd_soc_codec *codec)
627{ 551{
628 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); 552 struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
629 snd_soc_unregister_dai(&wm8731_dai); 553
630 snd_soc_unregister_codec(&wm8731->codec); 554 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
555
556 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
631 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); 557 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
632 kfree(wm8731); 558
633 wm8731_codec = NULL; 559 return 0;
634} 560}
635 561
562static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
563 .probe = wm8731_probe,
564 .remove = wm8731_remove,
565 .suspend = wm8731_suspend,
566 .resume = wm8731_resume,
567 .set_bias_level = wm8731_set_bias_level,
568 .reg_cache_size = ARRAY_SIZE(wm8731_reg),
569 .reg_word_size = sizeof(u16),
570 .reg_cache_default = wm8731_reg,
571};
572
636#if defined(CONFIG_SPI_MASTER) 573#if defined(CONFIG_SPI_MASTER)
637static int __devinit wm8731_spi_probe(struct spi_device *spi) 574static int __devinit wm8731_spi_probe(struct spi_device *spi)
638{ 575{
639 struct snd_soc_codec *codec;
640 struct wm8731_priv *wm8731; 576 struct wm8731_priv *wm8731;
577 int ret;
641 578
642 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); 579 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
643 if (wm8731 == NULL) 580 if (wm8731 == NULL)
644 return -ENOMEM; 581 return -ENOMEM;
645 582
646 codec = &wm8731->codec; 583 wm8731->control_type = SND_SOC_SPI;
647 codec->control_data = spi; 584 spi_set_drvdata(spi, wm8731);
648 codec->dev = &spi->dev;
649
650 dev_set_drvdata(&spi->dev, wm8731);
651 585
652 return wm8731_register(wm8731, SND_SOC_SPI); 586 ret = snd_soc_register_codec(&spi->dev,
587 &soc_codec_dev_wm8731, &wm8731_dai, 1);
588 if (ret < 0)
589 kfree(wm8731);
590 return ret;
653} 591}
654 592
655static int __devexit wm8731_spi_remove(struct spi_device *spi) 593static int __devexit wm8731_spi_remove(struct spi_device *spi)
656{ 594{
657 struct wm8731_priv *wm8731 = dev_get_drvdata(&spi->dev); 595 snd_soc_unregister_codec(&spi->dev);
658 596 kfree(spi_get_drvdata(spi));
659 wm8731_unregister(wm8731);
660
661 return 0; 597 return 0;
662} 598}
663 599
664static struct spi_driver wm8731_spi_driver = { 600static struct spi_driver wm8731_spi_driver = {
665 .driver = { 601 .driver = {
666 .name = "wm8731", 602 .name = "wm8731-codec",
667 .bus = &spi_bus_type,
668 .owner = THIS_MODULE, 603 .owner = THIS_MODULE,
669 }, 604 },
670 .probe = wm8731_spi_probe, 605 .probe = wm8731_spi_probe,
@@ -677,26 +612,26 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
677 const struct i2c_device_id *id) 612 const struct i2c_device_id *id)
678{ 613{
679 struct wm8731_priv *wm8731; 614 struct wm8731_priv *wm8731;
680 struct snd_soc_codec *codec; 615 int ret;
681 616
682 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL); 617 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
683 if (wm8731 == NULL) 618 if (wm8731 == NULL)
684 return -ENOMEM; 619 return -ENOMEM;
685 620
686 codec = &wm8731->codec;
687
688 i2c_set_clientdata(i2c, wm8731); 621 i2c_set_clientdata(i2c, wm8731);
689 codec->control_data = i2c; 622 wm8731->control_type = SND_SOC_I2C;
690
691 codec->dev = &i2c->dev;
692 623
693 return wm8731_register(wm8731, SND_SOC_I2C); 624 ret = snd_soc_register_codec(&i2c->dev,
625 &soc_codec_dev_wm8731, &wm8731_dai, 1);
626 if (ret < 0)
627 kfree(wm8731);
628 return ret;
694} 629}
695 630
696static __devexit int wm8731_i2c_remove(struct i2c_client *client) 631static __devexit int wm8731_i2c_remove(struct i2c_client *client)
697{ 632{
698 struct wm8731_priv *wm8731 = i2c_get_clientdata(client); 633 snd_soc_unregister_codec(&client->dev);
699 wm8731_unregister(wm8731); 634 kfree(i2c_get_clientdata(client));
700 return 0; 635 return 0;
701} 636}
702 637
@@ -708,7 +643,7 @@ MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
708 643
709static struct i2c_driver wm8731_i2c_driver = { 644static struct i2c_driver wm8731_i2c_driver = {
710 .driver = { 645 .driver = {
711 .name = "wm8731", 646 .name = "wm8731-codec",
712 .owner = THIS_MODULE, 647 .owner = THIS_MODULE,
713 }, 648 },
714 .probe = wm8731_i2c_probe, 649 .probe = wm8731_i2c_probe,
@@ -719,7 +654,7 @@ static struct i2c_driver wm8731_i2c_driver = {
719 654
720static int __init wm8731_modinit(void) 655static int __init wm8731_modinit(void)
721{ 656{
722 int ret; 657 int ret = 0;
723#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 658#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
724 ret = i2c_add_driver(&wm8731_i2c_driver); 659 ret = i2c_add_driver(&wm8731_i2c_driver);
725 if (ret != 0) { 660 if (ret != 0) {
@@ -734,7 +669,7 @@ static int __init wm8731_modinit(void)
734 ret); 669 ret);
735 } 670 }
736#endif 671#endif
737 return 0; 672 return ret;
738} 673}
739module_init(wm8731_modinit); 674module_init(wm8731_modinit);
740 675
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h
index cd7b806e8ad0..e9c0c76ab73b 100644
--- a/sound/soc/codecs/wm8731.h
+++ b/sound/soc/codecs/wm8731.h
@@ -31,10 +31,9 @@
31 31
32#define WM8731_CACHEREGNUM 10 32#define WM8731_CACHEREGNUM 10
33 33
34#define WM8731_SYSCLK 0 34#define WM8731_SYSCLK_XTAL 1
35#define WM8731_DAI 0 35#define WM8731_SYSCLK_MCLK 2
36 36
37extern struct snd_soc_dai wm8731_dai; 37#define WM8731_DAI 0
38extern struct snd_soc_codec_device soc_codec_dev_wm8731;
39 38
40#endif 39#endif
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index b9ea8904ad4b..90e31e9aa6f7 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -30,25 +30,21 @@
30 30
31#include "wm8741.h" 31#include "wm8741.h"
32 32
33static struct snd_soc_codec *wm8741_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8741;
35
36#define WM8741_NUM_SUPPLIES 2 33#define WM8741_NUM_SUPPLIES 2
37static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { 34static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
38 "AVDD", 35 "AVDD",
39 "DVDD", 36 "DVDD",
40}; 37};
41 38
42#define WM8741_NUM_RATES 4 39#define WM8741_NUM_RATES 6
43 40
44/* codec private data */ 41/* codec private data */
45struct wm8741_priv { 42struct wm8741_priv {
46 struct snd_soc_codec codec; 43 enum snd_soc_control_type control_type;
47 u16 reg_cache[WM8741_REGISTER_COUNT]; 44 u16 reg_cache[WM8741_REGISTER_COUNT];
48 struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; 45 struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
49 unsigned int sysclk; 46 unsigned int sysclk;
50 unsigned int rate_constraint_list[WM8741_NUM_RATES]; 47 struct snd_pcm_hw_constraint_list *sysclk_constraints;
51 struct snd_pcm_hw_constraint_list rate_constraint;
52}; 48};
53 49
54static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = { 50static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = {
@@ -111,10 +107,84 @@ static struct {
111 int value; 107 int value;
112 int ratio; 108 int ratio;
113} lrclk_ratios[WM8741_NUM_RATES] = { 109} lrclk_ratios[WM8741_NUM_RATES] = {
114 { 1, 256 }, 110 { 1, 128 },
115 { 2, 384 }, 111 { 2, 192 },
116 { 3, 512 }, 112 { 3, 256 },
117 { 4, 768 }, 113 { 4, 384 },
114 { 5, 512 },
115 { 6, 768 },
116};
117
118static unsigned int rates_11289[] = {
119 44100, 88235,
120};
121
122static struct snd_pcm_hw_constraint_list constraints_11289 = {
123 .count = ARRAY_SIZE(rates_11289),
124 .list = rates_11289,
125};
126
127static unsigned int rates_12288[] = {
128 32000, 48000, 96000,
129};
130
131static struct snd_pcm_hw_constraint_list constraints_12288 = {
132 .count = ARRAY_SIZE(rates_12288),
133 .list = rates_12288,
134};
135
136static unsigned int rates_16384[] = {
137 32000,
138};
139
140static struct snd_pcm_hw_constraint_list constraints_16384 = {
141 .count = ARRAY_SIZE(rates_16384),
142 .list = rates_16384,
143};
144
145static unsigned int rates_16934[] = {
146 44100, 88235,
147};
148
149static struct snd_pcm_hw_constraint_list constraints_16934 = {
150 .count = ARRAY_SIZE(rates_16934),
151 .list = rates_16934,
152};
153
154static unsigned int rates_18432[] = {
155 48000, 96000,
156};
157
158static struct snd_pcm_hw_constraint_list constraints_18432 = {
159 .count = ARRAY_SIZE(rates_18432),
160 .list = rates_18432,
161};
162
163static unsigned int rates_22579[] = {
164 44100, 88235, 1764000
165};
166
167static struct snd_pcm_hw_constraint_list constraints_22579 = {
168 .count = ARRAY_SIZE(rates_22579),
169 .list = rates_22579,
170};
171
172static unsigned int rates_24576[] = {
173 32000, 48000, 96000, 192000
174};
175
176static struct snd_pcm_hw_constraint_list constraints_24576 = {
177 .count = ARRAY_SIZE(rates_24576),
178 .list = rates_24576,
179};
180
181static unsigned int rates_36864[] = {
182 48000, 96000, 19200
183};
184
185static struct snd_pcm_hw_constraint_list constraints_36864 = {
186 .count = ARRAY_SIZE(rates_36864),
187 .list = rates_36864,
118}; 188};
119 189
120 190
@@ -135,7 +205,7 @@ static int wm8741_startup(struct snd_pcm_substream *substream,
135 205
136 snd_pcm_hw_constraint_list(substream->runtime, 0, 206 snd_pcm_hw_constraint_list(substream->runtime, 0,
137 SNDRV_PCM_HW_PARAM_RATE, 207 SNDRV_PCM_HW_PARAM_RATE,
138 &wm8741->rate_constraint); 208 wm8741->sysclk_constraints);
139 209
140 return 0; 210 return 0;
141} 211}
@@ -145,8 +215,7 @@ static int wm8741_hw_params(struct snd_pcm_substream *substream,
145 struct snd_soc_dai *dai) 215 struct snd_soc_dai *dai)
146{ 216{
147 struct snd_soc_pcm_runtime *rtd = substream->private_data; 217 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct snd_soc_device *socdev = rtd->socdev; 218 struct snd_soc_codec *codec = rtd->codec;
149 struct snd_soc_codec *codec = socdev->card->codec;
150 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); 219 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
151 u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC; 220 u16 iface = snd_soc_read(codec, WM8741_FORMAT_CONTROL) & 0x1FC;
152 int i; 221 int i;
@@ -196,47 +265,52 @@ static int wm8741_set_dai_sysclk(struct snd_soc_dai *codec_dai,
196{ 265{
197 struct snd_soc_codec *codec = codec_dai->codec; 266 struct snd_soc_codec *codec = codec_dai->codec;
198 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); 267 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
199 unsigned int val;
200 int i;
201 268
202 dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq); 269 dev_dbg(codec->dev, "wm8741_set_dai_sysclk info: freq=%dHz\n", freq);
203 270
204 wm8741->sysclk = freq; 271 switch (freq) {
205 272 case 11289600:
206 wm8741->rate_constraint.count = 0; 273 wm8741->sysclk_constraints = &constraints_11289;
207 274 wm8741->sysclk = freq;
208 for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { 275 return 0;
209 dev_dbg(codec->dev, "index = %d, ratio = %d, freq = %d", 276
210 i, lrclk_ratios[i].ratio, freq); 277 case 12288000:
211 278 wm8741->sysclk_constraints = &constraints_12288;
212 val = freq / lrclk_ratios[i].ratio; 279 wm8741->sysclk = freq;
213 /* Check that it's a standard rate since core can't 280 return 0;
214 * cope with others and having the odd rates confuses 281
215 * constraint matching. 282 case 16384000:
216 */ 283 wm8741->sysclk_constraints = &constraints_16384;
217 switch (val) { 284 wm8741->sysclk = freq;
218 case 32000: 285 return 0;
219 case 44100: 286
220 case 48000: 287 case 16934400:
221 case 64000: 288 wm8741->sysclk_constraints = &constraints_16934;
222 case 88200: 289 wm8741->sysclk = freq;
223 case 96000: 290 return 0;
224 dev_dbg(codec->dev, "Supported sample rate: %dHz\n", 291
225 val); 292 case 18432000:
226 wm8741->rate_constraint_list[i] = val; 293 wm8741->sysclk_constraints = &constraints_18432;
227 wm8741->rate_constraint.count++; 294 wm8741->sysclk = freq;
228 break; 295 return 0;
229 default: 296
230 dev_dbg(codec->dev, "Skipping sample rate: %dHz\n", 297 case 22579200:
231 val); 298 case 33868800:
232 } 299 wm8741->sysclk_constraints = &constraints_22579;
300 wm8741->sysclk = freq;
301 return 0;
302
303 case 24576000:
304 wm8741->sysclk_constraints = &constraints_24576;
305 wm8741->sysclk = freq;
306 return 0;
307
308 case 36864000:
309 wm8741->sysclk_constraints = &constraints_36864;
310 wm8741->sysclk = freq;
311 return 0;
233 } 312 }
234 313 return -EINVAL;
235 /* Need at least one supported rate... */
236 if (wm8741->rate_constraint.count == 0)
237 return -EINVAL;
238
239 return 0;
240} 314}
241 315
242static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai, 316static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -314,8 +388,8 @@ static struct snd_soc_dai_ops wm8741_dai_ops = {
314 .set_fmt = wm8741_set_dai_fmt, 388 .set_fmt = wm8741_set_dai_fmt,
315}; 389};
316 390
317struct snd_soc_dai wm8741_dai = { 391static struct snd_soc_dai_driver wm8741_dai = {
318 .name = "WM8741", 392 .name = "wm8741",
319 .playback = { 393 .playback = {
320 .stream_name = "Playback", 394 .stream_name = "Playback",
321 .channels_min = 2, /* Mono modes not yet supported */ 395 .channels_min = 2, /* Mono modes not yet supported */
@@ -325,13 +399,10 @@ struct snd_soc_dai wm8741_dai = {
325 }, 399 },
326 .ops = &wm8741_dai_ops, 400 .ops = &wm8741_dai_ops,
327}; 401};
328EXPORT_SYMBOL_GPL(wm8741_dai);
329 402
330#ifdef CONFIG_PM 403#ifdef CONFIG_PM
331static int wm8741_resume(struct platform_device *pdev) 404static int wm8741_resume(struct snd_soc_codec *codec)
332{ 405{
333 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
334 struct snd_soc_codec *codec = socdev->card->codec;
335 u16 *cache = codec->reg_cache; 406 u16 *cache = codec->reg_cache;
336 int i; 407 int i;
337 408
@@ -348,189 +419,99 @@ static int wm8741_resume(struct platform_device *pdev)
348#define wm8741_resume NULL 419#define wm8741_resume NULL
349#endif 420#endif
350 421
351static int wm8741_probe(struct platform_device *pdev) 422static int wm8741_probe(struct snd_soc_codec *codec)
352{ 423{
353 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 424 struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
354 struct snd_soc_codec *codec;
355 int ret = 0; 425 int ret = 0;
356 426
357 if (wm8741_codec == NULL) { 427 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
358 dev_err(&pdev->dev, "Codec device not registered\n"); 428 if (ret != 0) {
359 return -ENODEV; 429 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
430 return ret;
360 } 431 }
361 432
362 socdev->card->codec = wm8741_codec; 433 ret = wm8741_reset(codec);
363 codec = wm8741_codec;
364
365 /* register pcms */
366 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
367 if (ret < 0) { 434 if (ret < 0) {
368 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 435 dev_err(codec->dev, "Failed to issue reset\n");
369 goto pcm_err; 436 return ret;
370 } 437 }
371 438
439 /* Change some default settings - latch VU */
440 wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
441 wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
442 wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
443 wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
444
372 snd_soc_add_controls(codec, wm8741_snd_controls, 445 snd_soc_add_controls(codec, wm8741_snd_controls,
373 ARRAY_SIZE(wm8741_snd_controls)); 446 ARRAY_SIZE(wm8741_snd_controls));
374 wm8741_add_widgets(codec); 447 wm8741_add_widgets(codec);
375 448
376 return ret; 449 dev_dbg(codec->dev, "Successful registration\n");
377
378pcm_err:
379 return ret; 450 return ret;
380} 451}
381 452
382static int wm8741_remove(struct platform_device *pdev) 453static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {
383{
384 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
385
386 snd_soc_free_pcms(socdev);
387 snd_soc_dapm_free(socdev);
388
389 return 0;
390}
391
392struct snd_soc_codec_device soc_codec_dev_wm8741 = {
393 .probe = wm8741_probe, 454 .probe = wm8741_probe,
394 .remove = wm8741_remove,
395 .resume = wm8741_resume, 455 .resume = wm8741_resume,
456 .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults),
457 .reg_word_size = sizeof(u16),
458 .reg_cache_default = &wm8741_reg_defaults,
396}; 459};
397EXPORT_SYMBOL_GPL(soc_codec_dev_wm8741);
398 460
399static int wm8741_register(struct wm8741_priv *wm8741, 461#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
400 enum snd_soc_control_type control) 462static int wm8741_i2c_probe(struct i2c_client *i2c,
463 const struct i2c_device_id *id)
401{ 464{
402 int ret; 465 struct wm8741_priv *wm8741;
403 struct snd_soc_codec *codec = &wm8741->codec; 466 int ret, i;
404 int i;
405
406 if (wm8741_codec) {
407 dev_err(codec->dev, "Another WM8741 is registered\n");
408 return -EINVAL;
409 }
410
411 mutex_init(&codec->mutex);
412 INIT_LIST_HEAD(&codec->dapm_widgets);
413 INIT_LIST_HEAD(&codec->dapm_paths);
414
415 snd_soc_codec_set_drvdata(codec, wm8741);
416 codec->name = "WM8741";
417 codec->owner = THIS_MODULE;
418 codec->bias_level = SND_SOC_BIAS_OFF;
419 codec->set_bias_level = NULL;
420 codec->dai = &wm8741_dai;
421 codec->num_dai = 1;
422 codec->reg_cache_size = WM8741_REGISTER_COUNT;
423 codec->reg_cache = &wm8741->reg_cache;
424
425 wm8741->rate_constraint.list = &wm8741->rate_constraint_list[0];
426 wm8741->rate_constraint.count =
427 ARRAY_SIZE(wm8741->rate_constraint_list);
428
429 memcpy(codec->reg_cache, wm8741_reg_defaults,
430 sizeof(wm8741->reg_cache));
431 467
432 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 468 wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
433 if (ret != 0) { 469 if (wm8741 == NULL)
434 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 470 return -ENOMEM;
435 goto err;
436 }
437 471
438 for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) 472 for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
439 wm8741->supplies[i].supply = wm8741_supply_names[i]; 473 wm8741->supplies[i].supply = wm8741_supply_names[i];
440 474
441 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), 475 ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies),
442 wm8741->supplies); 476 wm8741->supplies);
443 if (ret != 0) { 477 if (ret != 0) {
444 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 478 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
445 goto err; 479 goto err;
446 } 480 }
447 481
448 ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), 482 ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
449 wm8741->supplies); 483 wm8741->supplies);
450 if (ret != 0) { 484 if (ret != 0) {
451 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); 485 dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
452 goto err_get; 486 goto err_get;
453 } 487 }
454 488
455 ret = wm8741_reset(codec); 489 i2c_set_clientdata(i2c, wm8741);
456 if (ret < 0) { 490 wm8741->control_type = SND_SOC_I2C;
457 dev_err(codec->dev, "Failed to issue reset\n");
458 goto err_enable;
459 }
460
461 wm8741_dai.dev = codec->dev;
462
463 /* Change some default settings - latch VU */
464 wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
465 wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
466 wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
467 wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
468
469 wm8741_codec = codec;
470
471 ret = snd_soc_register_codec(codec);
472 if (ret != 0) {
473 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
474 return ret;
475 }
476
477 ret = snd_soc_register_dai(&wm8741_dai);
478 if (ret != 0) {
479 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
480 snd_soc_unregister_codec(codec);
481 return ret;
482 }
483 491
484 dev_dbg(codec->dev, "Successful registration\n"); 492 ret = snd_soc_register_codec(&i2c->dev,
485 return 0; 493 &soc_codec_dev_wm8741, &wm8741_dai, 1);
494 if (ret < 0)
495 goto err_enable;
496 return ret;
486 497
487err_enable: 498err_enable:
488 regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); 499 regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
489 500
490err_get: 501err_get:
491 regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); 502 regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
492
493err: 503err:
494 kfree(wm8741); 504 kfree(wm8741);
495 return ret; 505 return ret;
496} 506}
497 507
498static void wm8741_unregister(struct wm8741_priv *wm8741) 508static int wm8741_i2c_remove(struct i2c_client *client)
499{
500 regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
501
502 snd_soc_unregister_dai(&wm8741_dai);
503 snd_soc_unregister_codec(&wm8741->codec);
504 kfree(wm8741);
505 wm8741_codec = NULL;
506}
507
508#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
509static __devinit int wm8741_i2c_probe(struct i2c_client *i2c,
510 const struct i2c_device_id *id)
511{
512 struct wm8741_priv *wm8741;
513 struct snd_soc_codec *codec;
514
515 wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
516 if (wm8741 == NULL)
517 return -ENOMEM;
518
519 codec = &wm8741->codec;
520 codec->hw_write = (hw_write_t)i2c_master_send;
521
522 i2c_set_clientdata(i2c, wm8741);
523 codec->control_data = i2c;
524
525 codec->dev = &i2c->dev;
526
527 return wm8741_register(wm8741, SND_SOC_I2C);
528}
529
530static __devexit int wm8741_i2c_remove(struct i2c_client *client)
531{ 509{
532 struct wm8741_priv *wm8741 = i2c_get_clientdata(client); 510 struct wm8741_priv *wm8741 = i2c_get_clientdata(client);
533 wm8741_unregister(wm8741); 511
512 snd_soc_unregister_codec(&client->dev);
513 regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
514 kfree(i2c_get_clientdata(client));
534 return 0; 515 return 0;
535} 516}
536 517
@@ -540,29 +521,28 @@ static const struct i2c_device_id wm8741_i2c_id[] = {
540}; 521};
541MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); 522MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
542 523
543
544static struct i2c_driver wm8741_i2c_driver = { 524static struct i2c_driver wm8741_i2c_driver = {
545 .driver = { 525 .driver = {
546 .name = "WM8741", 526 .name = "wm8741-codec",
547 .owner = THIS_MODULE, 527 .owner = THIS_MODULE,
548 }, 528 },
549 .probe = wm8741_i2c_probe, 529 .probe = wm8741_i2c_probe,
550 .remove = __devexit_p(wm8741_i2c_remove), 530 .remove = wm8741_i2c_remove,
551 .id_table = wm8741_i2c_id, 531 .id_table = wm8741_i2c_id,
552}; 532};
553#endif 533#endif
554 534
555static int __init wm8741_modinit(void) 535static int __init wm8741_modinit(void)
556{ 536{
557 int ret; 537 int ret = 0;
538
558#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 539#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
559 ret = i2c_add_driver(&wm8741_i2c_driver); 540 ret = i2c_add_driver(&wm8741_i2c_driver);
560 if (ret != 0) { 541 if (ret != 0)
561 printk(KERN_ERR "Failed to register WM8741 I2C driver: %d\n", 542 pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
562 ret);
563 }
564#endif 543#endif
565 return 0; 544
545 return ret;
566} 546}
567module_init(wm8741_modinit); 547module_init(wm8741_modinit);
568 548
diff --git a/sound/soc/codecs/wm8741.h b/sound/soc/codecs/wm8741.h
index fdef6ecd1f6f..56c1b1d4a681 100644
--- a/sound/soc/codecs/wm8741.h
+++ b/sound/soc/codecs/wm8741.h
@@ -208,7 +208,4 @@
208 208
209#define WM8741_SYSCLK 0 209#define WM8741_SYSCLK 0
210 210
211extern struct snd_soc_dai wm8741_dai;
212extern struct snd_soc_codec_device soc_codec_dev_wm8741;
213
214#endif 211#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index e2c05e3e323a..6c924cd2cfd4 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -52,7 +52,7 @@ static const u16 wm8750_reg[] = {
52/* codec private data */ 52/* codec private data */
53struct wm8750_priv { 53struct wm8750_priv {
54 unsigned int sysclk; 54 unsigned int sysclk;
55 struct snd_soc_codec codec; 55 enum snd_soc_control_type control_type;
56 u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; 56 u16 reg_cache[ARRAY_SIZE(wm8750_reg)];
57}; 57};
58 58
@@ -560,8 +560,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
560 struct snd_soc_dai *dai) 560 struct snd_soc_dai *dai)
561{ 561{
562 struct snd_soc_pcm_runtime *rtd = substream->private_data; 562 struct snd_soc_pcm_runtime *rtd = substream->private_data;
563 struct snd_soc_device *socdev = rtd->socdev; 563 struct snd_soc_codec *codec = rtd->codec;
564 struct snd_soc_codec *codec = socdev->card->codec;
565 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); 564 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
566 u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; 565 u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
567 u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; 566 u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
@@ -649,8 +648,8 @@ static struct snd_soc_dai_ops wm8750_dai_ops = {
649 .set_sysclk = wm8750_set_dai_sysclk, 648 .set_sysclk = wm8750_set_dai_sysclk,
650}; 649};
651 650
652struct snd_soc_dai wm8750_dai = { 651static struct snd_soc_dai_driver wm8750_dai = {
653 .name = "WM8750", 652 .name = "wm8750-hifi",
654 .playback = { 653 .playback = {
655 .stream_name = "Playback", 654 .stream_name = "Playback",
656 .channels_min = 1, 655 .channels_min = 1,
@@ -665,21 +664,15 @@ struct snd_soc_dai wm8750_dai = {
665 .formats = WM8750_FORMATS,}, 664 .formats = WM8750_FORMATS,},
666 .ops = &wm8750_dai_ops, 665 .ops = &wm8750_dai_ops,
667}; 666};
668EXPORT_SYMBOL_GPL(wm8750_dai);
669 667
670static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) 668static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
671{ 669{
672 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
673 struct snd_soc_codec *codec = socdev->card->codec;
674
675 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); 670 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
676 return 0; 671 return 0;
677} 672}
678 673
679static int wm8750_resume(struct platform_device *pdev) 674static int wm8750_resume(struct snd_soc_codec *codec)
680{ 675{
681 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
682 struct snd_soc_codec *codec = socdev->card->codec;
683 int i; 676 int i;
684 u8 data[2]; 677 u8 data[2];
685 u16 *cache = codec->reg_cache; 678 u16 *cache = codec->reg_cache;
@@ -698,100 +691,21 @@ static int wm8750_resume(struct platform_device *pdev)
698 return 0; 691 return 0;
699} 692}
700 693
701static struct snd_soc_codec *wm8750_codec; 694static int wm8750_probe(struct snd_soc_codec *codec)
702
703static int wm8750_probe(struct platform_device *pdev)
704{
705 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
706 struct snd_soc_codec *codec;
707 int ret = 0;
708
709 if (!wm8750_codec) {
710 dev_err(&pdev->dev, "WM8750 codec not yet registered\n");
711 return -EINVAL;
712 }
713
714 socdev->card->codec = wm8750_codec;
715 codec = wm8750_codec;
716
717 /* register pcms */
718 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
719 if (ret < 0) {
720 printk(KERN_ERR "wm8750: failed to create pcms\n");
721 goto err;
722 }
723
724 snd_soc_add_controls(codec, wm8750_snd_controls,
725 ARRAY_SIZE(wm8750_snd_controls));
726 wm8750_add_widgets(codec);
727
728 return 0;
729
730err:
731 return ret;
732}
733
734/* power down chip */
735static int wm8750_remove(struct platform_device *pdev)
736{
737 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
738
739 snd_soc_free_pcms(socdev);
740 snd_soc_dapm_free(socdev);
741
742 return 0;
743}
744
745struct snd_soc_codec_device soc_codec_dev_wm8750 = {
746 .probe = wm8750_probe,
747 .remove = wm8750_remove,
748 .suspend = wm8750_suspend,
749 .resume = wm8750_resume,
750};
751EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
752
753/*
754 * initialise the WM8750 driver
755 * register the mixer and dsp interfaces with the kernel
756 */
757static int wm8750_register(struct wm8750_priv *wm8750,
758 enum snd_soc_control_type control)
759{ 695{
760 struct snd_soc_codec *codec = &wm8750->codec; 696 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
761 int reg, ret = 0; 697 int reg, ret;
762
763 if (wm8750_codec) {
764 dev_err(codec->dev, "Multiple WM8750 devices not supported\n");
765 ret = -EINVAL;
766 goto err;
767 }
768
769 mutex_init(&codec->mutex);
770 INIT_LIST_HEAD(&codec->dapm_widgets);
771 INIT_LIST_HEAD(&codec->dapm_paths);
772
773 codec->name = "WM8750";
774 codec->owner = THIS_MODULE;
775 codec->bias_level = SND_SOC_BIAS_STANDBY;
776 codec->set_bias_level = wm8750_set_bias_level;
777 codec->dai = &wm8750_dai;
778 codec->num_dai = 1;
779 codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1;
780 codec->reg_cache = &wm8750->reg_cache;
781 snd_soc_codec_set_drvdata(codec, wm8750);
782
783 memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache));
784 698
785 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 699 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
786 if (ret < 0) { 700 if (ret < 0) {
787 printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); 701 printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
788 goto err; 702 return ret;
789 } 703 }
790 704
791 ret = wm8750_reset(codec); 705 ret = wm8750_reset(codec);
792 if (ret < 0) { 706 if (ret < 0) {
793 printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); 707 printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
794 goto err; 708 return ret;
795 } 709 }
796 710
797 /* charge output caps */ 711 /* charge output caps */
@@ -815,150 +729,130 @@ static int wm8750_register(struct wm8750_priv *wm8750,
815 reg = snd_soc_read(codec, WM8750_RINVOL); 729 reg = snd_soc_read(codec, WM8750_RINVOL);
816 snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); 730 snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
817 731
818 wm8750_codec = codec; 732 snd_soc_add_controls(codec, wm8750_snd_controls,
819 733 ARRAY_SIZE(wm8750_snd_controls));
820 ret = snd_soc_register_codec(codec); 734 wm8750_add_widgets(codec);
821 if (ret != 0) {
822 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
823 goto err;
824 }
825
826 ret = snd_soc_register_dais(&wm8750_dai, 1);
827 if (ret != 0) {
828 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
829 goto err_codec;
830 }
831
832 return 0;
833
834err_codec:
835 snd_soc_unregister_codec(codec);
836err:
837 kfree(wm8750);
838 return ret; 735 return ret;
839} 736}
840 737
841static void wm8750_unregister(struct wm8750_priv *wm8750) 738static int wm8750_remove(struct snd_soc_codec *codec)
842{ 739{
843 wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF); 740 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
844 snd_soc_unregister_dais(&wm8750_dai, 1); 741 return 0;
845 snd_soc_unregister_codec(&wm8750->codec);
846 kfree(wm8750);
847 wm8750_codec = NULL;
848} 742}
849 743
850#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 744static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
851 745 .probe = wm8750_probe,
852/* 746 .remove = wm8750_remove,
853 * WM8750 2 wire address is determined by GPIO5 747 .suspend = wm8750_suspend,
854 * state during powerup. 748 .resume = wm8750_resume,
855 * low = 0x1a 749 .set_bias_level = wm8750_set_bias_level,
856 * high = 0x1b 750 .reg_cache_size = ARRAY_SIZE(wm8750_reg),
857 */ 751 .reg_word_size = sizeof(u16),
752 .reg_cache_default = wm8750_reg,
753};
858 754
859static int wm8750_i2c_probe(struct i2c_client *i2c, 755#if defined(CONFIG_SPI_MASTER)
860 const struct i2c_device_id *id) 756static int __devinit wm8750_spi_probe(struct spi_device *spi)
861{ 757{
862 struct snd_soc_codec *codec;
863 struct wm8750_priv *wm8750; 758 struct wm8750_priv *wm8750;
759 int ret;
864 760
865 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); 761 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
866 if (wm8750 == NULL) 762 if (wm8750 == NULL)
867 return -ENOMEM; 763 return -ENOMEM;
868 764
869 codec = &wm8750->codec; 765 wm8750->control_type = SND_SOC_SPI;
870 codec->control_data = i2c; 766 spi_set_drvdata(spi, wm8750);
871 i2c_set_clientdata(i2c, wm8750);
872
873 codec->dev = &i2c->dev;
874 767
875 return wm8750_register(wm8750, SND_SOC_I2C); 768 ret = snd_soc_register_codec(&spi->dev,
769 &soc_codec_dev_wm8750, &wm8750_dai, 1);
770 if (ret < 0)
771 kfree(wm8750);
772 return ret;
876} 773}
877 774
878static int wm8750_i2c_remove(struct i2c_client *client) 775static int __devexit wm8750_spi_remove(struct spi_device *spi)
879{ 776{
880 struct wm8750_priv *wm8750 = i2c_get_clientdata(client); 777 snd_soc_unregister_codec(&spi->dev);
881 wm8750_unregister(wm8750); 778 kfree(spi_get_drvdata(spi));
882 return 0; 779 return 0;
883} 780}
884 781
885static const struct i2c_device_id wm8750_i2c_id[] = { 782static struct spi_driver wm8750_spi_driver = {
886 { "wm8750", 0 },
887 { "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */
888 { }
889};
890MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
891
892static struct i2c_driver wm8750_i2c_driver = {
893 .driver = { 783 .driver = {
894 .name = "WM8750 I2C Codec", 784 .name = "wm8750-codec",
895 .owner = THIS_MODULE, 785 .owner = THIS_MODULE,
896 }, 786 },
897 .probe = wm8750_i2c_probe, 787 .probe = wm8750_spi_probe,
898 .remove = wm8750_i2c_remove, 788 .remove = __devexit_p(wm8750_spi_remove),
899 .id_table = wm8750_i2c_id,
900}; 789};
901#endif 790#endif /* CONFIG_SPI_MASTER */
902 791
903#if defined(CONFIG_SPI_MASTER) 792#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
904static int __devinit wm8750_spi_probe(struct spi_device *spi) 793static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
794 const struct i2c_device_id *id)
905{ 795{
906 struct snd_soc_codec *codec;
907 struct wm8750_priv *wm8750; 796 struct wm8750_priv *wm8750;
797 int ret;
908 798
909 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); 799 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
910 if (wm8750 == NULL) 800 if (wm8750 == NULL)
911 return -ENOMEM; 801 return -ENOMEM;
912 802
913 codec = &wm8750->codec; 803 i2c_set_clientdata(i2c, wm8750);
914 codec->control_data = spi; 804 wm8750->control_type = SND_SOC_I2C;
915 codec->dev = &spi->dev;
916
917 dev_set_drvdata(&spi->dev, wm8750);
918 805
919 return wm8750_register(wm8750, SND_SOC_SPI); 806 ret = snd_soc_register_codec(&i2c->dev,
807 &soc_codec_dev_wm8750, &wm8750_dai, 1);
808 if (ret < 0)
809 kfree(wm8750);
810 return ret;
920} 811}
921 812
922static int __devexit wm8750_spi_remove(struct spi_device *spi) 813static __devexit int wm8750_i2c_remove(struct i2c_client *client)
923{ 814{
924 struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev); 815 snd_soc_unregister_codec(&client->dev);
925 wm8750_unregister(wm8750); 816 kfree(i2c_get_clientdata(client));
926 return 0; 817 return 0;
927} 818}
928 819
929static const struct spi_device_id wm8750_spi_id[] = { 820static const struct i2c_device_id wm8750_i2c_id[] = {
930 { "wm8750", 0 }, 821 { "wm8750", 0 },
931 { "wm8987", 0 }, 822 { "wm8987", 0 },
932 { } 823 { }
933}; 824};
934MODULE_DEVICE_TABLE(spi, wm8750_spi_id); 825MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
935 826
936static struct spi_driver wm8750_spi_driver = { 827static struct i2c_driver wm8750_i2c_driver = {
937 .driver = { 828 .driver = {
938 .name = "WM8750 SPI Codec", 829 .name = "wm8750-codec",
939 .bus = &spi_bus_type, 830 .owner = THIS_MODULE,
940 .owner = THIS_MODULE,
941 }, 831 },
942 .probe = wm8750_spi_probe, 832 .probe = wm8750_i2c_probe,
943 .remove = __devexit_p(wm8750_spi_remove), 833 .remove = __devexit_p(wm8750_i2c_remove),
944 .id_table = wm8750_spi_id, 834 .id_table = wm8750_i2c_id,
945}; 835};
946#endif 836#endif
947 837
948static int __init wm8750_modinit(void) 838static int __init wm8750_modinit(void)
949{ 839{
950 int ret; 840 int ret = 0;
951#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 841#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
952 ret = i2c_add_driver(&wm8750_i2c_driver); 842 ret = i2c_add_driver(&wm8750_i2c_driver);
953 if (ret != 0) 843 if (ret != 0) {
954 pr_err("Failed to register WM8750 I2C driver: %d\n", ret); 844 printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n",
845 ret);
846 }
955#endif 847#endif
956#if defined(CONFIG_SPI_MASTER) 848#if defined(CONFIG_SPI_MASTER)
957 ret = spi_register_driver(&wm8750_spi_driver); 849 ret = spi_register_driver(&wm8750_spi_driver);
958 if (ret != 0) 850 if (ret != 0) {
959 pr_err("Failed to register WM8750 SPI driver: %d\n", ret); 851 printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n",
852 ret);
853 }
960#endif 854#endif
961 return 0; 855 return ret;
962} 856}
963module_init(wm8750_modinit); 857module_init(wm8750_modinit);
964 858
diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h
index 1dc100e19cfe..121427c047fb 100644
--- a/sound/soc/codecs/wm8750.h
+++ b/sound/soc/codecs/wm8750.h
@@ -57,13 +57,4 @@
57 57
58#define WM8750_SYSCLK 0 58#define WM8750_SYSCLK 0
59 59
60struct wm8750_setup_data {
61 int spi;
62 int i2c_bus;
63 unsigned short i2c_address;
64};
65
66extern struct snd_soc_dai wm8750_dai;
67extern struct snd_soc_codec_device soc_codec_dev_wm8750;
68
69#endif 60#endif
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index b59f349c5218..8f679a13f2bc 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -57,7 +57,7 @@ module_param(caps_charge, int, 0);
57MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)"); 57MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
58 58
59static void wm8753_set_dai_mode(struct snd_soc_codec *codec, 59static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
60 unsigned int mode); 60 struct snd_soc_dai *dai, unsigned int hifi);
61 61
62/* 62/*
63 * wm8753 register cache 63 * wm8753 register cache
@@ -85,10 +85,11 @@ static const u16 wm8753_reg[] = {
85 85
86/* codec private data */ 86/* codec private data */
87struct wm8753_priv { 87struct wm8753_priv {
88 enum snd_soc_control_type control_type;
88 unsigned int sysclk; 89 unsigned int sysclk;
89 unsigned int pcmclk; 90 unsigned int pcmclk;
90 struct snd_soc_codec codec;
91 u16 reg_cache[ARRAY_SIZE(wm8753_reg)]; 91 u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
92 int dai_func;
92}; 93};
93 94
94/* 95/*
@@ -228,6 +229,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
228{ 229{
229 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 230 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
230 int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL); 231 int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
232 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
231 233
232 if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0]) 234 if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
233 return 0; 235 return 0;
@@ -235,8 +237,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
235 mode &= 0xfff3; 237 mode &= 0xfff3;
236 mode |= (ucontrol->value.integer.value[0] << 2); 238 mode |= (ucontrol->value.integer.value[0] << 2);
237 239
238 wm8753_write(codec, WM8753_IOCTL, mode); 240 wm8753->dai_func = ucontrol->value.integer.value[0];
239 wm8753_set_dai_mode(codec, ucontrol->value.integer.value[0]);
240 return 1; 241 return 1;
241} 242}
242 243
@@ -904,6 +905,13 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
904 return 0; 905 return 0;
905} 906}
906 907
908static int wm8753_pcm_startup(struct snd_pcm_substream *substream,
909 struct snd_soc_dai *dai)
910{
911 wm8753_set_dai_mode(dai->codec, dai, 0);
912 return 0;
913}
914
907/* 915/*
908 * Set PCM DAI bit size and sample rate. 916 * Set PCM DAI bit size and sample rate.
909 */ 917 */
@@ -912,8 +920,7 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
912 struct snd_soc_dai *dai) 920 struct snd_soc_dai *dai)
913{ 921{
914 struct snd_soc_pcm_runtime *rtd = substream->private_data; 922 struct snd_soc_pcm_runtime *rtd = substream->private_data;
915 struct snd_soc_device *socdev = rtd->socdev; 923 struct snd_soc_codec *codec = rtd->codec;
916 struct snd_soc_codec *codec = socdev->card->codec;
917 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); 924 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
918 u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3; 925 u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
919 u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f; 926 u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
@@ -1138,6 +1145,13 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
1138 return 0; 1145 return 0;
1139} 1146}
1140 1147
1148static int wm8753_i2s_startup(struct snd_pcm_substream *substream,
1149 struct snd_soc_dai *dai)
1150{
1151 wm8753_set_dai_mode(dai->codec, dai, 1);
1152 return 0;
1153}
1154
1141/* 1155/*
1142 * Set PCM DAI bit size and sample rate. 1156 * Set PCM DAI bit size and sample rate.
1143 */ 1157 */
@@ -1146,8 +1160,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
1146 struct snd_soc_dai *dai) 1160 struct snd_soc_dai *dai)
1147{ 1161{
1148 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1162 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1149 struct snd_soc_device *socdev = rtd->socdev; 1163 struct snd_soc_codec *codec = rtd->codec;
1150 struct snd_soc_codec *codec = socdev->card->codec;
1151 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); 1164 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1152 u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0; 1165 u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
1153 u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3; 1166 u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
@@ -1240,12 +1253,12 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
1240{ 1253{
1241 struct snd_soc_codec *codec = dai->codec; 1254 struct snd_soc_codec *codec = dai->codec;
1242 u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7; 1255 u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
1256 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1243 1257
1244 /* the digital mute covers the HiFi and Voice DAC's on the WM8753. 1258 /* the digital mute covers the HiFi and Voice DAC's on the WM8753.
1245 * make sure we check if they are not both active when we mute */ 1259 * make sure we check if they are not both active when we mute */
1246 if (mute && dai->id == 1) { 1260 if (mute && wm8753->dai_func == 1) {
1247 if (!wm8753_dai[WM8753_DAI_VOICE].playback.active || 1261 if (!codec->active)
1248 !wm8753_dai[WM8753_DAI_HIFI].playback.active)
1249 wm8753_write(codec, WM8753_DAC, mute_reg | 0x8); 1262 wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
1250 } else { 1263 } else {
1251 if (mute) 1264 if (mute)
@@ -1303,6 +1316,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,
1303 * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture 1316 * 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
1304 */ 1317 */
1305static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = { 1318static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {
1319 .startup = wm8753_i2s_startup,
1306 .hw_params = wm8753_i2s_hw_params, 1320 .hw_params = wm8753_i2s_hw_params,
1307 .digital_mute = wm8753_mute, 1321 .digital_mute = wm8753_mute,
1308 .set_fmt = wm8753_mode1h_set_dai_fmt, 1322 .set_fmt = wm8753_mode1h_set_dai_fmt,
@@ -1312,6 +1326,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode1 = {
1312}; 1326};
1313 1327
1314static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = { 1328static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {
1329 .startup = wm8753_pcm_startup,
1315 .hw_params = wm8753_pcm_hw_params, 1330 .hw_params = wm8753_pcm_hw_params,
1316 .digital_mute = wm8753_mute, 1331 .digital_mute = wm8753_mute,
1317 .set_fmt = wm8753_mode1v_set_dai_fmt, 1332 .set_fmt = wm8753_mode1v_set_dai_fmt,
@@ -1321,6 +1336,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode1 = {
1321}; 1336};
1322 1337
1323static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = { 1338static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {
1339 .startup = wm8753_pcm_startup,
1324 .hw_params = wm8753_pcm_hw_params, 1340 .hw_params = wm8753_pcm_hw_params,
1325 .digital_mute = wm8753_mute, 1341 .digital_mute = wm8753_mute,
1326 .set_fmt = wm8753_mode2_set_dai_fmt, 1342 .set_fmt = wm8753_mode2_set_dai_fmt,
@@ -1330,6 +1346,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode2 = {
1330}; 1346};
1331 1347
1332static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = { 1348static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = {
1349 .startup = wm8753_i2s_startup,
1333 .hw_params = wm8753_i2s_hw_params, 1350 .hw_params = wm8753_i2s_hw_params,
1334 .digital_mute = wm8753_mute, 1351 .digital_mute = wm8753_mute,
1335 .set_fmt = wm8753_mode3_4_set_dai_fmt, 1352 .set_fmt = wm8753_mode3_4_set_dai_fmt,
@@ -1339,6 +1356,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode3 = {
1339}; 1356};
1340 1357
1341static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = { 1358static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = {
1359 .startup = wm8753_i2s_startup,
1342 .hw_params = wm8753_i2s_hw_params, 1360 .hw_params = wm8753_i2s_hw_params,
1343 .digital_mute = wm8753_mute, 1361 .digital_mute = wm8753_mute,
1344 .set_fmt = wm8753_mode3_4_set_dai_fmt, 1362 .set_fmt = wm8753_mode3_4_set_dai_fmt,
@@ -1347,10 +1365,9 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode4 = {
1347 .set_sysclk = wm8753_set_dai_sysclk, 1365 .set_sysclk = wm8753_set_dai_sysclk,
1348}; 1366};
1349 1367
1350static const struct snd_soc_dai wm8753_all_dai[] = { 1368static struct snd_soc_dai_driver wm8753_all_dai[] = {
1351/* DAI HiFi mode 1 */ 1369/* DAI HiFi mode 1 */
1352{ .name = "WM8753 HiFi", 1370{ .name = "wm8753-hifi",
1353 .id = 1,
1354 .playback = { 1371 .playback = {
1355 .stream_name = "HiFi Playback", 1372 .stream_name = "HiFi Playback",
1356 .channels_min = 1, 1373 .channels_min = 1,
@@ -1366,8 +1383,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1366 .ops = &wm8753_dai_ops_hifi_mode1, 1383 .ops = &wm8753_dai_ops_hifi_mode1,
1367}, 1384},
1368/* DAI Voice mode 1 */ 1385/* DAI Voice mode 1 */
1369{ .name = "WM8753 Voice", 1386{ .name = "wm8753-voice",
1370 .id = 1,
1371 .playback = { 1387 .playback = {
1372 .stream_name = "Voice Playback", 1388 .stream_name = "Voice Playback",
1373 .channels_min = 1, 1389 .channels_min = 1,
@@ -1383,12 +1399,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1383 .ops = &wm8753_dai_ops_voice_mode1, 1399 .ops = &wm8753_dai_ops_voice_mode1,
1384}, 1400},
1385/* DAI HiFi mode 2 - dummy */ 1401/* DAI HiFi mode 2 - dummy */
1386{ .name = "WM8753 HiFi", 1402{ .name = "wm8753-hifi",
1387 .id = 2,
1388}, 1403},
1389/* DAI Voice mode 2 */ 1404/* DAI Voice mode 2 */
1390{ .name = "WM8753 Voice", 1405{ .name = "wm8753-voice",
1391 .id = 2,
1392 .playback = { 1406 .playback = {
1393 .stream_name = "Voice Playback", 1407 .stream_name = "Voice Playback",
1394 .channels_min = 1, 1408 .channels_min = 1,
@@ -1404,8 +1418,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1404 .ops = &wm8753_dai_ops_voice_mode2, 1418 .ops = &wm8753_dai_ops_voice_mode2,
1405}, 1419},
1406/* DAI HiFi mode 3 */ 1420/* DAI HiFi mode 3 */
1407{ .name = "WM8753 HiFi", 1421{ .name = "wm8753-hifi",
1408 .id = 3,
1409 .playback = { 1422 .playback = {
1410 .stream_name = "HiFi Playback", 1423 .stream_name = "HiFi Playback",
1411 .channels_min = 1, 1424 .channels_min = 1,
@@ -1421,12 +1434,10 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1421 .ops = &wm8753_dai_ops_hifi_mode3, 1434 .ops = &wm8753_dai_ops_hifi_mode3,
1422}, 1435},
1423/* DAI Voice mode 3 - dummy */ 1436/* DAI Voice mode 3 - dummy */
1424{ .name = "WM8753 Voice", 1437{ .name = "wm8753-voice",
1425 .id = 3,
1426}, 1438},
1427/* DAI HiFi mode 4 */ 1439/* DAI HiFi mode 4 */
1428{ .name = "WM8753 HiFi", 1440{ .name = "wm8753-hifi",
1429 .id = 4,
1430 .playback = { 1441 .playback = {
1431 .stream_name = "HiFi Playback", 1442 .stream_name = "HiFi Playback",
1432 .channels_min = 1, 1443 .channels_min = 1,
@@ -1442,58 +1453,31 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
1442 .ops = &wm8753_dai_ops_hifi_mode4, 1453 .ops = &wm8753_dai_ops_hifi_mode4,
1443}, 1454},
1444/* DAI Voice mode 4 - dummy */ 1455/* DAI Voice mode 4 - dummy */
1445{ .name = "WM8753 Voice", 1456{ .name = "wm8753-voice",
1446 .id = 4,
1447}, 1457},
1448}; 1458};
1449 1459
1450struct snd_soc_dai wm8753_dai[] = { 1460static struct snd_soc_dai_driver wm8753_dai[] = {
1451 { 1461 {
1452 .name = "WM8753 DAI 0", 1462 .name = "wm8753-aif0",
1453 }, 1463 },
1454 { 1464 {
1455 .name = "WM8753 DAI 1", 1465 .name = "wm8753-aif1",
1456 }, 1466 },
1457}; 1467};
1458EXPORT_SYMBOL_GPL(wm8753_dai);
1459 1468
1460static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode) 1469static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
1470 struct snd_soc_dai *dai, unsigned int hifi)
1461{ 1471{
1462 if (mode < 4) { 1472 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1463 int playback_active, capture_active, codec_active, pop_wait; 1473
1464 void *private_data; 1474 if (wm8753->dai_func < 4) {
1465 struct list_head list; 1475 if (hifi)
1466 1476 dai->driver = &wm8753_all_dai[wm8753->dai_func << 1];
1467 playback_active = wm8753_dai[0].playback.active; 1477 else
1468 capture_active = wm8753_dai[0].capture.active; 1478 dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
1469 codec_active = wm8753_dai[0].active;
1470 private_data = wm8753_dai[0].private_data;
1471 pop_wait = wm8753_dai[0].pop_wait;
1472 list = wm8753_dai[0].list;
1473 wm8753_dai[0] = wm8753_all_dai[mode << 1];
1474 wm8753_dai[0].playback.active = playback_active;
1475 wm8753_dai[0].capture.active = capture_active;
1476 wm8753_dai[0].active = codec_active;
1477 wm8753_dai[0].private_data = private_data;
1478 wm8753_dai[0].pop_wait = pop_wait;
1479 wm8753_dai[0].list = list;
1480
1481 playback_active = wm8753_dai[1].playback.active;
1482 capture_active = wm8753_dai[1].capture.active;
1483 codec_active = wm8753_dai[1].active;
1484 private_data = wm8753_dai[1].private_data;
1485 pop_wait = wm8753_dai[1].pop_wait;
1486 list = wm8753_dai[1].list;
1487 wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1];
1488 wm8753_dai[1].playback.active = playback_active;
1489 wm8753_dai[1].capture.active = capture_active;
1490 wm8753_dai[1].active = codec_active;
1491 wm8753_dai[1].private_data = private_data;
1492 wm8753_dai[1].pop_wait = pop_wait;
1493 wm8753_dai[1].list = list;
1494 } 1479 }
1495 wm8753_dai[0].codec = codec; 1480 wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func);
1496 wm8753_dai[1].codec = codec;
1497} 1481}
1498 1482
1499static void wm8753_work(struct work_struct *work) 1483static void wm8753_work(struct work_struct *work)
@@ -1503,19 +1487,14 @@ static void wm8753_work(struct work_struct *work)
1503 wm8753_set_bias_level(codec, codec->bias_level); 1487 wm8753_set_bias_level(codec, codec->bias_level);
1504} 1488}
1505 1489
1506static int wm8753_suspend(struct platform_device *pdev, pm_message_t state) 1490static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
1507{ 1491{
1508 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1509 struct snd_soc_codec *codec = socdev->card->codec;
1510
1511 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); 1492 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
1512 return 0; 1493 return 0;
1513} 1494}
1514 1495
1515static int wm8753_resume(struct platform_device *pdev) 1496static int wm8753_resume(struct snd_soc_codec *codec)
1516{ 1497{
1517 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1518 struct snd_soc_codec *codec = socdev->card->codec;
1519 int i; 1498 int i;
1520 u8 data[2]; 1499 u8 data[2];
1521 u16 *cache = codec->reg_cache; 1500 u16 *cache = codec->reg_cache;
@@ -1547,41 +1526,6 @@ static int wm8753_resume(struct platform_device *pdev)
1547 return 0; 1526 return 0;
1548} 1527}
1549 1528
1550static struct snd_soc_codec *wm8753_codec;
1551
1552static int wm8753_probe(struct platform_device *pdev)
1553{
1554 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1555 struct snd_soc_codec *codec;
1556 int ret = 0;
1557
1558 if (!wm8753_codec) {
1559 dev_err(&pdev->dev, "WM8753 codec not yet registered\n");
1560 return -EINVAL;
1561 }
1562
1563 socdev->card->codec = wm8753_codec;
1564 codec = wm8753_codec;
1565
1566 wm8753_set_dai_mode(codec, 0);
1567
1568 /* register pcms */
1569 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1570 if (ret < 0) {
1571 printk(KERN_ERR "wm8753: failed to create pcms\n");
1572 goto pcm_err;
1573 }
1574
1575 snd_soc_add_controls(codec, wm8753_snd_controls,
1576 ARRAY_SIZE(wm8753_snd_controls));
1577 wm8753_add_widgets(codec);
1578
1579 return 0;
1580
1581pcm_err:
1582 return ret;
1583}
1584
1585/* 1529/*
1586 * This function forces any delayed work to be queued and run. 1530 * This function forces any delayed work to be queued and run.
1587 */ 1531 */
@@ -1601,62 +1545,28 @@ static int run_delayed_work(struct delayed_work *dwork)
1601 return ret; 1545 return ret;
1602} 1546}
1603 1547
1604/* power down chip */ 1548static int wm8753_probe(struct snd_soc_codec *codec)
1605static int wm8753_remove(struct platform_device *pdev)
1606{ 1549{
1607 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1550 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1608 1551 int ret = 0, reg;
1609 snd_soc_free_pcms(socdev);
1610 snd_soc_dapm_free(socdev);
1611
1612 return 0;
1613}
1614
1615struct snd_soc_codec_device soc_codec_dev_wm8753 = {
1616 .probe = wm8753_probe,
1617 .remove = wm8753_remove,
1618 .suspend = wm8753_suspend,
1619 .resume = wm8753_resume,
1620};
1621EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
1622 1552
1623static int wm8753_register(struct wm8753_priv *wm8753) 1553 INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
1624{
1625 int ret, i;
1626 struct snd_soc_codec *codec = &wm8753->codec;
1627 u16 reg;
1628 1554
1629 if (wm8753_codec) { 1555 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type);
1630 dev_err(codec->dev, "Multiple WM8753 devices not supported\n"); 1556 if (ret < 0) {
1631 ret = -EINVAL; 1557 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1632 goto err; 1558 return ret;
1633 } 1559 }
1634 1560
1635 mutex_init(&codec->mutex);
1636 INIT_LIST_HEAD(&codec->dapm_widgets);
1637 INIT_LIST_HEAD(&codec->dapm_paths);
1638
1639 codec->name = "WM8753";
1640 codec->owner = THIS_MODULE;
1641 codec->read = wm8753_read_reg_cache;
1642 codec->write = wm8753_write;
1643 codec->bias_level = SND_SOC_BIAS_STANDBY;
1644 codec->set_bias_level = wm8753_set_bias_level;
1645 codec->dai = wm8753_dai;
1646 codec->num_dai = 2;
1647 codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache) + 1;
1648 codec->reg_cache = &wm8753->reg_cache;
1649 snd_soc_codec_set_drvdata(codec, wm8753);
1650
1651 memcpy(codec->reg_cache, wm8753_reg, sizeof(wm8753->reg_cache));
1652 INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
1653
1654 ret = wm8753_reset(codec); 1561 ret = wm8753_reset(codec);
1655 if (ret < 0) { 1562 if (ret < 0) {
1656 dev_err(codec->dev, "Failed to issue reset\n"); 1563 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
1657 goto err; 1564 return ret;
1658 } 1565 }
1659 1566
1567 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1568 wm8753->dai_func = 0;
1569
1660 /* charge output caps */ 1570 /* charge output caps */
1661 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); 1571 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
1662 schedule_delayed_work(&codec->delayed_work, 1572 schedule_delayed_work(&codec->delayed_work,
@@ -1684,165 +1594,133 @@ static int wm8753_register(struct wm8753_priv *wm8753)
1684 reg = wm8753_read_reg_cache(codec, WM8753_RINVOL); 1594 reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
1685 wm8753_write(codec, WM8753_RINVOL, reg | 0x0100); 1595 wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
1686 1596
1687 wm8753_codec = codec; 1597 snd_soc_add_controls(codec, wm8753_snd_controls,
1688 1598 ARRAY_SIZE(wm8753_snd_controls));
1689 for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++) 1599 wm8753_add_widgets(codec);
1690 wm8753_dai[i].dev = codec->dev;
1691
1692 ret = snd_soc_register_codec(codec);
1693 if (ret != 0) {
1694 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1695 goto err;
1696 }
1697
1698 ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
1699 if (ret != 0) {
1700 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
1701 goto err_codec;
1702 }
1703 1600
1704 return 0; 1601 return 0;
1705
1706err_codec:
1707 run_delayed_work(&codec->delayed_work);
1708 snd_soc_unregister_codec(codec);
1709err:
1710 kfree(wm8753);
1711 return ret;
1712} 1602}
1713 1603
1714static void wm8753_unregister(struct wm8753_priv *wm8753) 1604/* power down chip */
1605static int wm8753_remove(struct snd_soc_codec *codec)
1715{ 1606{
1716 wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF); 1607 run_delayed_work(&codec->delayed_work);
1717 run_delayed_work(&wm8753->codec.delayed_work); 1608 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
1718 snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai)); 1609
1719 snd_soc_unregister_codec(&wm8753->codec); 1610 return 0;
1720 kfree(wm8753);
1721 wm8753_codec = NULL;
1722} 1611}
1723 1612
1724#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1613static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
1614 .probe = wm8753_probe,
1615 .remove = wm8753_remove,
1616 .suspend = wm8753_suspend,
1617 .resume = wm8753_resume,
1618 .set_bias_level = wm8753_set_bias_level,
1619 .reg_cache_size = ARRAY_SIZE(wm8753_reg),
1620 .reg_word_size = sizeof(u16),
1621 .reg_cache_default = wm8753_reg,
1622};
1725 1623
1726static int wm8753_i2c_probe(struct i2c_client *i2c, 1624#if defined(CONFIG_SPI_MASTER)
1727 const struct i2c_device_id *id) 1625static int __devinit wm8753_spi_probe(struct spi_device *spi)
1728{ 1626{
1729 struct snd_soc_codec *codec;
1730 struct wm8753_priv *wm8753; 1627 struct wm8753_priv *wm8753;
1628 int ret;
1731 1629
1732 wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); 1630 wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
1733 if (wm8753 == NULL) 1631 if (wm8753 == NULL)
1734 return -ENOMEM; 1632 return -ENOMEM;
1735 1633
1736 codec = &wm8753->codec; 1634 wm8753->control_type = SND_SOC_SPI;
1737 codec->hw_write = (hw_write_t)i2c_master_send; 1635 spi_set_drvdata(spi, wm8753);
1738 codec->control_data = i2c;
1739 i2c_set_clientdata(i2c, wm8753);
1740
1741 codec->dev = &i2c->dev;
1742 1636
1743 return wm8753_register(wm8753); 1637 ret = snd_soc_register_codec(&spi->dev,
1638 &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
1639 if (ret < 0)
1640 kfree(wm8753);
1641 return ret;
1744} 1642}
1745 1643
1746static int wm8753_i2c_remove(struct i2c_client *client) 1644static int __devexit wm8753_spi_remove(struct spi_device *spi)
1747{ 1645{
1748 struct wm8753_priv *wm8753 = i2c_get_clientdata(client); 1646 snd_soc_unregister_codec(&spi->dev);
1749 wm8753_unregister(wm8753); 1647 kfree(spi_get_drvdata(spi));
1750 return 0; 1648 return 0;
1751} 1649}
1752 1650
1753static const struct i2c_device_id wm8753_i2c_id[] = { 1651static struct spi_driver wm8753_spi_driver = {
1754 { "wm8753", 0 },
1755 { }
1756};
1757MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
1758
1759static struct i2c_driver wm8753_i2c_driver = {
1760 .driver = { 1652 .driver = {
1761 .name = "wm8753", 1653 .name = "wm8753-codec",
1762 .owner = THIS_MODULE, 1654 .owner = THIS_MODULE,
1763 }, 1655 },
1764 .probe = wm8753_i2c_probe, 1656 .probe = wm8753_spi_probe,
1765 .remove = wm8753_i2c_remove, 1657 .remove = __devexit_p(wm8753_spi_remove),
1766 .id_table = wm8753_i2c_id,
1767}; 1658};
1768#endif 1659#endif /* CONFIG_SPI_MASTER */
1769
1770#if defined(CONFIG_SPI_MASTER)
1771static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
1772{
1773 struct spi_transfer t;
1774 struct spi_message m;
1775 u8 msg[2];
1776
1777 if (len <= 0)
1778 return 0;
1779 1660
1780 msg[0] = data[0]; 1661#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1781 msg[1] = data[1]; 1662static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
1782 1663 const struct i2c_device_id *id)
1783 spi_message_init(&m);
1784 memset(&t, 0, (sizeof t));
1785
1786 t.tx_buf = &msg[0];
1787 t.len = len;
1788
1789 spi_message_add_tail(&t, &m);
1790 spi_sync(spi, &m);
1791
1792 return len;
1793}
1794
1795static int __devinit wm8753_spi_probe(struct spi_device *spi)
1796{ 1664{
1797 struct snd_soc_codec *codec;
1798 struct wm8753_priv *wm8753; 1665 struct wm8753_priv *wm8753;
1666 int ret;
1799 1667
1800 wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL); 1668 wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
1801 if (wm8753 == NULL) 1669 if (wm8753 == NULL)
1802 return -ENOMEM; 1670 return -ENOMEM;
1803 1671
1804 codec = &wm8753->codec; 1672 i2c_set_clientdata(i2c, wm8753);
1805 codec->control_data = spi; 1673 wm8753->control_type = SND_SOC_I2C;
1806 codec->hw_write = (hw_write_t)wm8753_spi_write;
1807 codec->dev = &spi->dev;
1808 1674
1809 dev_set_drvdata(&spi->dev, wm8753); 1675 ret = snd_soc_register_codec(&i2c->dev,
1810 1676 &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
1811 return wm8753_register(wm8753); 1677 if (ret < 0)
1678 kfree(wm8753);
1679 return ret;
1812} 1680}
1813 1681
1814static int __devexit wm8753_spi_remove(struct spi_device *spi) 1682static __devexit int wm8753_i2c_remove(struct i2c_client *client)
1815{ 1683{
1816 struct wm8753_priv *wm8753 = dev_get_drvdata(&spi->dev); 1684 snd_soc_unregister_codec(&client->dev);
1817 wm8753_unregister(wm8753); 1685 kfree(i2c_get_clientdata(client));
1818 return 0; 1686 return 0;
1819} 1687}
1820 1688
1821static struct spi_driver wm8753_spi_driver = { 1689static const struct i2c_device_id wm8753_i2c_id[] = {
1690 { "wm8753", 0 },
1691 { }
1692};
1693MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
1694
1695static struct i2c_driver wm8753_i2c_driver = {
1822 .driver = { 1696 .driver = {
1823 .name = "wm8753", 1697 .name = "wm8753-codec",
1824 .bus = &spi_bus_type, 1698 .owner = THIS_MODULE,
1825 .owner = THIS_MODULE,
1826 }, 1699 },
1827 .probe = wm8753_spi_probe, 1700 .probe = wm8753_i2c_probe,
1828 .remove = __devexit_p(wm8753_spi_remove), 1701 .remove = __devexit_p(wm8753_i2c_remove),
1702 .id_table = wm8753_i2c_id,
1829}; 1703};
1830#endif 1704#endif
1831 1705
1832static int __init wm8753_modinit(void) 1706static int __init wm8753_modinit(void)
1833{ 1707{
1834 int ret; 1708 int ret = 0;
1835#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1709#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1836 ret = i2c_add_driver(&wm8753_i2c_driver); 1710 ret = i2c_add_driver(&wm8753_i2c_driver);
1837 if (ret != 0) 1711 if (ret != 0) {
1838 pr_err("Failed to register WM8753 I2C driver: %d\n", ret); 1712 printk(KERN_ERR "Failed to register wm8753 I2C driver: %d\n",
1713 ret);
1714 }
1839#endif 1715#endif
1840#if defined(CONFIG_SPI_MASTER) 1716#if defined(CONFIG_SPI_MASTER)
1841 ret = spi_register_driver(&wm8753_spi_driver); 1717 ret = spi_register_driver(&wm8753_spi_driver);
1842 if (ret != 0) 1718 if (ret != 0) {
1843 pr_err("Failed to register WM8753 SPI driver: %d\n", ret); 1719 printk(KERN_ERR "Failed to register wm8753 SPI driver: %d\n",
1720 ret);
1721 }
1844#endif 1722#endif
1845 return 0; 1723 return ret;
1846} 1724}
1847module_init(wm8753_modinit); 1725module_init(wm8753_modinit);
1848 1726
diff --git a/sound/soc/codecs/wm8753.h b/sound/soc/codecs/wm8753.h
index 57b2ba244040..94edac144bcb 100644
--- a/sound/soc/codecs/wm8753.h
+++ b/sound/soc/codecs/wm8753.h
@@ -115,7 +115,4 @@
115#define WM8753_DAI_HIFI 0 115#define WM8753_DAI_HIFI 0
116#define WM8753_DAI_VOICE 1 116#define WM8753_DAI_VOICE 1
117 117
118extern struct snd_soc_dai wm8753_dai[2];
119extern struct snd_soc_codec_device soc_codec_dev_wm8753;
120
121#endif 118#endif
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index f8154e661524..04182c464e35 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -31,20 +31,13 @@
31 31
32#include "wm8776.h" 32#include "wm8776.h"
33 33
34static struct snd_soc_codec *wm8776_codec;
35struct snd_soc_codec_device soc_codec_dev_wm8776;
36
37/* codec private data */ 34/* codec private data */
38struct wm8776_priv { 35struct wm8776_priv {
39 struct snd_soc_codec codec; 36 enum snd_soc_control_type control_type;
40 u16 reg_cache[WM8776_CACHEREGNUM]; 37 u16 reg_cache[WM8776_CACHEREGNUM];
41 int sysclk[2]; 38 int sysclk[2];
42}; 39};
43 40
44#ifdef CONFIG_SPI_MASTER
45static int wm8776_spi_write(struct spi_device *spi, const char *data, int len);
46#endif
47
48static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { 41static const u16 wm8776_reg[WM8776_CACHEREGNUM] = {
49 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ 42 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */
50 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ 43 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */
@@ -144,7 +137,7 @@ static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
144 struct snd_soc_codec *codec = dai->codec; 137 struct snd_soc_codec *codec = dai->codec;
145 int reg, iface, master; 138 int reg, iface, master;
146 139
147 switch (dai->id) { 140 switch (dai->driver->id) {
148 case WM8776_DAI_DAC: 141 case WM8776_DAI_DAC:
149 reg = WM8776_DACIFCTRL; 142 reg = WM8776_DACIFCTRL;
150 master = 0x80; 143 master = 0x80;
@@ -226,7 +219,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
226 219
227 iface = 0; 220 iface = 0;
228 221
229 switch (dai->id) { 222 switch (dai->driver->id) {
230 case WM8776_DAI_DAC: 223 case WM8776_DAI_DAC:
231 iface_reg = WM8776_DACIFCTRL; 224 iface_reg = WM8776_DACIFCTRL;
232 master = 0x80; 225 master = 0x80;
@@ -260,7 +253,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
260 /* Only need to set MCLK/LRCLK ratio if we're master */ 253 /* Only need to set MCLK/LRCLK ratio if we're master */
261 if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { 254 if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) {
262 for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { 255 for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) {
263 if (wm8776->sysclk[dai->id] / params_rate(params) 256 if (wm8776->sysclk[dai->driver->id] / params_rate(params)
264 == mclk_ratios[i]) 257 == mclk_ratios[i])
265 break; 258 break;
266 } 259 }
@@ -268,7 +261,7 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
268 if (i == ARRAY_SIZE(mclk_ratios)) { 261 if (i == ARRAY_SIZE(mclk_ratios)) {
269 dev_err(codec->dev, 262 dev_err(codec->dev,
270 "Unable to configure MCLK ratio %d/%d\n", 263 "Unable to configure MCLK ratio %d/%d\n",
271 wm8776->sysclk[dai->id], params_rate(params)); 264 wm8776->sysclk[dai->driver->id], params_rate(params));
272 return -EINVAL; 265 return -EINVAL;
273 } 266 }
274 267
@@ -298,9 +291,9 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai,
298 struct snd_soc_codec *codec = dai->codec; 291 struct snd_soc_codec *codec = dai->codec;
299 struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); 292 struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
300 293
301 BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk)); 294 BUG_ON(dai->driver->id >= ARRAY_SIZE(wm8776->sysclk));
302 295
303 wm8776->sysclk[dai->id] = freq; 296 wm8776->sysclk[dai->driver->id] = freq;
304 297
305 return 0; 298 return 0;
306} 299}
@@ -350,10 +343,10 @@ static struct snd_soc_dai_ops wm8776_adc_ops = {
350 .set_sysclk = wm8776_set_sysclk, 343 .set_sysclk = wm8776_set_sysclk,
351}; 344};
352 345
353struct snd_soc_dai wm8776_dai[] = { 346static struct snd_soc_dai_driver wm8776_dai[] = {
354 { 347 {
355 .name = "WM8776 Playback", 348 .name = "wm8776-hifi-playback",
356 .id = WM8776_DAI_DAC, 349 .id = WM8776_DAI_DAC,
357 .playback = { 350 .playback = {
358 .stream_name = "Playback", 351 .stream_name = "Playback",
359 .channels_min = 2, 352 .channels_min = 2,
@@ -364,8 +357,8 @@ struct snd_soc_dai wm8776_dai[] = {
364 .ops = &wm8776_dac_ops, 357 .ops = &wm8776_dac_ops,
365 }, 358 },
366 { 359 {
367 .name = "WM8776 Capture", 360 .name = "wm8776-hifi-capture",
368 .id = WM8776_DAI_ADC, 361 .id = WM8776_DAI_ADC,
369 .capture = { 362 .capture = {
370 .stream_name = "Capture", 363 .stream_name = "Capture",
371 .channels_min = 2, 364 .channels_min = 2,
@@ -376,23 +369,17 @@ struct snd_soc_dai wm8776_dai[] = {
376 .ops = &wm8776_adc_ops, 369 .ops = &wm8776_adc_ops,
377 }, 370 },
378}; 371};
379EXPORT_SYMBOL_GPL(wm8776_dai);
380 372
381#ifdef CONFIG_PM 373#ifdef CONFIG_PM
382static int wm8776_suspend(struct platform_device *pdev, pm_message_t state) 374static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
383{ 375{
384 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
385 struct snd_soc_codec *codec = socdev->card->codec;
386
387 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); 376 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
388 377
389 return 0; 378 return 0;
390} 379}
391 380
392static int wm8776_resume(struct platform_device *pdev) 381static int wm8776_resume(struct snd_soc_codec *codec)
393{ 382{
394 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
395 struct snd_soc_codec *codec = socdev->card->codec;
396 int i; 383 int i;
397 u8 data[2]; 384 u8 data[2];
398 u16 *cache = codec->reg_cache; 385 u16 *cache = codec->reg_cache;
@@ -415,27 +402,30 @@ static int wm8776_resume(struct platform_device *pdev)
415#define wm8776_resume NULL 402#define wm8776_resume NULL
416#endif 403#endif
417 404
418static int wm8776_probe(struct platform_device *pdev) 405static int wm8776_probe(struct snd_soc_codec *codec)
419{ 406{
420 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 407 struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
421 struct snd_soc_codec *codec;
422 int ret = 0; 408 int ret = 0;
423 409
424 if (wm8776_codec == NULL) { 410 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type);
425 dev_err(&pdev->dev, "Codec device not registered\n"); 411 if (ret < 0) {
426 return -ENODEV; 412 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
413 return ret;
427 } 414 }
428 415
429 socdev->card->codec = wm8776_codec; 416 ret = wm8776_reset(codec);
430 codec = wm8776_codec;
431
432 /* register pcms */
433 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
434 if (ret < 0) { 417 if (ret < 0) {
435 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 418 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
436 goto pcm_err; 419 return ret;
437 } 420 }
438 421
422 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
423
424 /* Latch the update bits; right channel only since we always
425 * update both. */
426 snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
427 snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
428
439 snd_soc_add_controls(codec, wm8776_snd_controls, 429 snd_soc_add_controls(codec, wm8776_snd_controls,
440 ARRAY_SIZE(wm8776_snd_controls)); 430 ARRAY_SIZE(wm8776_snd_controls));
441 snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, 431 snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets,
@@ -443,169 +433,56 @@ static int wm8776_probe(struct platform_device *pdev)
443 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); 433 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
444 434
445 return ret; 435 return ret;
446
447pcm_err:
448 return ret;
449} 436}
450 437
451/* power down chip */ 438/* power down chip */
452static int wm8776_remove(struct platform_device *pdev) 439static int wm8776_remove(struct snd_soc_codec *codec)
453{ 440{
454 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 441 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
455
456 snd_soc_free_pcms(socdev);
457 snd_soc_dapm_free(socdev);
458
459 return 0; 442 return 0;
460} 443}
461 444
462struct snd_soc_codec_device soc_codec_dev_wm8776 = { 445static struct snd_soc_codec_driver soc_codec_dev_wm8776 = {
463 .probe = wm8776_probe, 446 .probe = wm8776_probe,
464 .remove = wm8776_remove, 447 .remove = wm8776_remove,
465 .suspend = wm8776_suspend, 448 .suspend = wm8776_suspend,
466 .resume = wm8776_resume, 449 .resume = wm8776_resume,
450 .set_bias_level = wm8776_set_bias_level,
451 .reg_cache_size = ARRAY_SIZE(wm8776_reg),
452 .reg_word_size = sizeof(u16),
453 .reg_cache_default = wm8776_reg,
467}; 454};
468EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776);
469
470static int wm8776_register(struct wm8776_priv *wm8776,
471 enum snd_soc_control_type control)
472{
473 int ret, i;
474 struct snd_soc_codec *codec = &wm8776->codec;
475
476 if (wm8776_codec) {
477 dev_err(codec->dev, "Another WM8776 is registered\n");
478 ret = -EINVAL;
479 goto err;
480 }
481
482 mutex_init(&codec->mutex);
483 INIT_LIST_HEAD(&codec->dapm_widgets);
484 INIT_LIST_HEAD(&codec->dapm_paths);
485
486 snd_soc_codec_set_drvdata(codec, wm8776);
487 codec->name = "WM8776";
488 codec->owner = THIS_MODULE;
489 codec->bias_level = SND_SOC_BIAS_OFF;
490 codec->set_bias_level = wm8776_set_bias_level;
491 codec->dai = wm8776_dai;
492 codec->num_dai = ARRAY_SIZE(wm8776_dai);
493 codec->reg_cache_size = WM8776_CACHEREGNUM;
494 codec->reg_cache = &wm8776->reg_cache;
495
496 memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg));
497
498 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
499 if (ret < 0) {
500 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
501 goto err;
502 }
503
504 for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++)
505 wm8776_dai[i].dev = codec->dev;
506
507 ret = wm8776_reset(codec);
508 if (ret < 0) {
509 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
510 goto err;
511 }
512
513 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
514
515 /* Latch the update bits; right channel only since we always
516 * update both. */
517 snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
518 snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
519
520 wm8776_codec = codec;
521
522 ret = snd_soc_register_codec(codec);
523 if (ret != 0) {
524 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
525 goto err;
526 }
527
528 ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
529 if (ret != 0) {
530 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
531 goto err_codec;
532 }
533
534 return 0;
535
536err_codec:
537 snd_soc_unregister_codec(codec);
538err:
539 kfree(wm8776);
540 return ret;
541}
542
543static void wm8776_unregister(struct wm8776_priv *wm8776)
544{
545 wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF);
546 snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai));
547 snd_soc_unregister_codec(&wm8776->codec);
548 kfree(wm8776);
549 wm8776_codec = NULL;
550}
551 455
552#if defined(CONFIG_SPI_MASTER) 456#if defined(CONFIG_SPI_MASTER)
553static int wm8776_spi_write(struct spi_device *spi, const char *data, int len)
554{
555 struct spi_transfer t;
556 struct spi_message m;
557 u8 msg[2];
558
559 if (len <= 0)
560 return 0;
561
562 msg[0] = data[0];
563 msg[1] = data[1];
564
565 spi_message_init(&m);
566 memset(&t, 0, (sizeof t));
567
568 t.tx_buf = &msg[0];
569 t.len = len;
570
571 spi_message_add_tail(&t, &m);
572 spi_sync(spi, &m);
573
574 return len;
575}
576
577static int __devinit wm8776_spi_probe(struct spi_device *spi) 457static int __devinit wm8776_spi_probe(struct spi_device *spi)
578{ 458{
579 struct snd_soc_codec *codec;
580 struct wm8776_priv *wm8776; 459 struct wm8776_priv *wm8776;
460 int ret;
581 461
582 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); 462 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
583 if (wm8776 == NULL) 463 if (wm8776 == NULL)
584 return -ENOMEM; 464 return -ENOMEM;
585 465
586 codec = &wm8776->codec; 466 wm8776->control_type = SND_SOC_SPI;
587 codec->control_data = spi; 467 spi_set_drvdata(spi, wm8776);
588 codec->hw_write = (hw_write_t)wm8776_spi_write;
589 codec->dev = &spi->dev;
590 468
591 dev_set_drvdata(&spi->dev, wm8776); 469 ret = snd_soc_register_codec(&spi->dev,
592 470 &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
593 return wm8776_register(wm8776, SND_SOC_SPI); 471 if (ret < 0)
472 kfree(wm8776);
473 return ret;
594} 474}
595 475
596static int __devexit wm8776_spi_remove(struct spi_device *spi) 476static int __devexit wm8776_spi_remove(struct spi_device *spi)
597{ 477{
598 struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev); 478 snd_soc_unregister_codec(&spi->dev);
599 479 kfree(spi_get_drvdata(spi));
600 wm8776_unregister(wm8776);
601
602 return 0; 480 return 0;
603} 481}
604 482
605static struct spi_driver wm8776_spi_driver = { 483static struct spi_driver wm8776_spi_driver = {
606 .driver = { 484 .driver = {
607 .name = "wm8776", 485 .name = "wm8776-codec",
608 .bus = &spi_bus_type,
609 .owner = THIS_MODULE, 486 .owner = THIS_MODULE,
610 }, 487 },
611 .probe = wm8776_spi_probe, 488 .probe = wm8776_spi_probe,
@@ -618,27 +495,26 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
618 const struct i2c_device_id *id) 495 const struct i2c_device_id *id)
619{ 496{
620 struct wm8776_priv *wm8776; 497 struct wm8776_priv *wm8776;
621 struct snd_soc_codec *codec; 498 int ret;
622 499
623 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); 500 wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
624 if (wm8776 == NULL) 501 if (wm8776 == NULL)
625 return -ENOMEM; 502 return -ENOMEM;
626 503
627 codec = &wm8776->codec;
628 codec->hw_write = (hw_write_t)i2c_master_send;
629
630 i2c_set_clientdata(i2c, wm8776); 504 i2c_set_clientdata(i2c, wm8776);
631 codec->control_data = i2c; 505 wm8776->control_type = SND_SOC_I2C;
632
633 codec->dev = &i2c->dev;
634 506
635 return wm8776_register(wm8776, SND_SOC_I2C); 507 ret = snd_soc_register_codec(&i2c->dev,
508 &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
509 if (ret < 0)
510 kfree(wm8776);
511 return ret;
636} 512}
637 513
638static __devexit int wm8776_i2c_remove(struct i2c_client *client) 514static __devexit int wm8776_i2c_remove(struct i2c_client *client)
639{ 515{
640 struct wm8776_priv *wm8776 = i2c_get_clientdata(client); 516 snd_soc_unregister_codec(&client->dev);
641 wm8776_unregister(wm8776); 517 kfree(i2c_get_clientdata(client));
642 return 0; 518 return 0;
643} 519}
644 520
@@ -650,7 +526,7 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
650 526
651static struct i2c_driver wm8776_i2c_driver = { 527static struct i2c_driver wm8776_i2c_driver = {
652 .driver = { 528 .driver = {
653 .name = "wm8776", 529 .name = "wm8776-codec",
654 .owner = THIS_MODULE, 530 .owner = THIS_MODULE,
655 }, 531 },
656 .probe = wm8776_i2c_probe, 532 .probe = wm8776_i2c_probe,
@@ -661,22 +537,22 @@ static struct i2c_driver wm8776_i2c_driver = {
661 537
662static int __init wm8776_modinit(void) 538static int __init wm8776_modinit(void)
663{ 539{
664 int ret; 540 int ret = 0;
665#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 541#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
666 ret = i2c_add_driver(&wm8776_i2c_driver); 542 ret = i2c_add_driver(&wm8776_i2c_driver);
667 if (ret != 0) { 543 if (ret != 0) {
668 printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n", 544 printk(KERN_ERR "Failed to register wm8776 I2C driver: %d\n",
669 ret); 545 ret);
670 } 546 }
671#endif 547#endif
672#if defined(CONFIG_SPI_MASTER) 548#if defined(CONFIG_SPI_MASTER)
673 ret = spi_register_driver(&wm8776_spi_driver); 549 ret = spi_register_driver(&wm8776_spi_driver);
674 if (ret != 0) { 550 if (ret != 0) {
675 printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n", 551 printk(KERN_ERR "Failed to register wm8776 SPI driver: %d\n",
676 ret); 552 ret);
677 } 553 }
678#endif 554#endif
679 return 0; 555 return ret;
680} 556}
681module_init(wm8776_modinit); 557module_init(wm8776_modinit);
682 558
diff --git a/sound/soc/codecs/wm8776.h b/sound/soc/codecs/wm8776.h
index 6606d25d2d83..4cf1c8e0bfc9 100644
--- a/sound/soc/codecs/wm8776.h
+++ b/sound/soc/codecs/wm8776.h
@@ -45,7 +45,4 @@
45#define WM8776_DAI_DAC 0 45#define WM8776_DAI_DAC 0
46#define WM8776_DAI_ADC 1 46#define WM8776_DAI_ADC 1
47 47
48extern struct snd_soc_dai wm8776_dai[];
49extern struct snd_soc_codec_device soc_codec_dev_wm8776;
50
51#endif 48#endif
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
new file mode 100644
index 000000000000..4599e8e95aa2
--- /dev/null
+++ b/sound/soc/codecs/wm8804.c
@@ -0,0 +1,833 @@
1/*
2 * wm8804.c -- WM8804 S/PDIF transceiver driver
3 *
4 * Copyright 2010 Wolfson Microelectronics plc
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/init.h>
16#include <linux/delay.h>
17#include <linux/pm.h>
18#include <linux/i2c.h>
19#include <linux/spi/spi.h>
20#include <linux/regulator/consumer.h>
21#include <linux/slab.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/pcm_params.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/initval.h>
28#include <sound/tlv.h>
29
30#include "wm8804.h"
31
32#define WM8804_NUM_SUPPLIES 2
33static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
34 "PVDD",
35 "DVDD"
36};
37
38static const u8 wm8804_reg_defs[] = {
39 0x05, /* R0 - RST/DEVID1 */
40 0x88, /* R1 - DEVID2 */
41 0x04, /* R2 - DEVREV */
42 0x21, /* R3 - PLL1 */
43 0xFD, /* R4 - PLL2 */
44 0x36, /* R5 - PLL3 */
45 0x07, /* R6 - PLL4 */
46 0x16, /* R7 - PLL5 */
47 0x18, /* R8 - PLL6 */
48 0xFF, /* R9 - SPDMODE */
49 0x00, /* R10 - INTMASK */
50 0x00, /* R11 - INTSTAT */
51 0x00, /* R12 - SPDSTAT */
52 0x00, /* R13 - RXCHAN1 */
53 0x00, /* R14 - RXCHAN2 */
54 0x00, /* R15 - RXCHAN3 */
55 0x00, /* R16 - RXCHAN4 */
56 0x00, /* R17 - RXCHAN5 */
57 0x00, /* R18 - SPDTX1 */
58 0x00, /* R19 - SPDTX2 */
59 0x00, /* R20 - SPDTX3 */
60 0x71, /* R21 - SPDTX4 */
61 0x0B, /* R22 - SPDTX5 */
62 0x70, /* R23 - GPO0 */
63 0x57, /* R24 - GPO1 */
64 0x00, /* R25 */
65 0x42, /* R26 - GPO2 */
66 0x06, /* R27 - AIFTX */
67 0x06, /* R28 - AIFRX */
68 0x80, /* R29 - SPDRX1 */
69 0x07, /* R30 - PWRDN */
70};
71
72struct wm8804_priv {
73 enum snd_soc_control_type control_type;
74 struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
75 struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
76 struct snd_soc_codec *codec;
77};
78
79static int txsrc_get(struct snd_kcontrol *kcontrol,
80 struct snd_ctl_elem_value *ucontrol);
81
82static int txsrc_put(struct snd_kcontrol *kcontrol,
83 struct snd_ctl_elem_value *ucontrol);
84
85/*
86 * We can't use the same notifier block for more than one supply and
87 * there's no way I can see to get from a callback to the caller
88 * except container_of().
89 */
90#define WM8804_REGULATOR_EVENT(n) \
91static int wm8804_regulator_event_##n(struct notifier_block *nb, \
92 unsigned long event, void *data) \
93{ \
94 struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
95 disable_nb[n]); \
96 if (event & REGULATOR_EVENT_DISABLE) { \
97 wm8804->codec->cache_sync = 1; \
98 } \
99 return 0; \
100}
101
102WM8804_REGULATOR_EVENT(0)
103WM8804_REGULATOR_EVENT(1)
104
105static const char *txsrc_text[] = { "S/PDIF RX", "AIF" };
106static const SOC_ENUM_SINGLE_EXT_DECL(txsrc, txsrc_text);
107
108static const struct snd_kcontrol_new wm8804_snd_controls[] = {
109 SOC_ENUM_EXT("Input Source", txsrc, txsrc_get, txsrc_put),
110 SOC_SINGLE("TX Playback Switch", WM8804_PWRDN, 2, 1, 1),
111 SOC_SINGLE("AIF Playback Switch", WM8804_PWRDN, 4, 1, 1)
112};
113
114static int txsrc_get(struct snd_kcontrol *kcontrol,
115 struct snd_ctl_elem_value *ucontrol)
116{
117 struct snd_soc_codec *codec;
118 unsigned int src;
119
120 codec = snd_kcontrol_chip(kcontrol);
121 src = snd_soc_read(codec, WM8804_SPDTX4);
122 if (src & 0x40)
123 ucontrol->value.integer.value[0] = 1;
124 else
125 ucontrol->value.integer.value[0] = 0;
126
127 return 0;
128}
129
130static int txsrc_put(struct snd_kcontrol *kcontrol,
131 struct snd_ctl_elem_value *ucontrol)
132{
133 struct snd_soc_codec *codec;
134 unsigned int src, txpwr;
135
136 codec = snd_kcontrol_chip(kcontrol);
137
138 if (ucontrol->value.integer.value[0] != 0
139 && ucontrol->value.integer.value[0] != 1)
140 return -EINVAL;
141
142 src = snd_soc_read(codec, WM8804_SPDTX4);
143 switch ((src & 0x40) >> 6) {
144 case 0:
145 if (!ucontrol->value.integer.value[0])
146 return 0;
147 break;
148 case 1:
149 if (ucontrol->value.integer.value[1])
150 return 0;
151 break;
152 }
153
154 /* save the current power state of the transmitter */
155 txpwr = snd_soc_read(codec, WM8804_PWRDN) & 0x4;
156 /* power down the transmitter */
157 snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, 0x4);
158 /* set the tx source */
159 snd_soc_update_bits(codec, WM8804_SPDTX4, 0x40,
160 ucontrol->value.integer.value[0] << 6);
161
162 if (ucontrol->value.integer.value[0]) {
163 /* power down the receiver */
164 snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0x2);
165 /* power up the AIF */
166 snd_soc_update_bits(codec, WM8804_PWRDN, 0x10, 0);
167 } else {
168 /* don't power down the AIF -- may be used as an output */
169 /* power up the receiver */
170 snd_soc_update_bits(codec, WM8804_PWRDN, 0x2, 0);
171 }
172
173 /* restore the transmitter's configuration */
174 snd_soc_update_bits(codec, WM8804_PWRDN, 0x4, txpwr);
175
176 return 0;
177}
178
179static int wm8804_volatile(unsigned int reg)
180{
181 switch (reg) {
182 case WM8804_RST_DEVID1:
183 case WM8804_DEVID2:
184 case WM8804_DEVREV:
185 case WM8804_INTSTAT:
186 case WM8804_SPDSTAT:
187 case WM8804_RXCHAN1:
188 case WM8804_RXCHAN2:
189 case WM8804_RXCHAN3:
190 case WM8804_RXCHAN4:
191 case WM8804_RXCHAN5:
192 return 1;
193 default:
194 break;
195 }
196
197 return 0;
198}
199
200static int wm8804_reset(struct snd_soc_codec *codec)
201{
202 return snd_soc_write(codec, WM8804_RST_DEVID1, 0x0);
203}
204
205static int wm8804_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
206{
207 struct snd_soc_codec *codec;
208 u16 format, master, bcp, lrp;
209
210 codec = dai->codec;
211
212 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
213 case SND_SOC_DAIFMT_I2S:
214 format = 0x2;
215 break;
216 case SND_SOC_DAIFMT_RIGHT_J:
217 format = 0x0;
218 break;
219 case SND_SOC_DAIFMT_LEFT_J:
220 format = 0x1;
221 break;
222 case SND_SOC_DAIFMT_DSP_A:
223 case SND_SOC_DAIFMT_DSP_B:
224 format = 0x3;
225 break;
226 default:
227 dev_err(dai->dev, "Unknown dai format\n");
228 return -EINVAL;
229 }
230
231 /* set data format */
232 snd_soc_update_bits(codec, WM8804_AIFTX, 0x3, format);
233 snd_soc_update_bits(codec, WM8804_AIFRX, 0x3, format);
234
235 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
236 case SND_SOC_DAIFMT_CBM_CFM:
237 master = 1;
238 break;
239 case SND_SOC_DAIFMT_CBS_CFS:
240 master = 0;
241 break;
242 default:
243 dev_err(dai->dev, "Unknown master/slave configuration\n");
244 return -EINVAL;
245 }
246
247 /* set master/slave mode */
248 snd_soc_update_bits(codec, WM8804_AIFRX, 0x40, master << 6);
249
250 bcp = lrp = 0;
251 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
252 case SND_SOC_DAIFMT_NB_NF:
253 break;
254 case SND_SOC_DAIFMT_IB_IF:
255 bcp = lrp = 1;
256 break;
257 case SND_SOC_DAIFMT_IB_NF:
258 bcp = 1;
259 break;
260 case SND_SOC_DAIFMT_NB_IF:
261 lrp = 1;
262 break;
263 default:
264 dev_err(dai->dev, "Unknown polarity configuration\n");
265 return -EINVAL;
266 }
267
268 /* set frame inversion */
269 snd_soc_update_bits(codec, WM8804_AIFTX, 0x10 | 0x20,
270 (bcp << 4) | (lrp << 5));
271 snd_soc_update_bits(codec, WM8804_AIFRX, 0x10 | 0x20,
272 (bcp << 4) | (lrp << 5));
273 return 0;
274}
275
276static int wm8804_hw_params(struct snd_pcm_substream *substream,
277 struct snd_pcm_hw_params *params,
278 struct snd_soc_dai *dai)
279{
280 struct snd_soc_codec *codec;
281 u16 blen;
282
283 codec = dai->codec;
284
285 switch (params_format(params)) {
286 case SNDRV_PCM_FORMAT_S16_LE:
287 blen = 0x0;
288 break;
289 case SNDRV_PCM_FORMAT_S20_3LE:
290 blen = 0x1;
291 break;
292 case SNDRV_PCM_FORMAT_S24_LE:
293 blen = 0x2;
294 break;
295 default:
296 dev_err(dai->dev, "Unsupported word length: %u\n",
297 params_format(params));
298 return -EINVAL;
299 }
300
301 /* set word length */
302 snd_soc_update_bits(codec, WM8804_AIFTX, 0xc, blen << 2);
303 snd_soc_update_bits(codec, WM8804_AIFRX, 0xc, blen << 2);
304
305 return 0;
306}
307
308struct pll_div {
309 u32 prescale:1;
310 u32 mclkdiv:1;
311 u32 freqmode:2;
312 u32 n:4;
313 u32 k:22;
314};
315
316/* PLL rate to output rate divisions */
317static struct {
318 unsigned int div;
319 unsigned int freqmode;
320 unsigned int mclkdiv;
321} post_table[] = {
322 { 2, 0, 0 },
323 { 4, 0, 1 },
324 { 4, 1, 0 },
325 { 8, 1, 1 },
326 { 8, 2, 0 },
327 { 16, 2, 1 },
328 { 12, 3, 0 },
329 { 24, 3, 1 }
330};
331
332#define FIXED_PLL_SIZE ((1ULL << 22) * 10)
333static int pll_factors(struct pll_div *pll_div, unsigned int target,
334 unsigned int source)
335{
336 u64 Kpart;
337 unsigned long int K, Ndiv, Nmod, tmp;
338 int i;
339
340 /*
341 * Scale the output frequency up; the PLL should run in the
342 * region of 90-100MHz.
343 */
344 for (i = 0; i < ARRAY_SIZE(post_table); i++) {
345 tmp = target * post_table[i].div;
346 if (tmp >= 90000000 && tmp <= 100000000) {
347 pll_div->freqmode = post_table[i].freqmode;
348 pll_div->mclkdiv = post_table[i].mclkdiv;
349 target *= post_table[i].div;
350 break;
351 }
352 }
353
354 if (i == ARRAY_SIZE(post_table)) {
355 pr_err("%s: Unable to scale output frequency: %uHz\n",
356 __func__, target);
357 return -EINVAL;
358 }
359
360 pll_div->prescale = 0;
361 Ndiv = target / source;
362 if (Ndiv < 5) {
363 source >>= 1;
364 pll_div->prescale = 1;
365 Ndiv = target / source;
366 }
367
368 if (Ndiv < 5 || Ndiv > 13) {
369 pr_err("%s: WM8804 N value is not within the recommended range: %lu\n",
370 __func__, Ndiv);
371 return -EINVAL;
372 }
373 pll_div->n = Ndiv;
374
375 Nmod = target % source;
376 Kpart = FIXED_PLL_SIZE * (u64)Nmod;
377
378 do_div(Kpart, source);
379
380 K = Kpart & 0xffffffff;
381 if ((K % 10) >= 5)
382 K += 5;
383 K /= 10;
384 pll_div->k = K;
385
386 return 0;
387}
388
389static int wm8804_set_pll(struct snd_soc_dai *dai, int pll_id,
390 int source, unsigned int freq_in,
391 unsigned int freq_out)
392{
393 struct snd_soc_codec *codec;
394
395 codec = dai->codec;
396 if (!freq_in || !freq_out) {
397 /* disable the PLL */
398 snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1);
399 return 0;
400 } else {
401 int ret;
402 struct pll_div pll_div;
403
404 ret = pll_factors(&pll_div, freq_out, freq_in);
405 if (ret)
406 return ret;
407
408 /* power down the PLL before reprogramming it */
409 snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0x1);
410
411 if (!freq_in || !freq_out)
412 return 0;
413
414 /* set PLLN and PRESCALE */
415 snd_soc_update_bits(codec, WM8804_PLL4, 0xf | 0x10,
416 pll_div.n | (pll_div.prescale << 4));
417 /* set mclkdiv and freqmode */
418 snd_soc_update_bits(codec, WM8804_PLL5, 0x3 | 0x8,
419 pll_div.freqmode | (pll_div.mclkdiv << 3));
420 /* set PLLK */
421 snd_soc_write(codec, WM8804_PLL1, pll_div.k & 0xff);
422 snd_soc_write(codec, WM8804_PLL2, (pll_div.k >> 8) & 0xff);
423 snd_soc_write(codec, WM8804_PLL3, pll_div.k >> 16);
424
425 /* power up the PLL */
426 snd_soc_update_bits(codec, WM8804_PWRDN, 0x1, 0);
427 }
428
429 return 0;
430}
431
432static int wm8804_set_sysclk(struct snd_soc_dai *dai,
433 int clk_id, unsigned int freq, int dir)
434{
435 struct snd_soc_codec *codec;
436
437 codec = dai->codec;
438
439 switch (clk_id) {
440 case WM8804_TX_CLKSRC_MCLK:
441 if ((freq >= 10000000 && freq <= 14400000)
442 || (freq >= 16280000 && freq <= 27000000))
443 snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0x80);
444 else {
445 dev_err(dai->dev, "OSCCLOCK is not within the "
446 "recommended range: %uHz\n", freq);
447 return -EINVAL;
448 }
449 break;
450 case WM8804_TX_CLKSRC_PLL:
451 snd_soc_update_bits(codec, WM8804_PLL6, 0x80, 0);
452 break;
453 case WM8804_CLKOUT_SRC_CLK1:
454 snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0);
455 break;
456 case WM8804_CLKOUT_SRC_OSCCLK:
457 snd_soc_update_bits(codec, WM8804_PLL6, 0x8, 0x8);
458 break;
459 default:
460 dev_err(dai->dev, "Unknown clock source: %d\n", clk_id);
461 return -EINVAL;
462 }
463
464 return 0;
465}
466
467static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
468 int div_id, int div)
469{
470 struct snd_soc_codec *codec;
471
472 codec = dai->codec;
473 switch (div_id) {
474 case WM8804_CLKOUT_DIV:
475 snd_soc_update_bits(codec, WM8804_PLL5, 0x30,
476 (div & 0x3) << 4);
477 break;
478 default:
479 dev_err(dai->dev, "Unknown clock divider: %d\n", div_id);
480 return -EINVAL;
481 }
482 return 0;
483}
484
485static void wm8804_sync_cache(struct snd_soc_codec *codec)
486{
487 short i;
488 u8 *cache;
489
490 if (!codec->cache_sync)
491 return;
492
493 codec->cache_only = 0;
494 cache = codec->reg_cache;
495 for (i = 0; i < codec->driver->reg_cache_size; i++) {
496 if (i == WM8804_RST_DEVID1 || cache[i] == wm8804_reg_defs[i])
497 continue;
498 snd_soc_write(codec, i, cache[i]);
499 }
500 codec->cache_sync = 0;
501}
502
503static int wm8804_set_bias_level(struct snd_soc_codec *codec,
504 enum snd_soc_bias_level level)
505{
506 int ret;
507 struct wm8804_priv *wm8804;
508
509 wm8804 = snd_soc_codec_get_drvdata(codec);
510 switch (level) {
511 case SND_SOC_BIAS_ON:
512 break;
513 case SND_SOC_BIAS_PREPARE:
514 /* power up the OSC and the PLL */
515 snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0);
516 break;
517 case SND_SOC_BIAS_STANDBY:
518 if (codec->bias_level == SND_SOC_BIAS_OFF) {
519 ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
520 wm8804->supplies);
521 if (ret) {
522 dev_err(codec->dev,
523 "Failed to enable supplies: %d\n",
524 ret);
525 return ret;
526 }
527 wm8804_sync_cache(codec);
528 }
529 /* power down the OSC and the PLL */
530 snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
531 break;
532 case SND_SOC_BIAS_OFF:
533 /* power down the OSC and the PLL */
534 snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
535 regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies),
536 wm8804->supplies);
537 break;
538 }
539
540 codec->bias_level = level;
541 return 0;
542}
543
544#ifdef CONFIG_PM
545static int wm8804_suspend(struct snd_soc_codec *codec, pm_message_t state)
546{
547 wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
548 return 0;
549}
550
551static int wm8804_resume(struct snd_soc_codec *codec)
552{
553 wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
554 return 0;
555}
556#else
557#define wm8804_suspend NULL
558#define wm8804_resume NULL
559#endif
560
561static int wm8804_remove(struct snd_soc_codec *codec)
562{
563 struct wm8804_priv *wm8804;
564 int i;
565
566 wm8804 = snd_soc_codec_get_drvdata(codec);
567 wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
568
569 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); ++i)
570 regulator_unregister_notifier(wm8804->supplies[i].consumer,
571 &wm8804->disable_nb[i]);
572 regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
573 return 0;
574}
575
576static int wm8804_probe(struct snd_soc_codec *codec)
577{
578 struct wm8804_priv *wm8804;
579 int i, id1, id2, ret;
580
581 wm8804 = snd_soc_codec_get_drvdata(codec);
582 wm8804->codec = codec;
583
584 codec->idle_bias_off = 1;
585
586 ret = snd_soc_codec_set_cache_io(codec, 8, 8, wm8804->control_type);
587 if (ret < 0) {
588 dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
589 return ret;
590 }
591
592 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++)
593 wm8804->supplies[i].supply = wm8804_supply_names[i];
594
595 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8804->supplies),
596 wm8804->supplies);
597 if (ret) {
598 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
599 return ret;
600 }
601
602 wm8804->disable_nb[0].notifier_call = wm8804_regulator_event_0;
603 wm8804->disable_nb[1].notifier_call = wm8804_regulator_event_1;
604
605 /* This should really be moved into the regulator core */
606 for (i = 0; i < ARRAY_SIZE(wm8804->supplies); i++) {
607 ret = regulator_register_notifier(wm8804->supplies[i].consumer,
608 &wm8804->disable_nb[i]);
609 if (ret != 0) {
610 dev_err(codec->dev,
611 "Failed to register regulator notifier: %d\n",
612 ret);
613 }
614 }
615
616 ret = regulator_bulk_enable(ARRAY_SIZE(wm8804->supplies),
617 wm8804->supplies);
618 if (ret) {
619 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
620 goto err_reg_get;
621 }
622
623 id1 = snd_soc_read(codec, WM8804_RST_DEVID1);
624 if (id1 < 0) {
625 dev_err(codec->dev, "Failed to read device ID: %d\n", id1);
626 ret = id1;
627 goto err_reg_enable;
628 }
629
630 id2 = snd_soc_read(codec, WM8804_DEVID2);
631 if (id2 < 0) {
632 dev_err(codec->dev, "Failed to read device ID: %d\n", id2);
633 ret = id2;
634 goto err_reg_enable;
635 }
636
637 id2 = (id2 << 8) | id1;
638
639 if (id2 != ((wm8804_reg_defs[WM8804_DEVID2] << 8)
640 | wm8804_reg_defs[WM8804_RST_DEVID1])) {
641 dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
642 ret = -EINVAL;
643 goto err_reg_enable;
644 }
645
646 ret = snd_soc_read(codec, WM8804_DEVREV);
647 if (ret < 0) {
648 dev_err(codec->dev, "Failed to read device revision: %d\n",
649 ret);
650 goto err_reg_enable;
651 }
652 dev_info(codec->dev, "revision %c\n", ret + 'A');
653
654 ret = wm8804_reset(codec);
655 if (ret < 0) {
656 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
657 goto err_reg_enable;
658 }
659
660 wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
661
662 snd_soc_add_controls(codec, wm8804_snd_controls,
663 ARRAY_SIZE(wm8804_snd_controls));
664 return 0;
665
666err_reg_enable:
667 regulator_bulk_disable(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
668err_reg_get:
669 regulator_bulk_free(ARRAY_SIZE(wm8804->supplies), wm8804->supplies);
670 return ret;
671}
672
673static struct snd_soc_dai_ops wm8804_dai_ops = {
674 .hw_params = wm8804_hw_params,
675 .set_fmt = wm8804_set_fmt,
676 .set_sysclk = wm8804_set_sysclk,
677 .set_clkdiv = wm8804_set_clkdiv,
678 .set_pll = wm8804_set_pll
679};
680
681#define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
682 SNDRV_PCM_FMTBIT_S24_LE)
683
684static struct snd_soc_dai_driver wm8804_dai = {
685 .name = "wm8804-spdif",
686 .playback = {
687 .stream_name = "Playback",
688 .channels_min = 2,
689 .channels_max = 2,
690 .rates = SNDRV_PCM_RATE_8000_192000,
691 .formats = WM8804_FORMATS,
692 },
693 .capture = {
694 .stream_name = "Capture",
695 .channels_min = 2,
696 .channels_max = 2,
697 .rates = SNDRV_PCM_RATE_8000_192000,
698 .formats = WM8804_FORMATS,
699 },
700 .ops = &wm8804_dai_ops,
701 .symmetric_rates = 1
702};
703
704static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
705 .probe = wm8804_probe,
706 .remove = wm8804_remove,
707 .suspend = wm8804_suspend,
708 .resume = wm8804_resume,
709 .set_bias_level = wm8804_set_bias_level,
710 .reg_cache_size = ARRAY_SIZE(wm8804_reg_defs),
711 .reg_word_size = sizeof(u8),
712 .reg_cache_default = wm8804_reg_defs,
713 .volatile_register = wm8804_volatile
714};
715
716#if defined(CONFIG_SPI_MASTER)
717static int __devinit wm8804_spi_probe(struct spi_device *spi)
718{
719 struct wm8804_priv *wm8804;
720 int ret;
721
722 wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
723 if (!wm8804)
724 return -ENOMEM;
725
726 wm8804->control_type = SND_SOC_SPI;
727 spi_set_drvdata(spi, wm8804);
728
729 ret = snd_soc_register_codec(&spi->dev,
730 &soc_codec_dev_wm8804, &wm8804_dai, 1);
731 if (ret < 0)
732 kfree(wm8804);
733 return ret;
734}
735
736static int __devexit wm8804_spi_remove(struct spi_device *spi)
737{
738 snd_soc_unregister_codec(&spi->dev);
739 kfree(spi_get_drvdata(spi));
740 return 0;
741}
742
743static struct spi_driver wm8804_spi_driver = {
744 .driver = {
745 .name = "wm8804",
746 .owner = THIS_MODULE,
747 },
748 .probe = wm8804_spi_probe,
749 .remove = __devexit_p(wm8804_spi_remove)
750};
751#endif
752
753#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
754static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
755 const struct i2c_device_id *id)
756{
757 struct wm8804_priv *wm8804;
758 int ret;
759
760 wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
761 if (!wm8804)
762 return -ENOMEM;
763
764 wm8804->control_type = SND_SOC_I2C;
765 i2c_set_clientdata(i2c, wm8804);
766
767 ret = snd_soc_register_codec(&i2c->dev,
768 &soc_codec_dev_wm8804, &wm8804_dai, 1);
769 if (ret < 0)
770 kfree(wm8804);
771 return ret;
772}
773
774static __devexit int wm8804_i2c_remove(struct i2c_client *client)
775{
776 snd_soc_unregister_codec(&client->dev);
777 kfree(i2c_get_clientdata(client));
778 return 0;
779}
780
781static const struct i2c_device_id wm8804_i2c_id[] = {
782 { "wm8804", 0 },
783 { }
784};
785MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
786
787static struct i2c_driver wm8804_i2c_driver = {
788 .driver = {
789 .name = "wm8804",
790 .owner = THIS_MODULE,
791 },
792 .probe = wm8804_i2c_probe,
793 .remove = __devexit_p(wm8804_i2c_remove),
794 .id_table = wm8804_i2c_id
795};
796#endif
797
798static int __init wm8804_modinit(void)
799{
800 int ret = 0;
801
802#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
803 ret = i2c_add_driver(&wm8804_i2c_driver);
804 if (ret) {
805 printk(KERN_ERR "Failed to register wm8804 I2C driver: %d\n",
806 ret);
807 }
808#endif
809#if defined(CONFIG_SPI_MASTER)
810 ret = spi_register_driver(&wm8804_spi_driver);
811 if (ret != 0) {
812 printk(KERN_ERR "Failed to register wm8804 SPI driver: %d\n",
813 ret);
814 }
815#endif
816 return ret;
817}
818module_init(wm8804_modinit);
819
820static void __exit wm8804_exit(void)
821{
822#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
823 i2c_del_driver(&wm8804_i2c_driver);
824#endif
825#if defined(CONFIG_SPI_MASTER)
826 spi_unregister_driver(&wm8804_spi_driver);
827#endif
828}
829module_exit(wm8804_exit);
830
831MODULE_DESCRIPTION("ASoC WM8804 driver");
832MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
833MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8804.h b/sound/soc/codecs/wm8804.h
new file mode 100644
index 000000000000..8ec14f5573cb
--- /dev/null
+++ b/sound/soc/codecs/wm8804.h
@@ -0,0 +1,61 @@
1/*
2 * wm8804.h -- WM8804 S/PDIF transceiver driver
3 *
4 * Copyright 2010 Wolfson Microelectronics plc
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _WM8804_H
14#define _WM8804_H
15
16/*
17 * Register values.
18 */
19#define WM8804_RST_DEVID1 0x00
20#define WM8804_DEVID2 0x01
21#define WM8804_DEVREV 0x02
22#define WM8804_PLL1 0x03
23#define WM8804_PLL2 0x04
24#define WM8804_PLL3 0x05
25#define WM8804_PLL4 0x06
26#define WM8804_PLL5 0x07
27#define WM8804_PLL6 0x08
28#define WM8804_SPDMODE 0x09
29#define WM8804_INTMASK 0x0A
30#define WM8804_INTSTAT 0x0B
31#define WM8804_SPDSTAT 0x0C
32#define WM8804_RXCHAN1 0x0D
33#define WM8804_RXCHAN2 0x0E
34#define WM8804_RXCHAN3 0x0F
35#define WM8804_RXCHAN4 0x10
36#define WM8804_RXCHAN5 0x11
37#define WM8804_SPDTX1 0x12
38#define WM8804_SPDTX2 0x13
39#define WM8804_SPDTX3 0x14
40#define WM8804_SPDTX4 0x15
41#define WM8804_SPDTX5 0x16
42#define WM8804_GPO0 0x17
43#define WM8804_GPO1 0x18
44#define WM8804_GPO2 0x1A
45#define WM8804_AIFTX 0x1B
46#define WM8804_AIFRX 0x1C
47#define WM8804_SPDRX1 0x1D
48#define WM8804_PWRDN 0x1E
49
50#define WM8804_REGISTER_COUNT 30
51#define WM8804_MAX_REGISTER 0x1E
52
53#define WM8804_TX_CLKSRC_MCLK 1
54#define WM8804_TX_CLKSRC_PLL 2
55
56#define WM8804_CLKOUT_SRC_CLK1 3
57#define WM8804_CLKOUT_SRC_OSCCLK 4
58
59#define WM8804_CLKOUT_DIV 1
60
61#endif /* _WM8804_H */
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 5da17a704e5a..b4f11724a63f 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -23,6 +23,7 @@
23#include <linux/delay.h> 23#include <linux/delay.h>
24#include <linux/pm.h> 24#include <linux/pm.h>
25#include <linux/i2c.h> 25#include <linux/i2c.h>
26#include <linux/spi/spi.h>
26#include <linux/platform_device.h> 27#include <linux/platform_device.h>
27#include <linux/slab.h> 28#include <linux/slab.h>
28#include <sound/core.h> 29#include <sound/core.h>
@@ -137,11 +138,8 @@
137 138
138#define WM8900_LRC_MASK 0xfc00 139#define WM8900_LRC_MASK 0xfc00
139 140
140struct snd_soc_codec_device soc_codec_dev_wm8900;
141
142struct wm8900_priv { 141struct wm8900_priv {
143 struct snd_soc_codec codec; 142 enum snd_soc_control_type control_type;
144
145 u16 reg_cache[WM8900_MAXREG]; 143 u16 reg_cache[WM8900_MAXREG];
146 144
147 u32 fll_in; /* FLL input frequency */ 145 u32 fll_in; /* FLL input frequency */
@@ -627,8 +625,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
627 struct snd_soc_dai *dai) 625 struct snd_soc_dai *dai)
628{ 626{
629 struct snd_soc_pcm_runtime *rtd = substream->private_data; 627 struct snd_soc_pcm_runtime *rtd = substream->private_data;
630 struct snd_soc_device *socdev = rtd->socdev; 628 struct snd_soc_codec *codec = rtd->codec;
631 struct snd_soc_codec *codec = socdev->card->codec;
632 u16 reg; 629 u16 reg;
633 630
634 reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; 631 reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60;
@@ -1015,8 +1012,8 @@ static struct snd_soc_dai_ops wm8900_dai_ops = {
1015 .digital_mute = wm8900_digital_mute, 1012 .digital_mute = wm8900_digital_mute,
1016}; 1013};
1017 1014
1018struct snd_soc_dai wm8900_dai = { 1015static struct snd_soc_dai_driver wm8900_dai = {
1019 .name = "WM8900 HiFi", 1016 .name = "wm8900-hifi",
1020 .playback = { 1017 .playback = {
1021 .stream_name = "HiFi Playback", 1018 .stream_name = "HiFi Playback",
1022 .channels_min = 1, 1019 .channels_min = 1,
@@ -1033,7 +1030,6 @@ struct snd_soc_dai wm8900_dai = {
1033 }, 1030 },
1034 .ops = &wm8900_dai_ops, 1031 .ops = &wm8900_dai_ops,
1035}; 1032};
1036EXPORT_SYMBOL_GPL(wm8900_dai);
1037 1033
1038static int wm8900_set_bias_level(struct snd_soc_codec *codec, 1034static int wm8900_set_bias_level(struct snd_soc_codec *codec,
1039 enum snd_soc_bias_level level) 1035 enum snd_soc_bias_level level)
@@ -1128,10 +1124,8 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
1128 return 0; 1124 return 0;
1129} 1125}
1130 1126
1131static int wm8900_suspend(struct platform_device *pdev, pm_message_t state) 1127static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)
1132{ 1128{
1133 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1134 struct snd_soc_codec *codec = socdev->card->codec;
1135 struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); 1129 struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
1136 int fll_out = wm8900->fll_out; 1130 int fll_out = wm8900->fll_out;
1137 int fll_in = wm8900->fll_in; 1131 int fll_in = wm8900->fll_in;
@@ -1140,7 +1134,7 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
1140 /* Stop the FLL in an orderly fashion */ 1134 /* Stop the FLL in an orderly fashion */
1141 ret = wm8900_set_fll(codec, 0, 0, 0); 1135 ret = wm8900_set_fll(codec, 0, 0, 0);
1142 if (ret != 0) { 1136 if (ret != 0) {
1143 dev_err(&pdev->dev, "Failed to stop FLL\n"); 1137 dev_err(codec->dev, "Failed to stop FLL\n");
1144 return ret; 1138 return ret;
1145 } 1139 }
1146 1140
@@ -1152,10 +1146,8 @@ static int wm8900_suspend(struct platform_device *pdev, pm_message_t state)
1152 return 0; 1146 return 0;
1153} 1147}
1154 1148
1155static int wm8900_resume(struct platform_device *pdev) 1149static int wm8900_resume(struct snd_soc_codec *codec)
1156{ 1150{
1157 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1158 struct snd_soc_codec *codec = socdev->card->codec;
1159 struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); 1151 struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
1160 u16 *cache; 1152 u16 *cache;
1161 int i, ret; 1153 int i, ret;
@@ -1176,7 +1168,7 @@ static int wm8900_resume(struct platform_device *pdev)
1176 1168
1177 ret = wm8900_set_fll(codec, 0, fll_in, fll_out); 1169 ret = wm8900_set_fll(codec, 0, fll_in, fll_out);
1178 if (ret != 0) { 1170 if (ret != 0) {
1179 dev_err(&pdev->dev, "Failed to restart FLL\n"); 1171 dev_err(codec->dev, "Failed to restart FLL\n");
1180 return ret; 1172 return ret;
1181 } 1173 }
1182 } 1174 }
@@ -1186,60 +1178,32 @@ static int wm8900_resume(struct platform_device *pdev)
1186 snd_soc_write(codec, i, cache[i]); 1178 snd_soc_write(codec, i, cache[i]);
1187 kfree(cache); 1179 kfree(cache);
1188 } else 1180 } else
1189 dev_err(&pdev->dev, "Unable to allocate register cache\n"); 1181 dev_err(codec->dev, "Unable to allocate register cache\n");
1190 1182
1191 return 0; 1183 return 0;
1192} 1184}
1193 1185
1194static struct snd_soc_codec *wm8900_codec; 1186static int wm8900_probe(struct snd_soc_codec *codec)
1195
1196static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1197 const struct i2c_device_id *id)
1198{ 1187{
1199 struct wm8900_priv *wm8900; 1188 struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
1200 struct snd_soc_codec *codec; 1189 int ret = 0, reg;
1201 unsigned int reg;
1202 int ret;
1203
1204 wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
1205 if (wm8900 == NULL)
1206 return -ENOMEM;
1207 1190
1208 codec = &wm8900->codec; 1191 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type);
1209 snd_soc_codec_set_drvdata(codec, wm8900);
1210 codec->reg_cache = &wm8900->reg_cache[0];
1211 codec->reg_cache_size = WM8900_MAXREG;
1212
1213 mutex_init(&codec->mutex);
1214 INIT_LIST_HEAD(&codec->dapm_widgets);
1215 INIT_LIST_HEAD(&codec->dapm_paths);
1216
1217 codec->name = "WM8900";
1218 codec->owner = THIS_MODULE;
1219 codec->dai = &wm8900_dai;
1220 codec->num_dai = 1;
1221 codec->control_data = i2c;
1222 codec->set_bias_level = wm8900_set_bias_level;
1223 codec->volatile_register = wm8900_volatile_register;
1224 codec->dev = &i2c->dev;
1225
1226 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1227 if (ret != 0) { 1192 if (ret != 0) {
1228 dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); 1193 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1229 goto err; 1194 return ret;
1230 } 1195 }
1231 1196
1232 reg = snd_soc_read(codec, WM8900_REG_ID); 1197 reg = snd_soc_read(codec, WM8900_REG_ID);
1233 if (reg != 0x8900) { 1198 if (reg != 0x8900) {
1234 dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); 1199 dev_err(codec->dev, "Device is not a WM8900 - ID %x\n", reg);
1235 ret = -ENODEV; 1200 return -ENODEV;
1236 goto err;
1237 } 1201 }
1238 1202
1239 /* Read back from the chip */ 1203 /* Read back from the chip */
1240 reg = snd_soc_read(codec, WM8900_REG_POWER1); 1204 reg = snd_soc_read(codec, WM8900_REG_POWER1);
1241 reg = (reg >> 12) & 0xf; 1205 reg = (reg >> 12) & 0xf;
1242 dev_info(&i2c->dev, "WM8900 revision %d\n", reg); 1206 dev_info(codec->dev, "WM8900 revision %d\n", reg);
1243 1207
1244 wm8900_reset(codec); 1208 wm8900_reset(codec);
1245 1209
@@ -1271,43 +1235,94 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1271 /* Set the DAC and mixer output bias */ 1235 /* Set the DAC and mixer output bias */
1272 snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); 1236 snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
1273 1237
1274 wm8900_dai.dev = &i2c->dev; 1238 snd_soc_add_controls(codec, wm8900_snd_controls,
1239 ARRAY_SIZE(wm8900_snd_controls));
1240 wm8900_add_widgets(codec);
1275 1241
1276 wm8900_codec = codec; 1242 return 0;
1243}
1277 1244
1278 ret = snd_soc_register_codec(codec); 1245/* power down chip */
1279 if (ret != 0) { 1246static int wm8900_remove(struct snd_soc_codec *codec)
1280 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); 1247{
1281 goto err; 1248 wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF);
1282 } 1249 return 0;
1250}
1283 1251
1284 ret = snd_soc_register_dai(&wm8900_dai); 1252static struct snd_soc_codec_driver soc_codec_dev_wm8900 = {
1285 if (ret != 0) { 1253 .probe = wm8900_probe,
1286 dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); 1254 .remove = wm8900_remove,
1287 goto err_codec; 1255 .suspend = wm8900_suspend,
1288 } 1256 .resume = wm8900_resume,
1257 .set_bias_level = wm8900_set_bias_level,
1258 .volatile_register = wm8900_volatile_register,
1259 .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults),
1260 .reg_word_size = sizeof(u16),
1261 .reg_cache_default = wm8900_reg_defaults,
1262};
1289 1263
1290 return ret; 1264#if defined(CONFIG_SPI_MASTER)
1265static int __devinit wm8900_spi_probe(struct spi_device *spi)
1266{
1267 struct wm8900_priv *wm8900;
1268 int ret;
1269
1270 wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
1271 if (wm8900 == NULL)
1272 return -ENOMEM;
1291 1273
1292err_codec: 1274 wm8900->control_type = SND_SOC_SPI;
1293 snd_soc_unregister_codec(codec); 1275 spi_set_drvdata(spi, wm8900);
1294err: 1276
1295 kfree(wm8900); 1277 ret = snd_soc_register_codec(&spi->dev,
1296 wm8900_codec = NULL; 1278 &soc_codec_dev_wm8900, &wm8900_dai, 1);
1279 if (ret < 0)
1280 kfree(wm8900);
1297 return ret; 1281 return ret;
1298} 1282}
1299 1283
1300static __devexit int wm8900_i2c_remove(struct i2c_client *client) 1284static int __devexit wm8900_spi_remove(struct spi_device *spi)
1301{ 1285{
1302 snd_soc_unregister_dai(&wm8900_dai); 1286 snd_soc_unregister_codec(&spi->dev);
1303 snd_soc_unregister_codec(wm8900_codec); 1287 kfree(spi_get_drvdata(spi));
1288 return 0;
1289}
1304 1290
1305 wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); 1291static struct spi_driver wm8900_spi_driver = {
1292 .driver = {
1293 .name = "wm8900-codec",
1294 .owner = THIS_MODULE,
1295 },
1296 .probe = wm8900_spi_probe,
1297 .remove = __devexit_p(wm8900_spi_remove),
1298};
1299#endif /* CONFIG_SPI_MASTER */
1300
1301#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1302static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
1303 const struct i2c_device_id *id)
1304{
1305 struct wm8900_priv *wm8900;
1306 int ret;
1307
1308 wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL);
1309 if (wm8900 == NULL)
1310 return -ENOMEM;
1311
1312 i2c_set_clientdata(i2c, wm8900);
1313 wm8900->control_type = SND_SOC_I2C;
1306 1314
1307 wm8900_dai.dev = NULL; 1315 ret = snd_soc_register_codec(&i2c->dev,
1308 kfree(snd_soc_codec_get_drvdata(wm8900_codec)); 1316 &soc_codec_dev_wm8900, &wm8900_dai, 1);
1309 wm8900_codec = NULL; 1317 if (ret < 0)
1318 kfree(wm8900);
1319 return ret;
1320}
1310 1321
1322static __devexit int wm8900_i2c_remove(struct i2c_client *client)
1323{
1324 snd_soc_unregister_codec(&client->dev);
1325 kfree(i2c_get_clientdata(client));
1311 return 0; 1326 return 0;
1312} 1327}
1313 1328
@@ -1319,71 +1334,44 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
1319 1334
1320static struct i2c_driver wm8900_i2c_driver = { 1335static struct i2c_driver wm8900_i2c_driver = {
1321 .driver = { 1336 .driver = {
1322 .name = "WM8900", 1337 .name = "wm8900-codec",
1323 .owner = THIS_MODULE, 1338 .owner = THIS_MODULE,
1324 }, 1339 },
1325 .probe = wm8900_i2c_probe, 1340 .probe = wm8900_i2c_probe,
1326 .remove = __devexit_p(wm8900_i2c_remove), 1341 .remove = __devexit_p(wm8900_i2c_remove),
1327 .id_table = wm8900_i2c_id, 1342 .id_table = wm8900_i2c_id,
1328}; 1343};
1344#endif
1329 1345
1330static int wm8900_probe(struct platform_device *pdev) 1346static int __init wm8900_modinit(void)
1331{ 1347{
1332 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1333 struct snd_soc_codec *codec;
1334 int ret = 0; 1348 int ret = 0;
1335 1349#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1336 if (!wm8900_codec) { 1350 ret = i2c_add_driver(&wm8900_i2c_driver);
1337 dev_err(&pdev->dev, "I2C client not yet instantiated\n"); 1351 if (ret != 0) {
1338 return -ENODEV; 1352 printk(KERN_ERR "Failed to register wm8900 I2C driver: %d\n",
1353 ret);
1339 } 1354 }
1340 1355#endif
1341 codec = wm8900_codec; 1356#if defined(CONFIG_SPI_MASTER)
1342 socdev->card->codec = codec; 1357 ret = spi_register_driver(&wm8900_spi_driver);
1343 1358 if (ret != 0) {
1344 /* Register pcms */ 1359 printk(KERN_ERR "Failed to register wm8900 SPI driver: %d\n",
1345 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 1360 ret);
1346 if (ret < 0) {
1347 dev_err(&pdev->dev, "Failed to register new PCMs\n");
1348 goto pcm_err;
1349 } 1361 }
1350 1362#endif
1351 snd_soc_add_controls(codec, wm8900_snd_controls,
1352 ARRAY_SIZE(wm8900_snd_controls));
1353 wm8900_add_widgets(codec);
1354
1355pcm_err:
1356 return ret; 1363 return ret;
1357} 1364}
1358
1359/* power down chip */
1360static int wm8900_remove(struct platform_device *pdev)
1361{
1362 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1363
1364 snd_soc_free_pcms(socdev);
1365 snd_soc_dapm_free(socdev);
1366
1367 return 0;
1368}
1369
1370struct snd_soc_codec_device soc_codec_dev_wm8900 = {
1371 .probe = wm8900_probe,
1372 .remove = wm8900_remove,
1373 .suspend = wm8900_suspend,
1374 .resume = wm8900_resume,
1375};
1376EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
1377
1378static int __init wm8900_modinit(void)
1379{
1380 return i2c_add_driver(&wm8900_i2c_driver);
1381}
1382module_init(wm8900_modinit); 1365module_init(wm8900_modinit);
1383 1366
1384static void __exit wm8900_exit(void) 1367static void __exit wm8900_exit(void)
1385{ 1368{
1369#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1386 i2c_del_driver(&wm8900_i2c_driver); 1370 i2c_del_driver(&wm8900_i2c_driver);
1371#endif
1372#if defined(CONFIG_SPI_MASTER)
1373 spi_unregister_driver(&wm8900_spi_driver);
1374#endif
1387} 1375}
1388module_exit(wm8900_exit); 1376module_exit(wm8900_exit);
1389 1377
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h
index fd15007d10c7..583f257e799b 100644
--- a/sound/soc/codecs/wm8900.h
+++ b/sound/soc/codecs/wm8900.h
@@ -52,7 +52,4 @@
52#define WM8900_DAC_CLKDIV_5_5 0x14 52#define WM8900_DAC_CLKDIV_5_5 0x14
53#define WM8900_DAC_CLKDIV_6 0x18 53#define WM8900_DAC_CLKDIV_6 0x18
54 54
55extern struct snd_soc_dai wm8900_dai;
56extern struct snd_soc_codec_device soc_codec_dev_wm8900;
57
58#endif 55#endif
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index bf08282d5ee5..622b60238a82 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -213,10 +213,11 @@ static u16 wm8903_reg_defaults[] = {
213}; 213};
214 214
215struct wm8903_priv { 215struct wm8903_priv {
216 struct snd_soc_codec codec; 216
217 u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; 217 u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)];
218 218
219 int sysclk; 219 int sysclk;
220 int irq;
220 221
221 /* Reference counts */ 222 /* Reference counts */
222 int class_w_users; 223 int class_w_users;
@@ -252,7 +253,6 @@ static int wm8903_volatile_register(unsigned int reg)
252static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) 253static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
253{ 254{
254 u16 reg[5]; 255 u16 reg[5];
255 struct i2c_client *i2c = codec->control_data;
256 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 256 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
257 257
258 BUG_ON(start > 48); 258 BUG_ON(start > 48);
@@ -262,7 +262,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
262 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 262 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0,
263 reg[0] | WM8903_WSEQ_ENA); 263 reg[0] | WM8903_WSEQ_ENA);
264 264
265 dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); 265 dev_dbg(codec->dev, "Starting sequence at %d\n", start);
266 266
267 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, 267 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3,
268 start | WM8903_WSEQ_START); 268 start | WM8903_WSEQ_START);
@@ -277,7 +277,7 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
277 reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); 277 reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4);
278 } while (reg[4] & WM8903_WSEQ_BUSY); 278 } while (reg[4] & WM8903_WSEQ_BUSY);
279 279
280 dev_dbg(&i2c->dev, "Sequence complete\n"); 280 dev_dbg(codec->dev, "Sequence complete\n");
281 281
282 /* Disable the sequencer again if we enabled it */ 282 /* Disable the sequencer again if we enabled it */
283 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); 283 snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]);
@@ -422,7 +422,6 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
422 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 422 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
423 struct snd_soc_codec *codec = widget->codec; 423 struct snd_soc_codec *codec = widget->codec;
424 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 424 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
425 struct i2c_client *i2c = codec->control_data;
426 u16 reg; 425 u16 reg;
427 int ret; 426 int ret;
428 427
@@ -431,7 +430,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
431 /* Turn it off if we're about to enable bypass */ 430 /* Turn it off if we're about to enable bypass */
432 if (ucontrol->value.integer.value[0]) { 431 if (ucontrol->value.integer.value[0]) {
433 if (wm8903->class_w_users == 0) { 432 if (wm8903->class_w_users == 0) {
434 dev_dbg(&i2c->dev, "Disabling Class W\n"); 433 dev_dbg(codec->dev, "Disabling Class W\n");
435 snd_soc_write(codec, WM8903_CLASS_W_0, reg & 434 snd_soc_write(codec, WM8903_CLASS_W_0, reg &
436 ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); 435 ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V));
437 } 436 }
@@ -444,14 +443,14 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
444 /* If we've just disabled the last bypass path turn Class W on */ 443 /* If we've just disabled the last bypass path turn Class W on */
445 if (!ucontrol->value.integer.value[0]) { 444 if (!ucontrol->value.integer.value[0]) {
446 if (wm8903->class_w_users == 1) { 445 if (wm8903->class_w_users == 1) {
447 dev_dbg(&i2c->dev, "Enabling Class W\n"); 446 dev_dbg(codec->dev, "Enabling Class W\n");
448 snd_soc_write(codec, WM8903_CLASS_W_0, reg | 447 snd_soc_write(codec, WM8903_CLASS_W_0, reg |
449 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); 448 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
450 } 449 }
451 wm8903->class_w_users--; 450 wm8903->class_w_users--;
452 } 451 }
453 452
454 dev_dbg(&i2c->dev, "Bypass use count now %d\n", 453 dev_dbg(codec->dev, "Bypass use count now %d\n",
455 wm8903->class_w_users); 454 wm8903->class_w_users);
456 455
457 return ret; 456 return ret;
@@ -935,7 +934,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec)
935static int wm8903_set_bias_level(struct snd_soc_codec *codec, 934static int wm8903_set_bias_level(struct snd_soc_codec *codec,
936 enum snd_soc_bias_level level) 935 enum snd_soc_bias_level level)
937{ 936{
938 struct i2c_client *i2c = codec->control_data;
939 u16 reg, reg2; 937 u16 reg, reg2;
940 938
941 switch (level) { 939 switch (level) {
@@ -974,7 +972,7 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
974 /* By default no bypass paths are enabled so 972 /* By default no bypass paths are enabled so
975 * enable Class W support. 973 * enable Class W support.
976 */ 974 */
977 dev_dbg(&i2c->dev, "Enabling Class W\n"); 975 dev_dbg(codec->dev, "Enabling Class W\n");
978 snd_soc_write(codec, WM8903_CLASS_W_0, reg | 976 snd_soc_write(codec, WM8903_CLASS_W_0, reg |
979 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); 977 WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V);
980 } 978 }
@@ -1228,10 +1226,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
1228 struct snd_soc_dai *dai) 1226 struct snd_soc_dai *dai)
1229{ 1227{
1230 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1228 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1231 struct snd_soc_device *socdev = rtd->socdev; 1229 struct snd_soc_codec *codec = rtd->codec;
1232 struct snd_soc_codec *codec = socdev->card->codec;
1233 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 1230 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1234 struct i2c_client *i2c = codec->control_data;
1235 struct snd_pcm_runtime *master_runtime; 1231 struct snd_pcm_runtime *master_runtime;
1236 1232
1237 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1233 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -1245,7 +1241,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
1245 if (wm8903->master_substream) { 1241 if (wm8903->master_substream) {
1246 master_runtime = wm8903->master_substream->runtime; 1242 master_runtime = wm8903->master_substream->runtime;
1247 1243
1248 dev_dbg(&i2c->dev, "Constraining to %d bits\n", 1244 dev_dbg(codec->dev, "Constraining to %d bits\n",
1249 master_runtime->sample_bits); 1245 master_runtime->sample_bits);
1250 1246
1251 snd_pcm_hw_constraint_minmax(substream->runtime, 1247 snd_pcm_hw_constraint_minmax(substream->runtime,
@@ -1264,8 +1260,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream,
1264 struct snd_soc_dai *dai) 1260 struct snd_soc_dai *dai)
1265{ 1261{
1266 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1262 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1267 struct snd_soc_device *socdev = rtd->socdev; 1263 struct snd_soc_codec *codec = rtd->codec;
1268 struct snd_soc_codec *codec = socdev->card->codec;
1269 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 1264 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1270 1265
1271 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 1266 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -1284,10 +1279,8 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1284 struct snd_soc_dai *dai) 1279 struct snd_soc_dai *dai)
1285{ 1280{
1286 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1281 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1287 struct snd_soc_device *socdev = rtd->socdev; 1282 struct snd_soc_codec *codec =rtd->codec;
1288 struct snd_soc_codec *codec = socdev->card->codec;
1289 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec); 1283 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1290 struct i2c_client *i2c = codec->control_data;
1291 int fs = params_rate(params); 1284 int fs = params_rate(params);
1292 int bclk; 1285 int bclk;
1293 int bclk_div; 1286 int bclk_div;
@@ -1306,7 +1299,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1306 u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); 1299 u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1);
1307 1300
1308 if (substream == wm8903->slave_substream) { 1301 if (substream == wm8903->slave_substream) {
1309 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); 1302 dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");
1310 return 0; 1303 return 0;
1311 } 1304 }
1312 1305
@@ -1332,7 +1325,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1332 switch (sample_rates[dsp_config].rate) { 1325 switch (sample_rates[dsp_config].rate) {
1333 case 88200: 1326 case 88200:
1334 case 96000: 1327 case 96000:
1335 dev_err(&i2c->dev, "%dHz unsupported by ADC\n", 1328 dev_err(codec->dev, "%dHz unsupported by ADC\n",
1336 fs); 1329 fs);
1337 return -EINVAL; 1330 return -EINVAL;
1338 1331
@@ -1340,7 +1333,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1340 break; 1333 break;
1341 } 1334 }
1342 1335
1343 dev_dbg(&i2c->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate); 1336 dev_dbg(codec->dev, "DSP fs = %dHz\n", sample_rates[dsp_config].rate);
1344 clock1 &= ~WM8903_SAMPLE_RATE_MASK; 1337 clock1 &= ~WM8903_SAMPLE_RATE_MASK;
1345 clock1 |= sample_rates[dsp_config].value; 1338 clock1 |= sample_rates[dsp_config].value;
1346 1339
@@ -1366,7 +1359,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1366 return -EINVAL; 1359 return -EINVAL;
1367 } 1360 }
1368 1361
1369 dev_dbg(&i2c->dev, "MCLK = %dHz, target sample rate = %dHz\n", 1362 dev_dbg(codec->dev, "MCLK = %dHz, target sample rate = %dHz\n",
1370 wm8903->sysclk, fs); 1363 wm8903->sysclk, fs);
1371 1364
1372 /* We may not have an MCLK which allows us to generate exactly 1365 /* We may not have an MCLK which allows us to generate exactly
@@ -1401,12 +1394,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1401 clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT; 1394 clock1 |= clk_sys_ratios[clk_config].rate << WM8903_CLK_SYS_RATE_SHIFT;
1402 clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT; 1395 clock1 |= clk_sys_ratios[clk_config].mode << WM8903_CLK_SYS_MODE_SHIFT;
1403 1396
1404 dev_dbg(&i2c->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n", 1397 dev_dbg(codec->dev, "CLK_SYS_RATE=%x, CLK_SYS_MODE=%x div=%d\n",
1405 clk_sys_ratios[clk_config].rate, 1398 clk_sys_ratios[clk_config].rate,
1406 clk_sys_ratios[clk_config].mode, 1399 clk_sys_ratios[clk_config].mode,
1407 clk_sys_ratios[clk_config].div); 1400 clk_sys_ratios[clk_config].div);
1408 1401
1409 dev_dbg(&i2c->dev, "Actual CLK_SYS = %dHz\n", clk_sys); 1402 dev_dbg(codec->dev, "Actual CLK_SYS = %dHz\n", clk_sys);
1410 1403
1411 /* We may not get quite the right frequency if using 1404 /* We may not get quite the right frequency if using
1412 * approximate clocks so look for the closest match that is 1405 * approximate clocks so look for the closest match that is
@@ -1428,7 +1421,7 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
1428 aif2 &= ~WM8903_BCLK_DIV_MASK; 1421 aif2 &= ~WM8903_BCLK_DIV_MASK;
1429 aif3 &= ~WM8903_LRCLK_RATE_MASK; 1422 aif3 &= ~WM8903_LRCLK_RATE_MASK;
1430 1423
1431 dev_dbg(&i2c->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n", 1424 dev_dbg(codec->dev, "BCLK ratio %d for %dHz - actual BCLK = %dHz\n",
1432 bclk_divs[bclk_div].ratio / 10, bclk, 1425 bclk_divs[bclk_div].ratio / 10, bclk,
1433 (clk_sys * 10) / bclk_divs[bclk_div].ratio); 1426 (clk_sys * 10) / bclk_divs[bclk_div].ratio);
1434 1427
@@ -1504,8 +1497,8 @@ EXPORT_SYMBOL_GPL(wm8903_mic_detect);
1504 1497
1505static irqreturn_t wm8903_irq(int irq, void *data) 1498static irqreturn_t wm8903_irq(int irq, void *data)
1506{ 1499{
1507 struct wm8903_priv *wm8903 = data; 1500 struct snd_soc_codec *codec = data;
1508 struct snd_soc_codec *codec = &wm8903->codec; 1501 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1509 int mic_report; 1502 int mic_report;
1510 int int_pol; 1503 int int_pol;
1511 int int_val = 0; 1504 int int_val = 0;
@@ -1586,8 +1579,8 @@ static struct snd_soc_dai_ops wm8903_dai_ops = {
1586 .set_sysclk = wm8903_set_dai_sysclk, 1579 .set_sysclk = wm8903_set_dai_sysclk,
1587}; 1580};
1588 1581
1589struct snd_soc_dai wm8903_dai = { 1582static struct snd_soc_dai_driver wm8903_dai = {
1590 .name = "WM8903", 1583 .name = "wm8903-hifi",
1591 .playback = { 1584 .playback = {
1592 .stream_name = "Playback", 1585 .stream_name = "Playback",
1593 .channels_min = 2, 1586 .channels_min = 2,
@@ -1605,23 +1598,16 @@ struct snd_soc_dai wm8903_dai = {
1605 .ops = &wm8903_dai_ops, 1598 .ops = &wm8903_dai_ops,
1606 .symmetric_rates = 1, 1599 .symmetric_rates = 1,
1607}; 1600};
1608EXPORT_SYMBOL_GPL(wm8903_dai);
1609 1601
1610static int wm8903_suspend(struct platform_device *pdev, pm_message_t state) 1602static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)
1611{ 1603{
1612 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1613 struct snd_soc_codec *codec = socdev->card->codec;
1614
1615 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); 1604 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1616 1605
1617 return 0; 1606 return 0;
1618} 1607}
1619 1608
1620static int wm8903_resume(struct platform_device *pdev) 1609static int wm8903_resume(struct snd_soc_codec *codec)
1621{ 1610{
1622 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1623 struct snd_soc_codec *codec = socdev->card->codec;
1624 struct i2c_client *i2c = codec->control_data;
1625 int i; 1611 int i;
1626 u16 *reg_cache = codec->reg_cache; 1612 u16 *reg_cache = codec->reg_cache;
1627 u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults), 1613 u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults),
@@ -1637,65 +1623,37 @@ static int wm8903_resume(struct platform_device *pdev)
1637 snd_soc_write(codec, i, tmp_cache[i]); 1623 snd_soc_write(codec, i, tmp_cache[i]);
1638 kfree(tmp_cache); 1624 kfree(tmp_cache);
1639 } else { 1625 } else {
1640 dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); 1626 dev_err(codec->dev, "Failed to allocate temporary cache\n");
1641 } 1627 }
1642 1628
1643 return 0; 1629 return 0;
1644} 1630}
1645 1631
1646static struct snd_soc_codec *wm8903_codec; 1632static int wm8903_probe(struct snd_soc_codec *codec)
1647
1648static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1649 const struct i2c_device_id *id)
1650{ 1633{
1651 struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev); 1634 struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
1652 struct wm8903_priv *wm8903; 1635 struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
1653 struct snd_soc_codec *codec;
1654 int ret, i; 1636 int ret, i;
1655 int trigger, irq_pol; 1637 int trigger, irq_pol;
1656 u16 val; 1638 u16 val;
1657 1639
1658 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
1659 if (wm8903 == NULL)
1660 return -ENOMEM;
1661
1662 codec = &wm8903->codec;
1663
1664 mutex_init(&codec->mutex);
1665 INIT_LIST_HEAD(&codec->dapm_widgets);
1666 INIT_LIST_HEAD(&codec->dapm_paths);
1667
1668 codec->dev = &i2c->dev;
1669 codec->name = "WM8903";
1670 codec->owner = THIS_MODULE;
1671 codec->bias_level = SND_SOC_BIAS_OFF;
1672 codec->set_bias_level = wm8903_set_bias_level;
1673 codec->dai = &wm8903_dai;
1674 codec->num_dai = 1;
1675 codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
1676 codec->reg_cache = &wm8903->reg_cache[0];
1677 snd_soc_codec_set_drvdata(codec, wm8903);
1678 codec->volatile_register = wm8903_volatile_register;
1679 init_completion(&wm8903->wseq); 1640 init_completion(&wm8903->wseq);
1680 1641
1681 i2c_set_clientdata(i2c, codec);
1682 codec->control_data = i2c;
1683
1684 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); 1642 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1685 if (ret != 0) { 1643 if (ret != 0) {
1686 dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); 1644 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1687 goto err; 1645 return ret;
1688 } 1646 }
1689 1647
1690 val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID); 1648 val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
1691 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { 1649 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
1692 dev_err(&i2c->dev, 1650 dev_err(codec->dev,
1693 "Device with ID register %x is not a WM8903\n", val); 1651 "Device with ID register %x is not a WM8903\n", val);
1694 return -ENODEV; 1652 return -ENODEV;
1695 } 1653 }
1696 1654
1697 val = snd_soc_read(codec, WM8903_REVISION_NUMBER); 1655 val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
1698 dev_info(&i2c->dev, "WM8903 revision %d\n", 1656 dev_info(codec->dev, "WM8903 revision %d\n",
1699 val & WM8903_CHIP_REV_MASK); 1657 val & WM8903_CHIP_REV_MASK);
1700 1658
1701 wm8903_reset(codec); 1659 wm8903_reset(codec);
@@ -1721,7 +1679,7 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1721 wm8903->mic_delay = pdata->micdet_delay; 1679 wm8903->mic_delay = pdata->micdet_delay;
1722 } 1680 }
1723 1681
1724 if (i2c->irq) { 1682 if (wm8903->irq) {
1725 if (pdata && pdata->irq_active_low) { 1683 if (pdata && pdata->irq_active_low) {
1726 trigger = IRQF_TRIGGER_LOW; 1684 trigger = IRQF_TRIGGER_LOW;
1727 irq_pol = WM8903_IRQ_POL; 1685 irq_pol = WM8903_IRQ_POL;
@@ -1733,13 +1691,13 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1733 snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL, 1691 snd_soc_update_bits(codec, WM8903_INTERRUPT_CONTROL,
1734 WM8903_IRQ_POL, irq_pol); 1692 WM8903_IRQ_POL, irq_pol);
1735 1693
1736 ret = request_threaded_irq(i2c->irq, NULL, wm8903_irq, 1694 ret = request_threaded_irq(wm8903->irq, NULL, wm8903_irq,
1737 trigger | IRQF_ONESHOT, 1695 trigger | IRQF_ONESHOT,
1738 "wm8903", wm8903); 1696 "wm8903", codec);
1739 if (ret != 0) { 1697 if (ret != 0) {
1740 dev_err(&i2c->dev, "Failed to request IRQ: %d\n", 1698 dev_err(codec->dev, "Failed to request IRQ: %d\n",
1741 ret); 1699 ret);
1742 goto err; 1700 return ret;
1743 } 1701 }
1744 1702
1745 /* Enable write sequencer interrupts */ 1703 /* Enable write sequencer interrupts */
@@ -1781,133 +1739,96 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1781 val |= WM8903_DAC_MUTEMODE; 1739 val |= WM8903_DAC_MUTEMODE;
1782 snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); 1740 snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val);
1783 1741
1784 wm8903_dai.dev = &i2c->dev; 1742 snd_soc_add_controls(codec, wm8903_snd_controls,
1785 wm8903_codec = codec; 1743 ARRAY_SIZE(wm8903_snd_controls));
1786 1744 wm8903_add_widgets(codec);
1787 ret = snd_soc_register_codec(codec);
1788 if (ret != 0) {
1789 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1790 goto err_irq;
1791 }
1792
1793 ret = snd_soc_register_dai(&wm8903_dai);
1794 if (ret != 0) {
1795 dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
1796 goto err_codec;
1797 }
1798
1799 return ret;
1800 1745
1801err_codec:
1802 snd_soc_unregister_codec(codec);
1803err_irq:
1804 if (i2c->irq)
1805 free_irq(i2c->irq, wm8903);
1806err:
1807 wm8903_codec = NULL;
1808 kfree(wm8903);
1809 return ret; 1746 return ret;
1810} 1747}
1811 1748
1812static __devexit int wm8903_i2c_remove(struct i2c_client *client) 1749/* power down chip */
1750static int wm8903_remove(struct snd_soc_codec *codec)
1813{ 1751{
1814 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1752 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1815 struct wm8903_priv *priv = snd_soc_codec_get_drvdata(codec); 1753 return 0;
1754}
1816 1755
1817 snd_soc_unregister_dai(&wm8903_dai); 1756static struct snd_soc_codec_driver soc_codec_dev_wm8903 = {
1818 snd_soc_unregister_codec(codec); 1757 .probe = wm8903_probe,
1758 .remove = wm8903_remove,
1759 .suspend = wm8903_suspend,
1760 .resume = wm8903_resume,
1761 .set_bias_level = wm8903_set_bias_level,
1762 .reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults),
1763 .reg_word_size = sizeof(u16),
1764 .reg_cache_default = wm8903_reg_defaults,
1765 .volatile_register = wm8903_volatile_register,
1766};
1819 1767
1820 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); 1768#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1769static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
1770 const struct i2c_device_id *id)
1771{
1772 struct wm8903_priv *wm8903;
1773 int ret;
1821 1774
1822 if (client->irq) 1775 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
1823 free_irq(client->irq, priv); 1776 if (wm8903 == NULL)
1777 return -ENOMEM;
1824 1778
1825 kfree(priv); 1779 i2c_set_clientdata(i2c, wm8903);
1780 wm8903->irq = i2c->irq;
1826 1781
1827 wm8903_codec = NULL; 1782 ret = snd_soc_register_codec(&i2c->dev,
1828 wm8903_dai.dev = NULL; 1783 &soc_codec_dev_wm8903, &wm8903_dai, 1);
1784 if (ret < 0)
1785 kfree(wm8903);
1786 return ret;
1787}
1829 1788
1789static __devexit int wm8903_i2c_remove(struct i2c_client *client)
1790{
1791 snd_soc_unregister_codec(&client->dev);
1792 kfree(i2c_get_clientdata(client));
1830 return 0; 1793 return 0;
1831} 1794}
1832 1795
1833/* i2c codec control layer */
1834static const struct i2c_device_id wm8903_i2c_id[] = { 1796static const struct i2c_device_id wm8903_i2c_id[] = {
1835 { "wm8903", 0 }, 1797 { "wm8903", 0 },
1836 { } 1798 { }
1837}; 1799};
1838MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); 1800MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id);
1839 1801
1840static struct i2c_driver wm8903_i2c_driver = { 1802static struct i2c_driver wm8903_i2c_driver = {
1841 .driver = { 1803 .driver = {
1842 .name = "WM8903", 1804 .name = "wm8903-codec",
1843 .owner = THIS_MODULE, 1805 .owner = THIS_MODULE,
1844 }, 1806 },
1845 .probe = wm8903_i2c_probe, 1807 .probe = wm8903_i2c_probe,
1846 .remove = __devexit_p(wm8903_i2c_remove), 1808 .remove = __devexit_p(wm8903_i2c_remove),
1847 .id_table = wm8903_i2c_id, 1809 .id_table = wm8903_i2c_id,
1848}; 1810};
1811#endif
1849 1812
1850static int wm8903_probe(struct platform_device *pdev) 1813static int __init wm8903_modinit(void)
1851{ 1814{
1852 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1853 int ret = 0; 1815 int ret = 0;
1854 1816#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1855 if (!wm8903_codec) { 1817 ret = i2c_add_driver(&wm8903_i2c_driver);
1856 dev_err(&pdev->dev, "I2C device not yet probed\n"); 1818 if (ret != 0) {
1857 goto err; 1819 printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n",
1858 } 1820 ret);
1859
1860 socdev->card->codec = wm8903_codec;
1861
1862 /* register pcms */
1863 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1864 if (ret < 0) {
1865 dev_err(&pdev->dev, "failed to create pcms\n");
1866 goto err;
1867 } 1821 }
1868 1822#endif
1869 snd_soc_add_controls(socdev->card->codec, wm8903_snd_controls,
1870 ARRAY_SIZE(wm8903_snd_controls));
1871 wm8903_add_widgets(socdev->card->codec);
1872
1873 return ret; 1823 return ret;
1874
1875err:
1876 return ret;
1877}
1878
1879/* power down chip */
1880static int wm8903_remove(struct platform_device *pdev)
1881{
1882 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1883 struct snd_soc_codec *codec = socdev->card->codec;
1884
1885 if (codec->control_data)
1886 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1887
1888 snd_soc_free_pcms(socdev);
1889 snd_soc_dapm_free(socdev);
1890
1891 return 0;
1892}
1893
1894struct snd_soc_codec_device soc_codec_dev_wm8903 = {
1895 .probe = wm8903_probe,
1896 .remove = wm8903_remove,
1897 .suspend = wm8903_suspend,
1898 .resume = wm8903_resume,
1899};
1900EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
1901
1902static int __init wm8903_modinit(void)
1903{
1904 return i2c_add_driver(&wm8903_i2c_driver);
1905} 1824}
1906module_init(wm8903_modinit); 1825module_init(wm8903_modinit);
1907 1826
1908static void __exit wm8903_exit(void) 1827static void __exit wm8903_exit(void)
1909{ 1828{
1829#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1910 i2c_del_driver(&wm8903_i2c_driver); 1830 i2c_del_driver(&wm8903_i2c_driver);
1831#endif
1911} 1832}
1912module_exit(wm8903_exit); 1833module_exit(wm8903_exit);
1913 1834
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
index ce384a2ad820..996435e681e5 100644
--- a/sound/soc/codecs/wm8903.h
+++ b/sound/soc/codecs/wm8903.h
@@ -15,9 +15,6 @@
15 15
16#include <linux/i2c.h> 16#include <linux/i2c.h>
17 17
18extern struct snd_soc_dai wm8903_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8903;
20
21extern int wm8903_mic_detect(struct snd_soc_codec *codec, 18extern int wm8903_mic_detect(struct snd_soc_codec *codec,
22 struct snd_soc_jack *jack, 19 struct snd_soc_jack *jack,
23 int det, int shrt); 20 int det, int shrt);
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index f7dcabf6283c..33be84e506ea 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -31,9 +31,6 @@
31 31
32#include "wm8904.h" 32#include "wm8904.h"
33 33
34static struct snd_soc_codec *wm8904_codec;
35struct snd_soc_codec_device soc_codec_dev_wm8904;
36
37enum wm8904_type { 34enum wm8904_type {
38 WM8904, 35 WM8904,
39 WM8912, 36 WM8912,
@@ -52,10 +49,11 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
52 49
53/* codec private data */ 50/* codec private data */
54struct wm8904_priv { 51struct wm8904_priv {
55 struct snd_soc_codec codec; 52
56 u16 reg_cache[WM8904_MAX_REGISTER + 1]; 53 u16 reg_cache[WM8904_MAX_REGISTER + 1];
57 54
58 enum wm8904_type devtype; 55 enum wm8904_type devtype;
56 void *control_data;
59 57
60 struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES]; 58 struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
61 59
@@ -689,7 +687,7 @@ static int wm8904_put_drc_enum(struct snd_kcontrol *kcontrol,
689 struct snd_ctl_elem_value *ucontrol) 687 struct snd_ctl_elem_value *ucontrol)
690{ 688{
691 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 689 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
692 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 690 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
693 struct wm8904_pdata *pdata = wm8904->pdata; 691 struct wm8904_pdata *pdata = wm8904->pdata;
694 int value = ucontrol->value.integer.value[0]; 692 int value = ucontrol->value.integer.value[0];
695 693
@@ -760,7 +758,7 @@ static int wm8904_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
760 struct snd_ctl_elem_value *ucontrol) 758 struct snd_ctl_elem_value *ucontrol)
761{ 759{
762 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 760 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
763 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); 761 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
764 struct wm8904_pdata *pdata = wm8904->pdata; 762 struct wm8904_pdata *pdata = wm8904->pdata;
765 int value = ucontrol->value.integer.value[0]; 763 int value = ucontrol->value.integer.value[0];
766 764
@@ -2218,8 +2216,8 @@ static struct snd_soc_dai_ops wm8904_dai_ops = {
2218 .digital_mute = wm8904_digital_mute, 2216 .digital_mute = wm8904_digital_mute,
2219}; 2217};
2220 2218
2221struct snd_soc_dai wm8904_dai = { 2219static struct snd_soc_dai_driver wm8904_dai = {
2222 .name = "WM8904", 2220 .name = "wm8904-hifi",
2223 .playback = { 2221 .playback = {
2224 .stream_name = "Playback", 2222 .stream_name = "Playback",
2225 .channels_min = 2, 2223 .channels_min = 2,
@@ -2237,24 +2235,17 @@ struct snd_soc_dai wm8904_dai = {
2237 .ops = &wm8904_dai_ops, 2235 .ops = &wm8904_dai_ops,
2238 .symmetric_rates = 1, 2236 .symmetric_rates = 1,
2239}; 2237};
2240EXPORT_SYMBOL_GPL(wm8904_dai);
2241 2238
2242#ifdef CONFIG_PM 2239#ifdef CONFIG_PM
2243static int wm8904_suspend(struct platform_device *pdev, pm_message_t state) 2240static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state)
2244{ 2241{
2245 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2246 struct snd_soc_codec *codec = socdev->card->codec;
2247
2248 wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF); 2242 wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
2249 2243
2250 return 0; 2244 return 0;
2251} 2245}
2252 2246
2253static int wm8904_resume(struct platform_device *pdev) 2247static int wm8904_resume(struct snd_soc_codec *codec)
2254{ 2248{
2255 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2256 struct snd_soc_codec *codec = socdev->card->codec;
2257
2258 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 2249 wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2259 2250
2260 return 0; 2251 return 0;
@@ -2264,9 +2255,9 @@ static int wm8904_resume(struct platform_device *pdev)
2264#define wm8904_resume NULL 2255#define wm8904_resume NULL
2265#endif 2256#endif
2266 2257
2267static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904) 2258static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
2268{ 2259{
2269 struct snd_soc_codec *codec = &wm8904->codec; 2260 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2270 struct wm8904_pdata *pdata = wm8904->pdata; 2261 struct wm8904_pdata *pdata = wm8904->pdata;
2271 struct snd_kcontrol_new control = 2262 struct snd_kcontrol_new control =
2272 SOC_ENUM_EXT("EQ Mode", 2263 SOC_ENUM_EXT("EQ Mode",
@@ -2315,20 +2306,20 @@ static void wm8904_handle_retune_mobile_pdata(struct wm8904_priv *wm8904)
2315 wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts; 2306 wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
2316 wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts; 2307 wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
2317 2308
2318 ret = snd_soc_add_controls(&wm8904->codec, &control, 1); 2309 ret = snd_soc_add_controls(codec, &control, 1);
2319 if (ret != 0) 2310 if (ret != 0)
2320 dev_err(wm8904->codec.dev, 2311 dev_err(codec->dev,
2321 "Failed to add ReTune Mobile control: %d\n", ret); 2312 "Failed to add ReTune Mobile control: %d\n", ret);
2322} 2313}
2323 2314
2324static void wm8904_handle_pdata(struct wm8904_priv *wm8904) 2315static void wm8904_handle_pdata(struct snd_soc_codec *codec)
2325{ 2316{
2326 struct snd_soc_codec *codec = &wm8904->codec; 2317 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2327 struct wm8904_pdata *pdata = wm8904->pdata; 2318 struct wm8904_pdata *pdata = wm8904->pdata;
2328 int ret, i; 2319 int ret, i;
2329 2320
2330 if (!pdata) { 2321 if (!pdata) {
2331 snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, 2322 snd_soc_add_controls(codec, wm8904_eq_controls,
2332 ARRAY_SIZE(wm8904_eq_controls)); 2323 ARRAY_SIZE(wm8904_eq_controls));
2333 return; 2324 return;
2334 } 2325 }
@@ -2344,7 +2335,7 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
2344 wm8904->drc_texts = kmalloc(sizeof(char *) 2335 wm8904->drc_texts = kmalloc(sizeof(char *)
2345 * pdata->num_drc_cfgs, GFP_KERNEL); 2336 * pdata->num_drc_cfgs, GFP_KERNEL);
2346 if (!wm8904->drc_texts) { 2337 if (!wm8904->drc_texts) {
2347 dev_err(wm8904->codec.dev, 2338 dev_err(codec->dev,
2348 "Failed to allocate %d DRC config texts\n", 2339 "Failed to allocate %d DRC config texts\n",
2349 pdata->num_drc_cfgs); 2340 pdata->num_drc_cfgs);
2350 return; 2341 return;
@@ -2356,9 +2347,9 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
2356 wm8904->drc_enum.max = pdata->num_drc_cfgs; 2347 wm8904->drc_enum.max = pdata->num_drc_cfgs;
2357 wm8904->drc_enum.texts = wm8904->drc_texts; 2348 wm8904->drc_enum.texts = wm8904->drc_texts;
2358 2349
2359 ret = snd_soc_add_controls(&wm8904->codec, &control, 1); 2350 ret = snd_soc_add_controls(codec, &control, 1);
2360 if (ret != 0) 2351 if (ret != 0)
2361 dev_err(wm8904->codec.dev, 2352 dev_err(codec->dev,
2362 "Failed to add DRC mode control: %d\n", ret); 2353 "Failed to add DRC mode control: %d\n", ret);
2363 2354
2364 wm8904_set_drc(codec); 2355 wm8904_set_drc(codec);
@@ -2368,89 +2359,19 @@ static void wm8904_handle_pdata(struct wm8904_priv *wm8904)
2368 pdata->num_retune_mobile_cfgs); 2359 pdata->num_retune_mobile_cfgs);
2369 2360
2370 if (pdata->num_retune_mobile_cfgs) 2361 if (pdata->num_retune_mobile_cfgs)
2371 wm8904_handle_retune_mobile_pdata(wm8904); 2362 wm8904_handle_retune_mobile_pdata(codec);
2372 else 2363 else
2373 snd_soc_add_controls(&wm8904->codec, wm8904_eq_controls, 2364 snd_soc_add_controls(codec, wm8904_eq_controls,
2374 ARRAY_SIZE(wm8904_eq_controls)); 2365 ARRAY_SIZE(wm8904_eq_controls));
2375} 2366}
2376 2367
2377static int wm8904_probe(struct platform_device *pdev)
2378{
2379 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2380 struct snd_soc_codec *codec;
2381 int ret = 0;
2382
2383 if (wm8904_codec == NULL) {
2384 dev_err(&pdev->dev, "Codec device not registered\n");
2385 return -ENODEV;
2386 }
2387 2368
2388 socdev->card->codec = wm8904_codec; 2369static int wm8904_probe(struct snd_soc_codec *codec)
2389 codec = wm8904_codec;
2390
2391 /* register pcms */
2392 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
2393 if (ret < 0) {
2394 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
2395 goto pcm_err;
2396 }
2397
2398 wm8904_handle_pdata(snd_soc_codec_get_drvdata(codec));
2399
2400 wm8904_add_widgets(codec);
2401
2402 return ret;
2403
2404pcm_err:
2405 return ret;
2406}
2407
2408static int wm8904_remove(struct platform_device *pdev)
2409{
2410 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2411
2412 snd_soc_free_pcms(socdev);
2413 snd_soc_dapm_free(socdev);
2414
2415 return 0;
2416}
2417
2418struct snd_soc_codec_device soc_codec_dev_wm8904 = {
2419 .probe = wm8904_probe,
2420 .remove = wm8904_remove,
2421 .suspend = wm8904_suspend,
2422 .resume = wm8904_resume,
2423};
2424EXPORT_SYMBOL_GPL(soc_codec_dev_wm8904);
2425
2426static int wm8904_register(struct wm8904_priv *wm8904,
2427 enum snd_soc_control_type control)
2428{ 2370{
2371 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2429 struct wm8904_pdata *pdata = wm8904->pdata; 2372 struct wm8904_pdata *pdata = wm8904->pdata;
2430 int ret; 2373 int ret, i;
2431 struct snd_soc_codec *codec = &wm8904->codec;
2432 int i;
2433
2434 if (wm8904_codec) {
2435 dev_err(codec->dev, "Another WM8904 is registered\n");
2436 ret = -EINVAL;
2437 goto err;
2438 }
2439 2374
2440 mutex_init(&codec->mutex);
2441 INIT_LIST_HEAD(&codec->dapm_widgets);
2442 INIT_LIST_HEAD(&codec->dapm_paths);
2443
2444 snd_soc_codec_set_drvdata(codec, wm8904);
2445 codec->name = "WM8904";
2446 codec->owner = THIS_MODULE;
2447 codec->bias_level = SND_SOC_BIAS_OFF;
2448 codec->set_bias_level = wm8904_set_bias_level;
2449 codec->dai = &wm8904_dai;
2450 codec->num_dai = 1;
2451 codec->reg_cache_size = WM8904_MAX_REGISTER;
2452 codec->reg_cache = &wm8904->reg_cache;
2453 codec->volatile_register = wm8904_volatile_register;
2454 codec->cache_sync = 1; 2375 codec->cache_sync = 1;
2455 codec->idle_bias_off = 1; 2376 codec->idle_bias_off = 1;
2456 2377
@@ -2463,16 +2384,13 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2463 default: 2384 default:
2464 dev_err(codec->dev, "Unknown device type %d\n", 2385 dev_err(codec->dev, "Unknown device type %d\n",
2465 wm8904->devtype); 2386 wm8904->devtype);
2466 ret = -EINVAL; 2387 return -EINVAL;
2467 goto err;
2468 } 2388 }
2469 2389
2470 memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg)); 2390 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
2471
2472 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
2473 if (ret != 0) { 2391 if (ret != 0) {
2474 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 2392 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
2475 goto err; 2393 return ret;
2476 } 2394 }
2477 2395
2478 for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++) 2396 for (i = 0; i < ARRAY_SIZE(wm8904->supplies); i++)
@@ -2482,7 +2400,7 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2482 wm8904->supplies); 2400 wm8904->supplies);
2483 if (ret != 0) { 2401 if (ret != 0) {
2484 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 2402 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
2485 goto err; 2403 return ret;
2486 } 2404 }
2487 2405
2488 ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies), 2406 ret = regulator_bulk_enable(ARRAY_SIZE(wm8904->supplies),
@@ -2517,8 +2435,6 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2517 goto err_enable; 2435 goto err_enable;
2518 } 2436 }
2519 2437
2520 wm8904_dai.dev = codec->dev;
2521
2522 /* Change some default settings - latch VU and enable ZC */ 2438 /* Change some default settings - latch VU and enable ZC */
2523 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU; 2439 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
2524 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU; 2440 wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
@@ -2563,72 +2479,68 @@ static int wm8904_register(struct wm8904_priv *wm8904,
2563 /* Bias level configuration will have done an extra enable */ 2479 /* Bias level configuration will have done an extra enable */
2564 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2480 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2565 2481
2566 wm8904_codec = codec; 2482 wm8904_handle_pdata(codec);
2567 2483
2568 ret = snd_soc_register_codec(codec); 2484 wm8904_add_widgets(codec);
2569 if (ret != 0) {
2570 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
2571 goto err_enable;
2572 }
2573
2574 ret = snd_soc_register_dai(&wm8904_dai);
2575 if (ret != 0) {
2576 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
2577 goto err_codec;
2578 }
2579 2485
2580 return 0; 2486 return 0;
2581 2487
2582err_codec:
2583 snd_soc_unregister_codec(codec);
2584err_enable: 2488err_enable:
2585 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2489 regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2586err_get: 2490err_get:
2587 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2491 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2588err:
2589 kfree(wm8904);
2590 return ret; 2492 return ret;
2591} 2493}
2592 2494
2593static void wm8904_unregister(struct wm8904_priv *wm8904) 2495static int wm8904_remove(struct snd_soc_codec *codec)
2594{ 2496{
2595 wm8904_set_bias_level(&wm8904->codec, SND_SOC_BIAS_OFF); 2497 struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
2498
2499 wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
2596 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies); 2500 regulator_bulk_free(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
2597 snd_soc_unregister_dai(&wm8904_dai); 2501
2598 snd_soc_unregister_codec(&wm8904->codec); 2502 return 0;
2599 kfree(wm8904);
2600 wm8904_codec = NULL;
2601} 2503}
2602 2504
2505static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
2506 .probe = wm8904_probe,
2507 .remove = wm8904_remove,
2508 .suspend = wm8904_suspend,
2509 .resume = wm8904_resume,
2510 .set_bias_level = wm8904_set_bias_level,
2511 .reg_cache_size = ARRAY_SIZE(wm8904_reg),
2512 .reg_word_size = sizeof(u16),
2513 .reg_cache_default = wm8904_reg,
2514 .volatile_register = wm8904_volatile_register,
2515};
2516
2603#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 2517#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
2604static __devinit int wm8904_i2c_probe(struct i2c_client *i2c, 2518static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
2605 const struct i2c_device_id *id) 2519 const struct i2c_device_id *id)
2606{ 2520{
2607 struct wm8904_priv *wm8904; 2521 struct wm8904_priv *wm8904;
2608 struct snd_soc_codec *codec; 2522 int ret;
2609 2523
2610 wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL); 2524 wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);
2611 if (wm8904 == NULL) 2525 if (wm8904 == NULL)
2612 return -ENOMEM; 2526 return -ENOMEM;
2613 2527
2614 codec = &wm8904->codec;
2615 codec->hw_write = (hw_write_t)i2c_master_send;
2616
2617 wm8904->devtype = id->driver_data; 2528 wm8904->devtype = id->driver_data;
2618
2619 i2c_set_clientdata(i2c, wm8904); 2529 i2c_set_clientdata(i2c, wm8904);
2620 codec->control_data = i2c; 2530 wm8904->control_data = i2c;
2621 wm8904->pdata = i2c->dev.platform_data; 2531 wm8904->pdata = i2c->dev.platform_data;
2622 2532
2623 codec->dev = &i2c->dev; 2533 ret = snd_soc_register_codec(&i2c->dev,
2624 2534 &soc_codec_dev_wm8904, &wm8904_dai, 1);
2625 return wm8904_register(wm8904, SND_SOC_I2C); 2535 if (ret < 0)
2536 kfree(wm8904);
2537 return ret;
2626} 2538}
2627 2539
2628static __devexit int wm8904_i2c_remove(struct i2c_client *client) 2540static __devexit int wm8904_i2c_remove(struct i2c_client *client)
2629{ 2541{
2630 struct wm8904_priv *wm8904 = i2c_get_clientdata(client); 2542 snd_soc_unregister_codec(&client->dev);
2631 wm8904_unregister(wm8904); 2543 kfree(i2c_get_clientdata(client));
2632 return 0; 2544 return 0;
2633} 2545}
2634 2546
@@ -2641,7 +2553,7 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
2641 2553
2642static struct i2c_driver wm8904_i2c_driver = { 2554static struct i2c_driver wm8904_i2c_driver = {
2643 .driver = { 2555 .driver = {
2644 .name = "WM8904", 2556 .name = "wm8904-codec",
2645 .owner = THIS_MODULE, 2557 .owner = THIS_MODULE,
2646 }, 2558 },
2647 .probe = wm8904_i2c_probe, 2559 .probe = wm8904_i2c_probe,
@@ -2652,15 +2564,15 @@ static struct i2c_driver wm8904_i2c_driver = {
2652 2564
2653static int __init wm8904_modinit(void) 2565static int __init wm8904_modinit(void)
2654{ 2566{
2655 int ret; 2567 int ret = 0;
2656#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 2568#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
2657 ret = i2c_add_driver(&wm8904_i2c_driver); 2569 ret = i2c_add_driver(&wm8904_i2c_driver);
2658 if (ret != 0) { 2570 if (ret != 0) {
2659 printk(KERN_ERR "Failed to register WM8904 I2C driver: %d\n", 2571 printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
2660 ret); 2572 ret);
2661 } 2573 }
2662#endif 2574#endif
2663 return 0; 2575 return ret;
2664} 2576}
2665module_init(wm8904_modinit); 2577module_init(wm8904_modinit);
2666 2578
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h
index abe5059b3004..9e8c84188ba7 100644
--- a/sound/soc/codecs/wm8904.h
+++ b/sound/soc/codecs/wm8904.h
@@ -21,9 +21,6 @@
21#define WM8904_FLL_LRCLK 3 21#define WM8904_FLL_LRCLK 3
22#define WM8904_FLL_FREE_RUNNING 4 22#define WM8904_FLL_FREE_RUNNING 4
23 23
24extern struct snd_soc_dai wm8904_dai;
25extern struct snd_soc_codec_device soc_codec_dev_wm8904;
26
27/* 24/*
28 * Register values. 25 * Register values.
29 */ 26 */
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index f0c11138e610..2cb16f895c46 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -44,7 +44,8 @@
44struct wm8940_priv { 44struct wm8940_priv {
45 unsigned int sysclk; 45 unsigned int sysclk;
46 u16 reg_cache[WM8940_CACHEREGNUM]; 46 u16 reg_cache[WM8940_CACHEREGNUM];
47 struct snd_soc_codec codec; 47 enum snd_soc_control_type control_type;
48 void *control_data;
48}; 49};
49 50
50static u16 wm8940_reg_defaults[] = { 51static u16 wm8940_reg_defaults[] = {
@@ -365,8 +366,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
365 struct snd_soc_dai *dai) 366 struct snd_soc_dai *dai)
366{ 367{
367 struct snd_soc_pcm_runtime *rtd = substream->private_data; 368 struct snd_soc_pcm_runtime *rtd = substream->private_data;
368 struct snd_soc_device *socdev = rtd->socdev; 369 struct snd_soc_codec *codec = rtd->codec;
369 struct snd_soc_codec *codec = socdev->card->codec;
370 u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; 370 u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F;
371 u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; 371 u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1;
372 u16 companding = snd_soc_read(codec, 372 u16 companding = snd_soc_read(codec,
@@ -636,8 +636,8 @@ static struct snd_soc_dai_ops wm8940_dai_ops = {
636 .set_pll = wm8940_set_dai_pll, 636 .set_pll = wm8940_set_dai_pll,
637}; 637};
638 638
639struct snd_soc_dai wm8940_dai = { 639static struct snd_soc_dai_driver wm8940_dai = {
640 .name = "WM8940", 640 .name = "wm8940-hifi",
641 .playback = { 641 .playback = {
642 .stream_name = "Playback", 642 .stream_name = "Playback",
643 .channels_min = 1, 643 .channels_min = 1,
@@ -655,20 +655,14 @@ struct snd_soc_dai wm8940_dai = {
655 .ops = &wm8940_dai_ops, 655 .ops = &wm8940_dai_ops,
656 .symmetric_rates = 1, 656 .symmetric_rates = 1,
657}; 657};
658EXPORT_SYMBOL_GPL(wm8940_dai);
659 658
660static int wm8940_suspend(struct platform_device *pdev, pm_message_t state) 659static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
661{ 660{
662 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
663 struct snd_soc_codec *codec = socdev->card->codec;
664
665 return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF); 661 return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
666} 662}
667 663
668static int wm8940_resume(struct platform_device *pdev) 664static int wm8940_resume(struct snd_soc_codec *codec)
669{ 665{
670 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
671 struct snd_soc_codec *codec = socdev->card->codec;
672 int i; 666 int i;
673 int ret; 667 int ret;
674 u8 data[3]; 668 u8 data[3];
@@ -697,108 +691,26 @@ error_ret:
697 return ret; 691 return ret;
698} 692}
699 693
700static struct snd_soc_codec *wm8940_codec; 694static int wm8940_probe(struct snd_soc_codec *codec)
701
702static int wm8940_probe(struct platform_device *pdev)
703{
704 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
705 struct snd_soc_codec *codec;
706
707 int ret = 0;
708
709 if (wm8940_codec == NULL) {
710 dev_err(&pdev->dev, "Codec device not registered\n");
711 return -ENODEV;
712 }
713
714 socdev->card->codec = wm8940_codec;
715 codec = wm8940_codec;
716
717 mutex_init(&codec->mutex);
718 /* register pcms */
719 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
720 if (ret < 0) {
721 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
722 goto pcm_err;
723 }
724
725 ret = snd_soc_add_controls(codec, wm8940_snd_controls,
726 ARRAY_SIZE(wm8940_snd_controls));
727 if (ret)
728 goto error_free_pcms;
729 ret = wm8940_add_widgets(codec);
730 if (ret)
731 goto error_free_pcms;
732
733 return ret;
734
735error_free_pcms:
736 snd_soc_free_pcms(socdev);
737 snd_soc_dapm_free(socdev);
738pcm_err:
739 return ret;
740}
741
742static int wm8940_remove(struct platform_device *pdev)
743{
744 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
745
746 snd_soc_free_pcms(socdev);
747 snd_soc_dapm_free(socdev);
748
749 return 0;
750}
751
752struct snd_soc_codec_device soc_codec_dev_wm8940 = {
753 .probe = wm8940_probe,
754 .remove = wm8940_remove,
755 .suspend = wm8940_suspend,
756 .resume = wm8940_resume,
757};
758EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940);
759
760static int wm8940_register(struct wm8940_priv *wm8940,
761 enum snd_soc_control_type control)
762{ 695{
763 struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data; 696 struct wm8940_priv *wm8940 = snd_soc_codec_get_drvdata(codec);
764 struct snd_soc_codec *codec = &wm8940->codec; 697 struct wm8940_setup_data *pdata = codec->dev->platform_data;
765 int ret; 698 int ret;
766 u16 reg; 699 u16 reg;
767 if (wm8940_codec) {
768 dev_err(codec->dev, "Another WM8940 is registered\n");
769 return -EINVAL;
770 }
771
772 INIT_LIST_HEAD(&codec->dapm_widgets);
773 INIT_LIST_HEAD(&codec->dapm_paths);
774
775 snd_soc_codec_set_drvdata(codec, wm8940);
776 codec->name = "WM8940";
777 codec->owner = THIS_MODULE;
778 codec->bias_level = SND_SOC_BIAS_OFF;
779 codec->set_bias_level = wm8940_set_bias_level;
780 codec->dai = &wm8940_dai;
781 codec->num_dai = 1;
782 codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults);
783 codec->reg_cache = &wm8940->reg_cache;
784 700
785 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); 701 codec->control_data = wm8940->control_data;
702 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
786 if (ret < 0) { 703 if (ret < 0) {
787 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 704 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
788 return ret; 705 return ret;
789 } 706 }
790 707
791 memcpy(codec->reg_cache, wm8940_reg_defaults,
792 sizeof(wm8940_reg_defaults));
793
794 ret = wm8940_reset(codec); 708 ret = wm8940_reset(codec);
795 if (ret < 0) { 709 if (ret < 0) {
796 dev_err(codec->dev, "Failed to issue reset\n"); 710 dev_err(codec->dev, "Failed to issue reset\n");
797 return ret; 711 return ret;
798 } 712 }
799 713
800 wm8940_dai.dev = codec->dev;
801
802 wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 714 wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
803 715
804 ret = snd_soc_write(codec, WM8940_POWER1, 0x180); 716 ret = snd_soc_write(codec, WM8940_POWER1, 0x180);
@@ -814,64 +726,60 @@ static int wm8940_register(struct wm8940_priv *wm8940,
814 return ret; 726 return ret;
815 } 727 }
816 728
817 729 ret = snd_soc_add_controls(codec, wm8940_snd_controls,
818 wm8940_codec = codec; 730 ARRAY_SIZE(wm8940_snd_controls));
819 731 if (ret)
820 ret = snd_soc_register_codec(codec);
821 if (ret) {
822 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
823 return ret; 732 return ret;
824 } 733 ret = wm8940_add_widgets(codec);
825 734 if (ret)
826 ret = snd_soc_register_dai(&wm8940_dai);
827 if (ret) {
828 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
829 snd_soc_unregister_codec(codec);
830 return ret; 735 return ret;
831 }
832 736
833 return 0; 737 return ret;
738;
834} 739}
835 740
836static void wm8940_unregister(struct wm8940_priv *wm8940) 741static int wm8940_remove(struct snd_soc_codec *codec)
837{ 742{
838 wm8940_set_bias_level(&wm8940->codec, SND_SOC_BIAS_OFF); 743 wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
839 snd_soc_unregister_dai(&wm8940_dai); 744 return 0;
840 snd_soc_unregister_codec(&wm8940->codec);
841 kfree(wm8940);
842 wm8940_codec = NULL;
843} 745}
844 746
845static int wm8940_i2c_probe(struct i2c_client *i2c, 747static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
846 const struct i2c_device_id *id) 748 .probe = wm8940_probe,
749 .remove = wm8940_remove,
750 .suspend = wm8940_suspend,
751 .resume = wm8940_resume,
752 .set_bias_level = wm8940_set_bias_level,
753 .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
754 .reg_word_size = sizeof(u16),
755 .reg_cache_default = wm8940_reg_defaults,
756};
757
758#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
759static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
760 const struct i2c_device_id *id)
847{ 761{
848 int ret;
849 struct wm8940_priv *wm8940; 762 struct wm8940_priv *wm8940;
850 struct snd_soc_codec *codec; 763 int ret;
851 764
852 wm8940 = kzalloc(sizeof *wm8940, GFP_KERNEL); 765 wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL);
853 if (wm8940 == NULL) 766 if (wm8940 == NULL)
854 return -ENOMEM; 767 return -ENOMEM;
855 768
856 codec = &wm8940->codec;
857 codec->hw_write = (hw_write_t)i2c_master_send;
858 i2c_set_clientdata(i2c, wm8940); 769 i2c_set_clientdata(i2c, wm8940);
859 codec->control_data = i2c; 770 wm8940->control_data = i2c;
860 codec->dev = &i2c->dev;
861 771
862 ret = wm8940_register(wm8940, SND_SOC_I2C); 772 ret = snd_soc_register_codec(&i2c->dev,
773 &soc_codec_dev_wm8940, &wm8940_dai, 1);
863 if (ret < 0) 774 if (ret < 0)
864 kfree(wm8940); 775 kfree(wm8940);
865
866 return ret; 776 return ret;
867} 777}
868 778
869static int __devexit wm8940_i2c_remove(struct i2c_client *client) 779static __devexit int wm8940_i2c_remove(struct i2c_client *client)
870{ 780{
871 struct wm8940_priv *wm8940 = i2c_get_clientdata(client); 781 snd_soc_unregister_codec(&client->dev);
872 782 kfree(i2c_get_clientdata(client));
873 wm8940_unregister(wm8940);
874
875 return 0; 783 return 0;
876} 784}
877 785
@@ -883,29 +791,34 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
883 791
884static struct i2c_driver wm8940_i2c_driver = { 792static struct i2c_driver wm8940_i2c_driver = {
885 .driver = { 793 .driver = {
886 .name = "WM8940 I2C Codec", 794 .name = "wm8940-codec",
887 .owner = THIS_MODULE, 795 .owner = THIS_MODULE,
888 }, 796 },
889 .probe = wm8940_i2c_probe, 797 .probe = wm8940_i2c_probe,
890 .remove = __devexit_p(wm8940_i2c_remove), 798 .remove = __devexit_p(wm8940_i2c_remove),
891 .id_table = wm8940_i2c_id, 799 .id_table = wm8940_i2c_id,
892}; 800};
801#endif
893 802
894static int __init wm8940_modinit(void) 803static int __init wm8940_modinit(void)
895{ 804{
896 int ret; 805 int ret = 0;
897 806#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
898 ret = i2c_add_driver(&wm8940_i2c_driver); 807 ret = i2c_add_driver(&wm8940_i2c_driver);
899 if (ret) 808 if (ret != 0) {
900 printk(KERN_ERR "Failed to register WM8940 I2C driver: %d\n", 809 printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n",
901 ret); 810 ret);
811 }
812#endif
902 return ret; 813 return ret;
903} 814}
904module_init(wm8940_modinit); 815module_init(wm8940_modinit);
905 816
906static void __exit wm8940_exit(void) 817static void __exit wm8940_exit(void)
907{ 818{
819#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
908 i2c_del_driver(&wm8940_i2c_driver); 820 i2c_del_driver(&wm8940_i2c_driver);
821#endif
909} 822}
910module_exit(wm8940_exit); 823module_exit(wm8940_exit);
911 824
diff --git a/sound/soc/codecs/wm8940.h b/sound/soc/codecs/wm8940.h
index 8410eed3ef84..907fe192e9e0 100644
--- a/sound/soc/codecs/wm8940.h
+++ b/sound/soc/codecs/wm8940.h
@@ -15,8 +15,6 @@ struct wm8940_setup_data {
15#define WM8940_VROI_30K 1 15#define WM8940_VROI_30K 1
16 unsigned int vroi:1; 16 unsigned int vroi:1;
17}; 17};
18extern struct snd_soc_dai wm8940_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8940;
20 18
21/* WM8940 register space */ 19/* WM8940 register space */
22#define WM8940_SOFTRESET 0x00 20#define WM8940_SOFTRESET 0x00
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 5f025593d84d..f89ad6c9a80b 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -30,9 +30,6 @@
30 30
31#include "wm8955.h" 31#include "wm8955.h"
32 32
33static struct snd_soc_codec *wm8955_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8955;
35
36#define WM8955_NUM_SUPPLIES 4 33#define WM8955_NUM_SUPPLIES 4
37static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { 34static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
38 "DCVDD", 35 "DCVDD",
@@ -43,7 +40,8 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
43 40
44/* codec private data */ 41/* codec private data */
45struct wm8955_priv { 42struct wm8955_priv {
46 struct snd_soc_codec codec; 43 enum snd_soc_control_type control_type;
44
47 u16 reg_cache[WM8955_MAX_REGISTER + 1]; 45 u16 reg_cache[WM8955_MAX_REGISTER + 1];
48 46
49 unsigned int mclk_rate; 47 unsigned int mclk_rate;
@@ -52,8 +50,6 @@ struct wm8955_priv {
52 int fs; 50 int fs;
53 51
54 struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; 52 struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
55
56 struct wm8955_pdata *pdata;
57}; 53};
58 54
59static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { 55static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
@@ -870,8 +866,8 @@ static struct snd_soc_dai_ops wm8955_dai_ops = {
870 .digital_mute = wm8955_digital_mute, 866 .digital_mute = wm8955_digital_mute,
871}; 867};
872 868
873struct snd_soc_dai wm8955_dai = { 869static struct snd_soc_dai_driver wm8955_dai = {
874 .name = "WM8955", 870 .name = "wm8955-hifi",
875 .playback = { 871 .playback = {
876 .stream_name = "Playback", 872 .stream_name = "Playback",
877 .channels_min = 2, 873 .channels_min = 2,
@@ -881,24 +877,17 @@ struct snd_soc_dai wm8955_dai = {
881 }, 877 },
882 .ops = &wm8955_dai_ops, 878 .ops = &wm8955_dai_ops,
883}; 879};
884EXPORT_SYMBOL_GPL(wm8955_dai);
885 880
886#ifdef CONFIG_PM 881#ifdef CONFIG_PM
887static int wm8955_suspend(struct platform_device *pdev, pm_message_t state) 882static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state)
888{ 883{
889 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
890 struct snd_soc_codec *codec = socdev->card->codec;
891
892 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); 884 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
893 885
894 return 0; 886 return 0;
895} 887}
896 888
897static int wm8955_resume(struct platform_device *pdev) 889static int wm8955_resume(struct snd_soc_codec *codec)
898{ 890{
899 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
900 struct snd_soc_codec *codec = socdev->card->codec;
901
902 wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 891 wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
903 892
904 return 0; 893 return 0;
@@ -908,86 +897,16 @@ static int wm8955_resume(struct platform_device *pdev)
908#define wm8955_resume NULL 897#define wm8955_resume NULL
909#endif 898#endif
910 899
911static int wm8955_probe(struct platform_device *pdev) 900static int wm8955_probe(struct snd_soc_codec *codec)
912{
913 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
914 struct snd_soc_codec *codec;
915 int ret = 0;
916
917 if (wm8955_codec == NULL) {
918 dev_err(&pdev->dev, "Codec device not registered\n");
919 return -ENODEV;
920 }
921
922 socdev->card->codec = wm8955_codec;
923 codec = wm8955_codec;
924
925 /* register pcms */
926 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
927 if (ret < 0) {
928 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
929 goto pcm_err;
930 }
931
932 wm8955_add_widgets(codec);
933
934 return ret;
935
936pcm_err:
937 return ret;
938}
939
940static int wm8955_remove(struct platform_device *pdev)
941{ 901{
942 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 902 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
943 903 struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
944 snd_soc_free_pcms(socdev); 904 int ret, i;
945 snd_soc_dapm_free(socdev);
946
947 return 0;
948}
949
950struct snd_soc_codec_device soc_codec_dev_wm8955 = {
951 .probe = wm8955_probe,
952 .remove = wm8955_remove,
953 .suspend = wm8955_suspend,
954 .resume = wm8955_resume,
955};
956EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955);
957
958static int wm8955_register(struct wm8955_priv *wm8955,
959 enum snd_soc_control_type control)
960{
961 int ret;
962 struct snd_soc_codec *codec = &wm8955->codec;
963 int i;
964
965 if (wm8955_codec) {
966 dev_err(codec->dev, "Another WM8955 is registered\n");
967 ret = -EINVAL;
968 goto err;
969 }
970
971 mutex_init(&codec->mutex);
972 INIT_LIST_HEAD(&codec->dapm_widgets);
973 INIT_LIST_HEAD(&codec->dapm_paths);
974
975 snd_soc_codec_set_drvdata(codec, wm8955);
976 codec->name = "WM8955";
977 codec->owner = THIS_MODULE;
978 codec->bias_level = SND_SOC_BIAS_OFF;
979 codec->set_bias_level = wm8955_set_bias_level;
980 codec->dai = &wm8955_dai;
981 codec->num_dai = 1;
982 codec->reg_cache_size = WM8955_MAX_REGISTER;
983 codec->reg_cache = &wm8955->reg_cache;
984
985 memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg));
986 905
987 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 906 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
988 if (ret != 0) { 907 if (ret != 0) {
989 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 908 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
990 goto err; 909 return ret;
991 } 910 }
992 911
993 for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) 912 for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++)
@@ -997,7 +916,7 @@ static int wm8955_register(struct wm8955_priv *wm8955,
997 wm8955->supplies); 916 wm8955->supplies);
998 if (ret != 0) { 917 if (ret != 0) {
999 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 918 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1000 goto err; 919 return ret;
1001 } 920 }
1002 921
1003 ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), 922 ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies),
@@ -1013,8 +932,6 @@ static int wm8955_register(struct wm8955_priv *wm8955,
1013 goto err_enable; 932 goto err_enable;
1014 } 933 }
1015 934
1016 wm8955_dai.dev = codec->dev;
1017
1018 /* Change some default settings - latch VU and enable ZC */ 935 /* Change some default settings - latch VU and enable ZC */
1019 wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; 936 wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
1020 wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; 937 wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
@@ -1028,12 +945,12 @@ static int wm8955_register(struct wm8955_priv *wm8955,
1028 wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; 945 wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
1029 946
1030 /* Set platform data values */ 947 /* Set platform data values */
1031 if (wm8955->pdata) { 948 if (pdata) {
1032 if (wm8955->pdata->out2_speaker) 949 if (pdata->out2_speaker)
1033 wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] 950 wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]
1034 |= WM8955_ROUT2INV; 951 |= WM8955_ROUT2INV;
1035 952
1036 if (wm8955->pdata->monoin_diff) 953 if (pdata->monoin_diff)
1037 wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] 954 wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]
1038 |= WM8955_DMEN; 955 |= WM8955_DMEN;
1039 } 956 }
@@ -1043,70 +960,60 @@ static int wm8955_register(struct wm8955_priv *wm8955,
1043 /* Bias level configuration will have done an extra enable */ 960 /* Bias level configuration will have done an extra enable */
1044 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 961 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1045 962
1046 wm8955_codec = codec; 963 wm8955_add_widgets(codec);
1047
1048 ret = snd_soc_register_codec(codec);
1049 if (ret != 0) {
1050 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1051 goto err_enable;
1052 }
1053
1054 ret = snd_soc_register_dai(&wm8955_dai);
1055 if (ret != 0) {
1056 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1057 goto err_codec;
1058 }
1059
1060 return 0; 964 return 0;
1061 965
1062err_codec:
1063 snd_soc_unregister_codec(codec);
1064err_enable: 966err_enable:
1065 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 967 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1066err_get: 968err_get:
1067 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 969 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1068err:
1069 kfree(wm8955);
1070 return ret; 970 return ret;
1071} 971}
1072 972
1073static void wm8955_unregister(struct wm8955_priv *wm8955) 973static int wm8955_remove(struct snd_soc_codec *codec)
1074{ 974{
1075 wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF); 975 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
976
977 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
1076 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 978 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1077 snd_soc_unregister_dai(&wm8955_dai); 979 return 0;
1078 snd_soc_unregister_codec(&wm8955->codec);
1079 kfree(wm8955);
1080 wm8955_codec = NULL;
1081} 980}
1082 981
982static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
983 .probe = wm8955_probe,
984 .remove = wm8955_remove,
985 .suspend = wm8955_suspend,
986 .resume = wm8955_resume,
987 .set_bias_level = wm8955_set_bias_level,
988 .reg_cache_size = ARRAY_SIZE(wm8955_reg),
989 .reg_word_size = sizeof(u16),
990 .reg_cache_default = wm8955_reg,
991};
992
1083#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 993#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1084static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, 994static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
1085 const struct i2c_device_id *id) 995 const struct i2c_device_id *id)
1086{ 996{
1087 struct wm8955_priv *wm8955; 997 struct wm8955_priv *wm8955;
1088 struct snd_soc_codec *codec; 998 int ret;
1089 999
1090 wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL); 1000 wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
1091 if (wm8955 == NULL) 1001 if (wm8955 == NULL)
1092 return -ENOMEM; 1002 return -ENOMEM;
1093 1003
1094 codec = &wm8955->codec;
1095 codec->hw_write = (hw_write_t)i2c_master_send;
1096
1097 i2c_set_clientdata(i2c, wm8955); 1004 i2c_set_clientdata(i2c, wm8955);
1098 codec->control_data = i2c;
1099 wm8955->pdata = i2c->dev.platform_data;
1100
1101 codec->dev = &i2c->dev;
1102 1005
1103 return wm8955_register(wm8955, SND_SOC_I2C); 1006 ret = snd_soc_register_codec(&i2c->dev,
1007 &soc_codec_dev_wm8955, &wm8955_dai, 1);
1008 if (ret < 0)
1009 kfree(wm8955);
1010 return ret;
1104} 1011}
1105 1012
1106static __devexit int wm8955_i2c_remove(struct i2c_client *client) 1013static __devexit int wm8955_i2c_remove(struct i2c_client *client)
1107{ 1014{
1108 struct wm8955_priv *wm8955 = i2c_get_clientdata(client); 1015 snd_soc_unregister_codec(&client->dev);
1109 wm8955_unregister(wm8955); 1016 kfree(i2c_get_clientdata(client));
1110 return 0; 1017 return 0;
1111} 1018}
1112 1019
@@ -1118,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
1118 1025
1119static struct i2c_driver wm8955_i2c_driver = { 1026static struct i2c_driver wm8955_i2c_driver = {
1120 .driver = { 1027 .driver = {
1121 .name = "wm8955", 1028 .name = "wm8955-codec",
1122 .owner = THIS_MODULE, 1029 .owner = THIS_MODULE,
1123 }, 1030 },
1124 .probe = wm8955_i2c_probe, 1031 .probe = wm8955_i2c_probe,
@@ -1129,7 +1036,7 @@ static struct i2c_driver wm8955_i2c_driver = {
1129 1036
1130static int __init wm8955_modinit(void) 1037static int __init wm8955_modinit(void)
1131{ 1038{
1132 int ret; 1039 int ret = 0;
1133#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1040#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1134 ret = i2c_add_driver(&wm8955_i2c_driver); 1041 ret = i2c_add_driver(&wm8955_i2c_driver);
1135 if (ret != 0) { 1042 if (ret != 0) {
@@ -1137,7 +1044,7 @@ static int __init wm8955_modinit(void)
1137 ret); 1044 ret);
1138 } 1045 }
1139#endif 1046#endif
1140 return 0; 1047 return ret;
1141} 1048}
1142module_init(wm8955_modinit); 1049module_init(wm8955_modinit);
1143 1050
diff --git a/sound/soc/codecs/wm8955.h b/sound/soc/codecs/wm8955.h
index ae349c8531f6..d13fd5c5fa63 100644
--- a/sound/soc/codecs/wm8955.h
+++ b/sound/soc/codecs/wm8955.h
@@ -15,9 +15,6 @@
15 15
16#define WM8955_CLK_MCLK 1 16#define WM8955_CLK_MCLK 1
17 17
18extern struct snd_soc_dai wm8955_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8955;
20
21/* 18/*
22 * Register values. 19 * Register values.
23 */ 20 */
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 3c6ee61f6c95..8d5efb333c33 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -29,8 +29,6 @@
29 29
30#define AUDIO_NAME "wm8960" 30#define AUDIO_NAME "wm8960"
31 31
32struct snd_soc_codec_device soc_codec_dev_wm8960;
33
34/* R25 - Power 1 */ 32/* R25 - Power 1 */
35#define WM8960_VMID_MASK 0x180 33#define WM8960_VMID_MASK 0x180
36#define WM8960_VREF 0x40 34#define WM8960_VREF 0x40
@@ -75,7 +73,10 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
75 73
76struct wm8960_priv { 74struct wm8960_priv {
77 u16 reg_cache[WM8960_CACHEREGNUM]; 75 u16 reg_cache[WM8960_CACHEREGNUM];
78 struct snd_soc_codec codec; 76 enum snd_soc_control_type control_type;
77 void *control_data;
78 int (*set_bias_level)(struct snd_soc_codec *,
79 enum snd_soc_bias_level level);
79 struct snd_soc_dapm_widget *lout1; 80 struct snd_soc_dapm_widget *lout1;
80 struct snd_soc_dapm_widget *rout1; 81 struct snd_soc_dapm_widget *rout1;
81 struct snd_soc_dapm_widget *out3; 82 struct snd_soc_dapm_widget *out3;
@@ -507,8 +508,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
507 struct snd_soc_dai *dai) 508 struct snd_soc_dai *dai)
508{ 509{
509 struct snd_soc_pcm_runtime *rtd = substream->private_data; 510 struct snd_soc_pcm_runtime *rtd = substream->private_data;
510 struct snd_soc_device *socdev = rtd->socdev; 511 struct snd_soc_codec *codec = rtd->codec;
511 struct snd_soc_codec *codec = socdev->card->codec;
512 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); 512 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
513 u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; 513 u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
514 int i; 514 int i;
@@ -849,6 +849,14 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
849 return 0; 849 return 0;
850} 850}
851 851
852static int wm8960_set_bias_level(struct snd_soc_codec *codec,
853 enum snd_soc_bias_level level)
854{
855 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
856
857 return wm8960->set_bias_level(codec, level);
858}
859
852#define WM8960_RATES SNDRV_PCM_RATE_8000_48000 860#define WM8960_RATES SNDRV_PCM_RATE_8000_48000
853 861
854#define WM8960_FORMATS \ 862#define WM8960_FORMATS \
@@ -863,8 +871,8 @@ static struct snd_soc_dai_ops wm8960_dai_ops = {
863 .set_pll = wm8960_set_dai_pll, 871 .set_pll = wm8960_set_dai_pll,
864}; 872};
865 873
866struct snd_soc_dai wm8960_dai = { 874static struct snd_soc_dai_driver wm8960_dai = {
867 .name = "WM8960", 875 .name = "wm8960-hifi",
868 .playback = { 876 .playback = {
869 .stream_name = "Playback", 877 .stream_name = "Playback",
870 .channels_min = 1, 878 .channels_min = 1,
@@ -880,21 +888,18 @@ struct snd_soc_dai wm8960_dai = {
880 .ops = &wm8960_dai_ops, 888 .ops = &wm8960_dai_ops,
881 .symmetric_rates = 1, 889 .symmetric_rates = 1,
882}; 890};
883EXPORT_SYMBOL_GPL(wm8960_dai);
884 891
885static int wm8960_suspend(struct platform_device *pdev, pm_message_t state) 892static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
886{ 893{
887 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 894 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
888 struct snd_soc_codec *codec = socdev->card->codec;
889 895
890 codec->set_bias_level(codec, SND_SOC_BIAS_OFF); 896 wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);
891 return 0; 897 return 0;
892} 898}
893 899
894static int wm8960_resume(struct platform_device *pdev) 900static int wm8960_resume(struct snd_soc_codec *codec)
895{ 901{
896 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 902 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
897 struct snd_soc_codec *codec = socdev->card->codec;
898 int i; 903 int i;
899 u8 data[2]; 904 u8 data[2];
900 u16 *cache = codec->reg_cache; 905 u16 *cache = codec->reg_cache;
@@ -906,78 +911,19 @@ static int wm8960_resume(struct platform_device *pdev)
906 codec->hw_write(codec->control_data, data, 2); 911 codec->hw_write(codec->control_data, data, 2);
907 } 912 }
908 913
909 codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); 914 wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
910
911 return 0; 915 return 0;
912} 916}
913 917
914static struct snd_soc_codec *wm8960_codec; 918static int wm8960_probe(struct snd_soc_codec *codec)
915
916static int wm8960_probe(struct platform_device *pdev)
917{
918 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
919 struct snd_soc_codec *codec;
920 int ret = 0;
921
922 if (wm8960_codec == NULL) {
923 dev_err(&pdev->dev, "Codec device not registered\n");
924 return -ENODEV;
925 }
926
927 socdev->card->codec = wm8960_codec;
928 codec = wm8960_codec;
929
930 /* register pcms */
931 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
932 if (ret < 0) {
933 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
934 goto pcm_err;
935 }
936
937 snd_soc_add_controls(codec, wm8960_snd_controls,
938 ARRAY_SIZE(wm8960_snd_controls));
939 wm8960_add_widgets(codec);
940
941 return ret;
942
943pcm_err:
944 return ret;
945}
946
947/* power down chip */
948static int wm8960_remove(struct platform_device *pdev)
949{
950 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
951
952 snd_soc_free_pcms(socdev);
953 snd_soc_dapm_free(socdev);
954
955 return 0;
956}
957
958struct snd_soc_codec_device soc_codec_dev_wm8960 = {
959 .probe = wm8960_probe,
960 .remove = wm8960_remove,
961 .suspend = wm8960_suspend,
962 .resume = wm8960_resume,
963};
964EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960);
965
966static int wm8960_register(struct wm8960_priv *wm8960,
967 enum snd_soc_control_type control)
968{ 919{
969 struct wm8960_data *pdata = wm8960->codec.dev->platform_data; 920 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
970 struct snd_soc_codec *codec = &wm8960->codec; 921 struct wm8960_data *pdata = dev_get_platdata(codec->dev);
971 int ret; 922 int ret;
972 u16 reg; 923 u16 reg;
973 924
974 if (wm8960_codec) { 925 wm8960->set_bias_level = wm8960_set_bias_level_out3;
975 dev_err(codec->dev, "Another WM8960 is registered\n"); 926 codec->control_data = wm8960->control_data;
976 ret = -EINVAL;
977 goto err;
978 }
979
980 codec->set_bias_level = wm8960_set_bias_level_out3;
981 927
982 if (!pdata) { 928 if (!pdata) {
983 dev_warn(codec->dev, "No platform data supplied\n"); 929 dev_warn(codec->dev, "No platform data supplied\n");
@@ -988,39 +934,22 @@ static int wm8960_register(struct wm8960_priv *wm8960,
988 } 934 }
989 935
990 if (pdata->capless) 936 if (pdata->capless)
991 codec->set_bias_level = wm8960_set_bias_level_capless; 937 wm8960->set_bias_level = wm8960_set_bias_level_capless;
992 } 938 }
993 939
994 mutex_init(&codec->mutex); 940 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type);
995 INIT_LIST_HEAD(&codec->dapm_widgets);
996 INIT_LIST_HEAD(&codec->dapm_paths);
997
998 snd_soc_codec_set_drvdata(codec, wm8960);
999 codec->name = "WM8960";
1000 codec->owner = THIS_MODULE;
1001 codec->bias_level = SND_SOC_BIAS_OFF;
1002 codec->dai = &wm8960_dai;
1003 codec->num_dai = 1;
1004 codec->reg_cache_size = WM8960_CACHEREGNUM;
1005 codec->reg_cache = &wm8960->reg_cache;
1006
1007 memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
1008
1009 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
1010 if (ret < 0) { 941 if (ret < 0) {
1011 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 942 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1012 goto err; 943 return ret;
1013 } 944 }
1014 945
1015 ret = wm8960_reset(codec); 946 ret = wm8960_reset(codec);
1016 if (ret < 0) { 947 if (ret < 0) {
1017 dev_err(codec->dev, "Failed to issue reset\n"); 948 dev_err(codec->dev, "Failed to issue reset\n");
1018 goto err; 949 return ret;
1019 } 950 }
1020 951
1021 wm8960_dai.dev = codec->dev; 952 wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1022
1023 codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1024 953
1025 /* Latch the update bits */ 954 /* Latch the update bits */
1026 reg = snd_soc_read(codec, WM8960_LINVOL); 955 reg = snd_soc_read(codec, WM8960_LINVOL);
@@ -1044,62 +973,58 @@ static int wm8960_register(struct wm8960_priv *wm8960,
1044 reg = snd_soc_read(codec, WM8960_ROUT2); 973 reg = snd_soc_read(codec, WM8960_ROUT2);
1045 snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); 974 snd_soc_write(codec, WM8960_ROUT2, reg | 0x100);
1046 975
1047 wm8960_codec = codec; 976 snd_soc_add_controls(codec, wm8960_snd_controls,
1048 977 ARRAY_SIZE(wm8960_snd_controls));
1049 ret = snd_soc_register_codec(codec); 978 wm8960_add_widgets(codec);
1050 if (ret != 0) {
1051 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1052 goto err;
1053 }
1054
1055 ret = snd_soc_register_dai(&wm8960_dai);
1056 if (ret != 0) {
1057 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1058 goto err_codec;
1059 }
1060 979
1061 return 0; 980 return 0;
1062
1063err_codec:
1064 snd_soc_unregister_codec(codec);
1065err:
1066 kfree(wm8960);
1067 return ret;
1068} 981}
1069 982
1070static void wm8960_unregister(struct wm8960_priv *wm8960) 983/* power down chip */
984static int wm8960_remove(struct snd_soc_codec *codec)
1071{ 985{
1072 wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); 986 struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
1073 snd_soc_unregister_dai(&wm8960_dai); 987
1074 snd_soc_unregister_codec(&wm8960->codec); 988 wm8960->set_bias_level(codec, SND_SOC_BIAS_OFF);
1075 kfree(wm8960); 989 return 0;
1076 wm8960_codec = NULL;
1077} 990}
1078 991
992static struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
993 .probe = wm8960_probe,
994 .remove = wm8960_remove,
995 .suspend = wm8960_suspend,
996 .resume = wm8960_resume,
997 .set_bias_level = wm8960_set_bias_level,
998 .reg_cache_size = ARRAY_SIZE(wm8960_reg),
999 .reg_word_size = sizeof(u16),
1000 .reg_cache_default = wm8960_reg,
1001};
1002
1003#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1079static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, 1004static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
1080 const struct i2c_device_id *id) 1005 const struct i2c_device_id *id)
1081{ 1006{
1082 struct wm8960_priv *wm8960; 1007 struct wm8960_priv *wm8960;
1083 struct snd_soc_codec *codec; 1008 int ret;
1084 1009
1085 wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL); 1010 wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);
1086 if (wm8960 == NULL) 1011 if (wm8960 == NULL)
1087 return -ENOMEM; 1012 return -ENOMEM;
1088 1013
1089 codec = &wm8960->codec;
1090
1091 i2c_set_clientdata(i2c, wm8960); 1014 i2c_set_clientdata(i2c, wm8960);
1092 codec->control_data = i2c; 1015 wm8960->control_data = i2c;
1093
1094 codec->dev = &i2c->dev;
1095 1016
1096 return wm8960_register(wm8960, SND_SOC_I2C); 1017 ret = snd_soc_register_codec(&i2c->dev,
1018 &soc_codec_dev_wm8960, &wm8960_dai, 1);
1019 if (ret < 0)
1020 kfree(wm8960);
1021 return ret;
1097} 1022}
1098 1023
1099static __devexit int wm8960_i2c_remove(struct i2c_client *client) 1024static __devexit int wm8960_i2c_remove(struct i2c_client *client)
1100{ 1025{
1101 struct wm8960_priv *wm8960 = i2c_get_clientdata(client); 1026 snd_soc_unregister_codec(&client->dev);
1102 wm8960_unregister(wm8960); 1027 kfree(i2c_get_clientdata(client));
1103 return 0; 1028 return 0;
1104} 1029}
1105 1030
@@ -1111,35 +1036,37 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
1111 1036
1112static struct i2c_driver wm8960_i2c_driver = { 1037static struct i2c_driver wm8960_i2c_driver = {
1113 .driver = { 1038 .driver = {
1114 .name = "wm8960", 1039 .name = "wm8960-codec",
1115 .owner = THIS_MODULE, 1040 .owner = THIS_MODULE,
1116 }, 1041 },
1117 .probe = wm8960_i2c_probe, 1042 .probe = wm8960_i2c_probe,
1118 .remove = __devexit_p(wm8960_i2c_remove), 1043 .remove = __devexit_p(wm8960_i2c_remove),
1119 .id_table = wm8960_i2c_id, 1044 .id_table = wm8960_i2c_id,
1120}; 1045};
1046#endif
1121 1047
1122static int __init wm8960_modinit(void) 1048static int __init wm8960_modinit(void)
1123{ 1049{
1124 int ret; 1050 int ret = 0;
1125 1051#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1126 ret = i2c_add_driver(&wm8960_i2c_driver); 1052 ret = i2c_add_driver(&wm8960_i2c_driver);
1127 if (ret != 0) { 1053 if (ret != 0) {
1128 printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", 1054 printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
1129 ret); 1055 ret);
1130 } 1056 }
1131 1057#endif
1132 return ret; 1058 return ret;
1133} 1059}
1134module_init(wm8960_modinit); 1060module_init(wm8960_modinit);
1135 1061
1136static void __exit wm8960_exit(void) 1062static void __exit wm8960_exit(void)
1137{ 1063{
1064#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1138 i2c_del_driver(&wm8960_i2c_driver); 1065 i2c_del_driver(&wm8960_i2c_driver);
1066#endif
1139} 1067}
1140module_exit(wm8960_exit); 1068module_exit(wm8960_exit);
1141 1069
1142
1143MODULE_DESCRIPTION("ASoC WM8960 driver"); 1070MODULE_DESCRIPTION("ASoC WM8960 driver");
1144MODULE_AUTHOR("Liam Girdwood"); 1071MODULE_AUTHOR("Liam Girdwood");
1145MODULE_LICENSE("GPL"); 1072MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8960.h b/sound/soc/codecs/wm8960.h
index a5ef65481b86..2d8163d7004b 100644
--- a/sound/soc/codecs/wm8960.h
+++ b/sound/soc/codecs/wm8960.h
@@ -110,7 +110,4 @@
110#define WM8960_OPCLK_DIV_5_5 (4 << 0) 110#define WM8960_OPCLK_DIV_5_5 (4 << 0)
111#define WM8960_OPCLK_DIV_6 (5 << 0) 111#define WM8960_OPCLK_DIV_6 (5 << 0)
112 112
113extern struct snd_soc_dai wm8960_dai;
114extern struct snd_soc_codec_device soc_codec_dev_wm8960;
115
116#endif 113#endif
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 2549d3a297ab..4f326f604104 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -288,7 +288,7 @@ static u16 wm8961_reg_defaults[] = {
288}; 288};
289 289
290struct wm8961_priv { 290struct wm8961_priv {
291 struct snd_soc_codec codec; 291 enum snd_soc_control_type control_type;
292 int sysclk; 292 int sysclk;
293 u16 reg_cache[WM8961_MAX_REGISTER]; 293 u16 reg_cache[WM8961_MAX_REGISTER];
294}; 294};
@@ -940,8 +940,8 @@ static struct snd_soc_dai_ops wm8961_dai_ops = {
940 .set_clkdiv = wm8961_set_clkdiv, 940 .set_clkdiv = wm8961_set_clkdiv,
941}; 941};
942 942
943struct snd_soc_dai wm8961_dai = { 943static struct snd_soc_dai_driver wm8961_dai = {
944 .name = "WM8961", 944 .name = "wm8961-hifi",
945 .playback = { 945 .playback = {
946 .stream_name = "HiFi Playback", 946 .stream_name = "HiFi Playback",
947 .channels_min = 1, 947 .channels_min = 1,
@@ -956,140 +956,22 @@ struct snd_soc_dai wm8961_dai = {
956 .formats = WM8961_FORMATS,}, 956 .formats = WM8961_FORMATS,},
957 .ops = &wm8961_dai_ops, 957 .ops = &wm8961_dai_ops,
958}; 958};
959EXPORT_SYMBOL_GPL(wm8961_dai);
960 959
961 960static int wm8961_probe(struct snd_soc_codec *codec)
962static struct snd_soc_codec *wm8961_codec;
963
964static int wm8961_probe(struct platform_device *pdev)
965{ 961{
966 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
967 struct snd_soc_codec *codec;
968 int ret = 0; 962 int ret = 0;
969
970 if (wm8961_codec == NULL) {
971 dev_err(&pdev->dev, "Codec device not registered\n");
972 return -ENODEV;
973 }
974
975 socdev->card->codec = wm8961_codec;
976 codec = wm8961_codec;
977
978 /* register pcms */
979 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
980 if (ret < 0) {
981 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
982 goto pcm_err;
983 }
984
985 snd_soc_add_controls(codec, wm8961_snd_controls,
986 ARRAY_SIZE(wm8961_snd_controls));
987 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
988 ARRAY_SIZE(wm8961_dapm_widgets));
989 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
990
991 return ret;
992
993pcm_err:
994 return ret;
995}
996
997static int wm8961_remove(struct platform_device *pdev)
998{
999 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1000
1001 snd_soc_free_pcms(socdev);
1002 snd_soc_dapm_free(socdev);
1003
1004 return 0;
1005}
1006
1007#ifdef CONFIG_PM
1008static int wm8961_suspend(struct platform_device *pdev, pm_message_t state)
1009{
1010 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1011 struct snd_soc_codec *codec = socdev->card->codec;
1012
1013 wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
1014
1015 return 0;
1016}
1017
1018static int wm8961_resume(struct platform_device *pdev)
1019{
1020 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1021 struct snd_soc_codec *codec = socdev->card->codec;
1022 u16 *reg_cache = codec->reg_cache;
1023 int i;
1024
1025 for (i = 0; i < codec->reg_cache_size; i++) {
1026 if (reg_cache[i] == wm8961_reg_defaults[i])
1027 continue;
1028
1029 if (i == WM8961_SOFTWARE_RESET)
1030 continue;
1031
1032 snd_soc_write(codec, i, reg_cache[i]);
1033 }
1034
1035 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1036
1037 return 0;
1038}
1039#else
1040#define wm8961_suspend NULL
1041#define wm8961_resume NULL
1042#endif
1043
1044struct snd_soc_codec_device soc_codec_dev_wm8961 = {
1045 .probe = wm8961_probe,
1046 .remove = wm8961_remove,
1047 .suspend = wm8961_suspend,
1048 .resume = wm8961_resume,
1049};
1050EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961);
1051
1052static int wm8961_register(struct wm8961_priv *wm8961)
1053{
1054 struct snd_soc_codec *codec = &wm8961->codec;
1055 int ret;
1056 u16 reg; 963 u16 reg;
1057 964
1058 if (wm8961_codec) {
1059 dev_err(codec->dev, "Another WM8961 is registered\n");
1060 ret = -EINVAL;
1061 goto err;
1062 }
1063
1064 mutex_init(&codec->mutex);
1065 INIT_LIST_HEAD(&codec->dapm_widgets);
1066 INIT_LIST_HEAD(&codec->dapm_paths);
1067
1068 snd_soc_codec_set_drvdata(codec, wm8961);
1069 codec->name = "WM8961";
1070 codec->owner = THIS_MODULE;
1071 codec->dai = &wm8961_dai;
1072 codec->num_dai = 1;
1073 codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache);
1074 codec->reg_cache = &wm8961->reg_cache;
1075 codec->bias_level = SND_SOC_BIAS_OFF;
1076 codec->set_bias_level = wm8961_set_bias_level;
1077 codec->volatile_register = wm8961_volatile_register;
1078
1079 memcpy(codec->reg_cache, wm8961_reg_defaults,
1080 sizeof(wm8961_reg_defaults));
1081
1082 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); 965 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1083 if (ret != 0) { 966 if (ret != 0) {
1084 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 967 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1085 goto err; 968 return ret;
1086 } 969 }
1087 970
1088 reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); 971 reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET);
1089 if (reg != 0x1801) { 972 if (reg != 0x1801) {
1090 dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); 973 dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg);
1091 ret = -EINVAL; 974 return -EINVAL;
1092 goto err;
1093 } 975 }
1094 976
1095 /* This isn't volatile - readback doesn't correspond to write */ 977 /* This isn't volatile - readback doesn't correspond to write */
@@ -1102,7 +984,7 @@ static int wm8961_register(struct wm8961_priv *wm8961)
1102 ret = wm8961_reset(codec); 984 ret = wm8961_reset(codec);
1103 if (ret < 0) { 985 if (ret < 0) {
1104 dev_err(codec->dev, "Failed to issue reset\n"); 986 dev_err(codec->dev, "Failed to issue reset\n");
1105 goto err; 987 return ret;
1106 } 988 }
1107 989
1108 /* Enable class W */ 990 /* Enable class W */
@@ -1140,64 +1022,89 @@ static int wm8961_register(struct wm8961_priv *wm8961)
1140 1022
1141 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1023 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1142 1024
1143 wm8961_dai.dev = codec->dev; 1025 snd_soc_add_controls(codec, wm8961_snd_controls,
1026 ARRAY_SIZE(wm8961_snd_controls));
1027 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
1028 ARRAY_SIZE(wm8961_dapm_widgets));
1029 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
1144 1030
1145 wm8961_codec = codec; 1031 return 0;
1032}
1146 1033
1147 ret = snd_soc_register_codec(codec); 1034static int wm8961_remove(struct snd_soc_codec *codec)
1148 if (ret != 0) { 1035{
1149 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 1036 wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
1150 goto err; 1037 return 0;
1151 } 1038}
1152 1039
1153 ret = snd_soc_register_dai(&wm8961_dai); 1040#ifdef CONFIG_PM
1154 if (ret != 0) { 1041static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state)
1155 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 1042{
1156 goto err_codec; 1043 wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
1157 }
1158 1044
1159 return 0; 1045 return 0;
1160
1161err_codec:
1162 snd_soc_unregister_codec(codec);
1163err:
1164 kfree(wm8961);
1165 return ret;
1166} 1046}
1167 1047
1168static void wm8961_unregister(struct wm8961_priv *wm8961) 1048static int wm8961_resume(struct snd_soc_codec *codec)
1169{ 1049{
1170 wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF); 1050 u16 *reg_cache = codec->reg_cache;
1171 snd_soc_unregister_dai(&wm8961_dai); 1051 int i;
1172 snd_soc_unregister_codec(&wm8961->codec); 1052
1173 kfree(wm8961); 1053 for (i = 0; i < codec->driver->reg_cache_size; i++) {
1174 wm8961_codec = NULL; 1054 if (reg_cache[i] == wm8961_reg_defaults[i])
1055 continue;
1056
1057 if (i == WM8961_SOFTWARE_RESET)
1058 continue;
1059
1060 snd_soc_write(codec, i, reg_cache[i]);
1061 }
1062
1063 wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1064
1065 return 0;
1175} 1066}
1067#else
1068#define wm8961_suspend NULL
1069#define wm8961_resume NULL
1070#endif
1071
1072static struct snd_soc_codec_driver soc_codec_dev_wm8961 = {
1073 .probe = wm8961_probe,
1074 .remove = wm8961_remove,
1075 .suspend = wm8961_suspend,
1076 .resume = wm8961_resume,
1077 .set_bias_level = wm8961_set_bias_level,
1078 .reg_cache_size = ARRAY_SIZE(wm8961_reg_defaults),
1079 .reg_word_size = sizeof(u16),
1080 .reg_cache_default = wm8961_reg_defaults,
1081 .volatile_register = wm8961_volatile_register,
1082};
1176 1083
1084#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1177static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, 1085static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
1178 const struct i2c_device_id *id) 1086 const struct i2c_device_id *id)
1179{ 1087{
1180 struct wm8961_priv *wm8961; 1088 struct wm8961_priv *wm8961;
1181 struct snd_soc_codec *codec; 1089 int ret;
1182 1090
1183 wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL); 1091 wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL);
1184 if (wm8961 == NULL) 1092 if (wm8961 == NULL)
1185 return -ENOMEM; 1093 return -ENOMEM;
1186 1094
1187 codec = &wm8961->codec;
1188
1189 i2c_set_clientdata(i2c, wm8961); 1095 i2c_set_clientdata(i2c, wm8961);
1190 codec->control_data = i2c;
1191
1192 codec->dev = &i2c->dev;
1193 1096
1194 return wm8961_register(wm8961); 1097 ret = snd_soc_register_codec(&i2c->dev,
1098 &soc_codec_dev_wm8961, &wm8961_dai, 1);
1099 if (ret < 0)
1100 kfree(wm8961);
1101 return ret;
1195} 1102}
1196 1103
1197static __devexit int wm8961_i2c_remove(struct i2c_client *client) 1104static __devexit int wm8961_i2c_remove(struct i2c_client *client)
1198{ 1105{
1199 struct wm8961_priv *wm8961 = i2c_get_clientdata(client); 1106 snd_soc_unregister_codec(&client->dev);
1200 wm8961_unregister(wm8961); 1107 kfree(i2c_get_clientdata(client));
1201 return 0; 1108 return 0;
1202} 1109}
1203 1110
@@ -1209,35 +1116,37 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
1209 1116
1210static struct i2c_driver wm8961_i2c_driver = { 1117static struct i2c_driver wm8961_i2c_driver = {
1211 .driver = { 1118 .driver = {
1212 .name = "wm8961", 1119 .name = "wm8961-codec",
1213 .owner = THIS_MODULE, 1120 .owner = THIS_MODULE,
1214 }, 1121 },
1215 .probe = wm8961_i2c_probe, 1122 .probe = wm8961_i2c_probe,
1216 .remove = __devexit_p(wm8961_i2c_remove), 1123 .remove = __devexit_p(wm8961_i2c_remove),
1217 .id_table = wm8961_i2c_id, 1124 .id_table = wm8961_i2c_id,
1218}; 1125};
1126#endif
1219 1127
1220static int __init wm8961_modinit(void) 1128static int __init wm8961_modinit(void)
1221{ 1129{
1222 int ret; 1130 int ret = 0;
1223 1131#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1224 ret = i2c_add_driver(&wm8961_i2c_driver); 1132 ret = i2c_add_driver(&wm8961_i2c_driver);
1225 if (ret != 0) { 1133 if (ret != 0) {
1226 printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n", 1134 printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n",
1227 ret); 1135 ret);
1228 } 1136 }
1229 1137#endif
1230 return ret; 1138 return ret;
1231} 1139}
1232module_init(wm8961_modinit); 1140module_init(wm8961_modinit);
1233 1141
1234static void __exit wm8961_exit(void) 1142static void __exit wm8961_exit(void)
1235{ 1143{
1144#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1236 i2c_del_driver(&wm8961_i2c_driver); 1145 i2c_del_driver(&wm8961_i2c_driver);
1146#endif
1237} 1147}
1238module_exit(wm8961_exit); 1148module_exit(wm8961_exit);
1239 1149
1240
1241MODULE_DESCRIPTION("ASoC WM8961 driver"); 1150MODULE_DESCRIPTION("ASoC WM8961 driver");
1242MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 1151MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1243MODULE_LICENSE("GPL"); 1152MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8961.h b/sound/soc/codecs/wm8961.h
index 5513bfd720d6..1d736e5701c8 100644
--- a/sound/soc/codecs/wm8961.h
+++ b/sound/soc/codecs/wm8961.h
@@ -11,9 +11,6 @@
11 11
12#include <sound/soc.h> 12#include <sound/soc.h>
13 13
14extern struct snd_soc_codec_device soc_codec_dev_wm8961;
15extern struct snd_soc_dai wm8961_dai;
16
17#define WM8961_BCLK 1 14#define WM8961_BCLK 1
18#define WM8961_LRCLK 2 15#define WM8961_LRCLK 2
19 16
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
new file mode 100644
index 000000000000..894d0cd3aa9b
--- /dev/null
+++ b/sound/soc/codecs/wm8962.c
@@ -0,0 +1,3977 @@
1/*
2 * wm8962.c -- WM8962 ALSA SoC Audio driver
3 *
4 * Copyright 2010 Wolfson Microelectronics plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/pm.h>
19#include <linux/gcd.h>
20#include <linux/gpio.h>
21#include <linux/i2c.h>
22#include <linux/input.h>
23#include <linux/platform_device.h>
24#include <linux/regulator/consumer.h>
25#include <linux/slab.h>
26#include <linux/workqueue.h>
27#include <sound/core.h>
28#include <sound/jack.h>
29#include <sound/pcm.h>
30#include <sound/pcm_params.h>
31#include <sound/soc.h>
32#include <sound/soc-dapm.h>
33#include <sound/initval.h>
34#include <sound/tlv.h>
35#include <sound/wm8962.h>
36
37#include "wm8962.h"
38
39#define WM8962_NUM_SUPPLIES 8
40static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
41 "DCVDD",
42 "DBVDD",
43 "AVDD",
44 "CPVDD",
45 "MICVDD",
46 "PLLVDD",
47 "SPKVDD1",
48 "SPKVDD2",
49};
50
51/* codec private data */
52struct wm8962_priv {
53 struct snd_soc_codec *codec;
54
55 u16 reg_cache[WM8962_MAX_REGISTER + 1];
56
57 int sysclk;
58 int sysclk_rate;
59
60 int bclk; /* Desired BCLK */
61 int lrclk;
62
63 int fll_src;
64 int fll_fref;
65 int fll_fout;
66
67 struct delayed_work mic_work;
68 struct snd_soc_jack *jack;
69
70 struct regulator_bulk_data supplies[WM8962_NUM_SUPPLIES];
71 struct notifier_block disable_nb[WM8962_NUM_SUPPLIES];
72
73#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
74 struct input_dev *beep;
75 struct work_struct beep_work;
76 int beep_rate;
77#endif
78
79#ifdef CONFIG_GPIOLIB
80 struct gpio_chip gpio_chip;
81#endif
82};
83
84/* We can't use the same notifier block for more than one supply and
85 * there's no way I can see to get from a callback to the caller
86 * except container_of().
87 */
88#define WM8962_REGULATOR_EVENT(n) \
89static int wm8962_regulator_event_##n(struct notifier_block *nb, \
90 unsigned long event, void *data) \
91{ \
92 struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
93 disable_nb[n]); \
94 if (event & REGULATOR_EVENT_DISABLE) { \
95 wm8962->codec->cache_sync = 1; \
96 } \
97 return 0; \
98}
99
100WM8962_REGULATOR_EVENT(0)
101WM8962_REGULATOR_EVENT(1)
102WM8962_REGULATOR_EVENT(2)
103WM8962_REGULATOR_EVENT(3)
104WM8962_REGULATOR_EVENT(4)
105WM8962_REGULATOR_EVENT(5)
106WM8962_REGULATOR_EVENT(6)
107WM8962_REGULATOR_EVENT(7)
108
109static const u16 wm8962_reg[WM8962_MAX_REGISTER + 1] = {
110 [0] = 0x009F, /* R0 - Left Input volume */
111 [1] = 0x049F, /* R1 - Right Input volume */
112 [2] = 0x0000, /* R2 - HPOUTL volume */
113 [3] = 0x0000, /* R3 - HPOUTR volume */
114 [4] = 0x0020, /* R4 - Clocking1 */
115 [5] = 0x0018, /* R5 - ADC & DAC Control 1 */
116 [6] = 0x2008, /* R6 - ADC & DAC Control 2 */
117 [7] = 0x000A, /* R7 - Audio Interface 0 */
118 [8] = 0x01E4, /* R8 - Clocking2 */
119 [9] = 0x0300, /* R9 - Audio Interface 1 */
120 [10] = 0x00C0, /* R10 - Left DAC volume */
121 [11] = 0x00C0, /* R11 - Right DAC volume */
122
123 [14] = 0x0040, /* R14 - Audio Interface 2 */
124 [15] = 0x6243, /* R15 - Software Reset */
125
126 [17] = 0x007B, /* R17 - ALC1 */
127 [18] = 0x0000, /* R18 - ALC2 */
128 [19] = 0x1C32, /* R19 - ALC3 */
129 [20] = 0x3200, /* R20 - Noise Gate */
130 [21] = 0x00C0, /* R21 - Left ADC volume */
131 [22] = 0x00C0, /* R22 - Right ADC volume */
132 [23] = 0x0160, /* R23 - Additional control(1) */
133 [24] = 0x0000, /* R24 - Additional control(2) */
134 [25] = 0x0000, /* R25 - Pwr Mgmt (1) */
135 [26] = 0x0000, /* R26 - Pwr Mgmt (2) */
136 [27] = 0x0010, /* R27 - Additional Control (3) */
137 [28] = 0x0000, /* R28 - Anti-pop */
138
139 [30] = 0x005E, /* R30 - Clocking 3 */
140 [31] = 0x0000, /* R31 - Input mixer control (1) */
141 [32] = 0x0145, /* R32 - Left input mixer volume */
142 [33] = 0x0145, /* R33 - Right input mixer volume */
143 [34] = 0x0009, /* R34 - Input mixer control (2) */
144 [35] = 0x0003, /* R35 - Input bias control */
145 [37] = 0x0008, /* R37 - Left input PGA control */
146 [38] = 0x0008, /* R38 - Right input PGA control */
147
148 [40] = 0x0000, /* R40 - SPKOUTL volume */
149 [41] = 0x0000, /* R41 - SPKOUTR volume */
150
151 [47] = 0x0000, /* R47 - Thermal Shutdown Status */
152 [48] = 0x8027, /* R48 - Additional Control (4) */
153 [49] = 0x0010, /* R49 - Class D Control 1 */
154
155 [51] = 0x0003, /* R51 - Class D Control 2 */
156
157 [56] = 0x0506, /* R56 - Clocking 4 */
158 [57] = 0x0000, /* R57 - DAC DSP Mixing (1) */
159 [58] = 0x0000, /* R58 - DAC DSP Mixing (2) */
160
161 [60] = 0x0300, /* R60 - DC Servo 0 */
162 [61] = 0x0300, /* R61 - DC Servo 1 */
163
164 [64] = 0x0810, /* R64 - DC Servo 4 */
165
166 [66] = 0x0000, /* R66 - DC Servo 6 */
167
168 [68] = 0x001B, /* R68 - Analogue PGA Bias */
169 [69] = 0x0000, /* R69 - Analogue HP 0 */
170
171 [71] = 0x01FB, /* R71 - Analogue HP 2 */
172 [72] = 0x0000, /* R72 - Charge Pump 1 */
173
174 [82] = 0x0004, /* R82 - Charge Pump B */
175
176 [87] = 0x0000, /* R87 - Write Sequencer Control 1 */
177
178 [90] = 0x0000, /* R90 - Write Sequencer Control 2 */
179
180 [93] = 0x0000, /* R93 - Write Sequencer Control 3 */
181 [94] = 0x0000, /* R94 - Control Interface */
182
183 [99] = 0x0000, /* R99 - Mixer Enables */
184 [100] = 0x0000, /* R100 - Headphone Mixer (1) */
185 [101] = 0x0000, /* R101 - Headphone Mixer (2) */
186 [102] = 0x013F, /* R102 - Headphone Mixer (3) */
187 [103] = 0x013F, /* R103 - Headphone Mixer (4) */
188
189 [105] = 0x0000, /* R105 - Speaker Mixer (1) */
190 [106] = 0x0000, /* R106 - Speaker Mixer (2) */
191 [107] = 0x013F, /* R107 - Speaker Mixer (3) */
192 [108] = 0x013F, /* R108 - Speaker Mixer (4) */
193 [109] = 0x0003, /* R109 - Speaker Mixer (5) */
194 [110] = 0x0002, /* R110 - Beep Generator (1) */
195
196 [115] = 0x0006, /* R115 - Oscillator Trim (3) */
197 [116] = 0x0026, /* R116 - Oscillator Trim (4) */
198
199 [119] = 0x0000, /* R119 - Oscillator Trim (7) */
200
201 [124] = 0x0011, /* R124 - Analogue Clocking1 */
202 [125] = 0x004B, /* R125 - Analogue Clocking2 */
203 [126] = 0x000D, /* R126 - Analogue Clocking3 */
204 [127] = 0x0000, /* R127 - PLL Software Reset */
205
206 [129] = 0x0000, /* R129 - PLL2 */
207
208 [131] = 0x0000, /* R131 - PLL 4 */
209
210 [136] = 0x0067, /* R136 - PLL 9 */
211 [137] = 0x001C, /* R137 - PLL 10 */
212 [138] = 0x0071, /* R138 - PLL 11 */
213 [139] = 0x00C7, /* R139 - PLL 12 */
214 [140] = 0x0067, /* R140 - PLL 13 */
215 [141] = 0x0048, /* R141 - PLL 14 */
216 [142] = 0x0022, /* R142 - PLL 15 */
217 [143] = 0x0097, /* R143 - PLL 16 */
218
219 [155] = 0x000C, /* R155 - FLL Control (1) */
220 [156] = 0x0039, /* R156 - FLL Control (2) */
221 [157] = 0x0180, /* R157 - FLL Control (3) */
222
223 [159] = 0x0032, /* R159 - FLL Control (5) */
224 [160] = 0x0018, /* R160 - FLL Control (6) */
225 [161] = 0x007D, /* R161 - FLL Control (7) */
226 [162] = 0x0008, /* R162 - FLL Control (8) */
227
228 [252] = 0x0005, /* R252 - General test 1 */
229
230 [256] = 0x0000, /* R256 - DF1 */
231 [257] = 0x0000, /* R257 - DF2 */
232 [258] = 0x0000, /* R258 - DF3 */
233 [259] = 0x0000, /* R259 - DF4 */
234 [260] = 0x0000, /* R260 - DF5 */
235 [261] = 0x0000, /* R261 - DF6 */
236 [262] = 0x0000, /* R262 - DF7 */
237
238 [264] = 0x0000, /* R264 - LHPF1 */
239 [265] = 0x0000, /* R265 - LHPF2 */
240
241 [268] = 0x0000, /* R268 - THREED1 */
242 [269] = 0x0000, /* R269 - THREED2 */
243 [270] = 0x0000, /* R270 - THREED3 */
244 [271] = 0x0000, /* R271 - THREED4 */
245
246 [276] = 0x000C, /* R276 - DRC 1 */
247 [277] = 0x0925, /* R277 - DRC 2 */
248 [278] = 0x0000, /* R278 - DRC 3 */
249 [279] = 0x0000, /* R279 - DRC 4 */
250 [280] = 0x0000, /* R280 - DRC 5 */
251
252 [285] = 0x0000, /* R285 - Tloopback */
253
254 [335] = 0x0004, /* R335 - EQ1 */
255 [336] = 0x6318, /* R336 - EQ2 */
256 [337] = 0x6300, /* R337 - EQ3 */
257 [338] = 0x0FCA, /* R338 - EQ4 */
258 [339] = 0x0400, /* R339 - EQ5 */
259 [340] = 0x00D8, /* R340 - EQ6 */
260 [341] = 0x1EB5, /* R341 - EQ7 */
261 [342] = 0xF145, /* R342 - EQ8 */
262 [343] = 0x0B75, /* R343 - EQ9 */
263 [344] = 0x01C5, /* R344 - EQ10 */
264 [345] = 0x1C58, /* R345 - EQ11 */
265 [346] = 0xF373, /* R346 - EQ12 */
266 [347] = 0x0A54, /* R347 - EQ13 */
267 [348] = 0x0558, /* R348 - EQ14 */
268 [349] = 0x168E, /* R349 - EQ15 */
269 [350] = 0xF829, /* R350 - EQ16 */
270 [351] = 0x07AD, /* R351 - EQ17 */
271 [352] = 0x1103, /* R352 - EQ18 */
272 [353] = 0x0564, /* R353 - EQ19 */
273 [354] = 0x0559, /* R354 - EQ20 */
274 [355] = 0x4000, /* R355 - EQ21 */
275 [356] = 0x6318, /* R356 - EQ22 */
276 [357] = 0x6300, /* R357 - EQ23 */
277 [358] = 0x0FCA, /* R358 - EQ24 */
278 [359] = 0x0400, /* R359 - EQ25 */
279 [360] = 0x00D8, /* R360 - EQ26 */
280 [361] = 0x1EB5, /* R361 - EQ27 */
281 [362] = 0xF145, /* R362 - EQ28 */
282 [363] = 0x0B75, /* R363 - EQ29 */
283 [364] = 0x01C5, /* R364 - EQ30 */
284 [365] = 0x1C58, /* R365 - EQ31 */
285 [366] = 0xF373, /* R366 - EQ32 */
286 [367] = 0x0A54, /* R367 - EQ33 */
287 [368] = 0x0558, /* R368 - EQ34 */
288 [369] = 0x168E, /* R369 - EQ35 */
289 [370] = 0xF829, /* R370 - EQ36 */
290 [371] = 0x07AD, /* R371 - EQ37 */
291 [372] = 0x1103, /* R372 - EQ38 */
292 [373] = 0x0564, /* R373 - EQ39 */
293 [374] = 0x0559, /* R374 - EQ40 */
294 [375] = 0x4000, /* R375 - EQ41 */
295
296 [513] = 0x0000, /* R513 - GPIO 2 */
297 [514] = 0x0000, /* R514 - GPIO 3 */
298
299 [516] = 0x8100, /* R516 - GPIO 5 */
300 [517] = 0x8100, /* R517 - GPIO 6 */
301
302 [560] = 0x0000, /* R560 - Interrupt Status 1 */
303 [561] = 0x0000, /* R561 - Interrupt Status 2 */
304
305 [568] = 0x0030, /* R568 - Interrupt Status 1 Mask */
306 [569] = 0xFFED, /* R569 - Interrupt Status 2 Mask */
307
308 [576] = 0x0000, /* R576 - Interrupt Control */
309
310 [584] = 0x002D, /* R584 - IRQ Debounce */
311
312 [586] = 0x0000, /* R586 - MICINT Source Pol */
313
314 [768] = 0x1C00, /* R768 - DSP2 Power Management */
315
316 [1037] = 0x0000, /* R1037 - DSP2_ExecControl */
317
318 [8192] = 0x0000, /* R8192 - DSP2 Instruction RAM 0 */
319
320 [9216] = 0x0030, /* R9216 - DSP2 Address RAM 2 */
321 [9217] = 0x0000, /* R9217 - DSP2 Address RAM 1 */
322 [9218] = 0x0000, /* R9218 - DSP2 Address RAM 0 */
323
324 [12288] = 0x0000, /* R12288 - DSP2 Data1 RAM 1 */
325 [12289] = 0x0000, /* R12289 - DSP2 Data1 RAM 0 */
326
327 [13312] = 0x0000, /* R13312 - DSP2 Data2 RAM 1 */
328 [13313] = 0x0000, /* R13313 - DSP2 Data2 RAM 0 */
329
330 [14336] = 0x0000, /* R14336 - DSP2 Data3 RAM 1 */
331 [14337] = 0x0000, /* R14337 - DSP2 Data3 RAM 0 */
332
333 [15360] = 0x000A, /* R15360 - DSP2 Coeff RAM 0 */
334
335 [16384] = 0x0000, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
336 [16385] = 0x0000, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
337 [16386] = 0x0000, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
338 [16387] = 0x0000, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
339 [16388] = 0x0000, /* R16388 - SOUNDSTAGE_ENABLES_1 */
340 [16389] = 0x0000, /* R16389 - SOUNDSTAGE_ENABLES_0 */
341
342 [16896] = 0x0002, /* R16896 - HDBASS_AI_1 */
343 [16897] = 0xBD12, /* R16897 - HDBASS_AI_0 */
344 [16898] = 0x007C, /* R16898 - HDBASS_AR_1 */
345 [16899] = 0x586C, /* R16899 - HDBASS_AR_0 */
346 [16900] = 0x0053, /* R16900 - HDBASS_B_1 */
347 [16901] = 0x8121, /* R16901 - HDBASS_B_0 */
348 [16902] = 0x003F, /* R16902 - HDBASS_K_1 */
349 [16903] = 0x8BD8, /* R16903 - HDBASS_K_0 */
350 [16904] = 0x0032, /* R16904 - HDBASS_N1_1 */
351 [16905] = 0xF52D, /* R16905 - HDBASS_N1_0 */
352 [16906] = 0x0065, /* R16906 - HDBASS_N2_1 */
353 [16907] = 0xAC8C, /* R16907 - HDBASS_N2_0 */
354 [16908] = 0x006B, /* R16908 - HDBASS_N3_1 */
355 [16909] = 0xE087, /* R16909 - HDBASS_N3_0 */
356 [16910] = 0x0072, /* R16910 - HDBASS_N4_1 */
357 [16911] = 0x1483, /* R16911 - HDBASS_N4_0 */
358 [16912] = 0x0072, /* R16912 - HDBASS_N5_1 */
359 [16913] = 0x1483, /* R16913 - HDBASS_N5_0 */
360 [16914] = 0x0043, /* R16914 - HDBASS_X1_1 */
361 [16915] = 0x3525, /* R16915 - HDBASS_X1_0 */
362 [16916] = 0x0006, /* R16916 - HDBASS_X2_1 */
363 [16917] = 0x6A4A, /* R16917 - HDBASS_X2_0 */
364 [16918] = 0x0043, /* R16918 - HDBASS_X3_1 */
365 [16919] = 0x6079, /* R16919 - HDBASS_X3_0 */
366 [16920] = 0x0008, /* R16920 - HDBASS_ATK_1 */
367 [16921] = 0x0000, /* R16921 - HDBASS_ATK_0 */
368 [16922] = 0x0001, /* R16922 - HDBASS_DCY_1 */
369 [16923] = 0x0000, /* R16923 - HDBASS_DCY_0 */
370 [16924] = 0x0059, /* R16924 - HDBASS_PG_1 */
371 [16925] = 0x999A, /* R16925 - HDBASS_PG_0 */
372
373 [17048] = 0x0083, /* R17408 - HPF_C_1 */
374 [17049] = 0x98AD, /* R17409 - HPF_C_0 */
375
376 [17920] = 0x007F, /* R17920 - ADCL_RETUNE_C1_1 */
377 [17921] = 0xFFFF, /* R17921 - ADCL_RETUNE_C1_0 */
378 [17922] = 0x0000, /* R17922 - ADCL_RETUNE_C2_1 */
379 [17923] = 0x0000, /* R17923 - ADCL_RETUNE_C2_0 */
380 [17924] = 0x0000, /* R17924 - ADCL_RETUNE_C3_1 */
381 [17925] = 0x0000, /* R17925 - ADCL_RETUNE_C3_0 */
382 [17926] = 0x0000, /* R17926 - ADCL_RETUNE_C4_1 */
383 [17927] = 0x0000, /* R17927 - ADCL_RETUNE_C4_0 */
384 [17928] = 0x0000, /* R17928 - ADCL_RETUNE_C5_1 */
385 [17929] = 0x0000, /* R17929 - ADCL_RETUNE_C5_0 */
386 [17930] = 0x0000, /* R17930 - ADCL_RETUNE_C6_1 */
387 [17931] = 0x0000, /* R17931 - ADCL_RETUNE_C6_0 */
388 [17932] = 0x0000, /* R17932 - ADCL_RETUNE_C7_1 */
389 [17933] = 0x0000, /* R17933 - ADCL_RETUNE_C7_0 */
390 [17934] = 0x0000, /* R17934 - ADCL_RETUNE_C8_1 */
391 [17935] = 0x0000, /* R17935 - ADCL_RETUNE_C8_0 */
392 [17936] = 0x0000, /* R17936 - ADCL_RETUNE_C9_1 */
393 [17937] = 0x0000, /* R17937 - ADCL_RETUNE_C9_0 */
394 [17938] = 0x0000, /* R17938 - ADCL_RETUNE_C10_1 */
395 [17939] = 0x0000, /* R17939 - ADCL_RETUNE_C10_0 */
396 [17940] = 0x0000, /* R17940 - ADCL_RETUNE_C11_1 */
397 [17941] = 0x0000, /* R17941 - ADCL_RETUNE_C11_0 */
398 [17942] = 0x0000, /* R17942 - ADCL_RETUNE_C12_1 */
399 [17943] = 0x0000, /* R17943 - ADCL_RETUNE_C12_0 */
400 [17944] = 0x0000, /* R17944 - ADCL_RETUNE_C13_1 */
401 [17945] = 0x0000, /* R17945 - ADCL_RETUNE_C13_0 */
402 [17946] = 0x0000, /* R17946 - ADCL_RETUNE_C14_1 */
403 [17947] = 0x0000, /* R17947 - ADCL_RETUNE_C14_0 */
404 [17948] = 0x0000, /* R17948 - ADCL_RETUNE_C15_1 */
405 [17949] = 0x0000, /* R17949 - ADCL_RETUNE_C15_0 */
406 [17950] = 0x0000, /* R17950 - ADCL_RETUNE_C16_1 */
407 [17951] = 0x0000, /* R17951 - ADCL_RETUNE_C16_0 */
408 [17952] = 0x0000, /* R17952 - ADCL_RETUNE_C17_1 */
409 [17953] = 0x0000, /* R17953 - ADCL_RETUNE_C17_0 */
410 [17954] = 0x0000, /* R17954 - ADCL_RETUNE_C18_1 */
411 [17955] = 0x0000, /* R17955 - ADCL_RETUNE_C18_0 */
412 [17956] = 0x0000, /* R17956 - ADCL_RETUNE_C19_1 */
413 [17957] = 0x0000, /* R17957 - ADCL_RETUNE_C19_0 */
414 [17958] = 0x0000, /* R17958 - ADCL_RETUNE_C20_1 */
415 [17959] = 0x0000, /* R17959 - ADCL_RETUNE_C20_0 */
416 [17960] = 0x0000, /* R17960 - ADCL_RETUNE_C21_1 */
417 [17961] = 0x0000, /* R17961 - ADCL_RETUNE_C21_0 */
418 [17962] = 0x0000, /* R17962 - ADCL_RETUNE_C22_1 */
419 [17963] = 0x0000, /* R17963 - ADCL_RETUNE_C22_0 */
420 [17964] = 0x0000, /* R17964 - ADCL_RETUNE_C23_1 */
421 [17965] = 0x0000, /* R17965 - ADCL_RETUNE_C23_0 */
422 [17966] = 0x0000, /* R17966 - ADCL_RETUNE_C24_1 */
423 [17967] = 0x0000, /* R17967 - ADCL_RETUNE_C24_0 */
424 [17968] = 0x0000, /* R17968 - ADCL_RETUNE_C25_1 */
425 [17969] = 0x0000, /* R17969 - ADCL_RETUNE_C25_0 */
426 [17970] = 0x0000, /* R17970 - ADCL_RETUNE_C26_1 */
427 [17971] = 0x0000, /* R17971 - ADCL_RETUNE_C26_0 */
428 [17972] = 0x0000, /* R17972 - ADCL_RETUNE_C27_1 */
429 [17973] = 0x0000, /* R17973 - ADCL_RETUNE_C27_0 */
430 [17974] = 0x0000, /* R17974 - ADCL_RETUNE_C28_1 */
431 [17975] = 0x0000, /* R17975 - ADCL_RETUNE_C28_0 */
432 [17976] = 0x0000, /* R17976 - ADCL_RETUNE_C29_1 */
433 [17977] = 0x0000, /* R17977 - ADCL_RETUNE_C29_0 */
434 [17978] = 0x0000, /* R17978 - ADCL_RETUNE_C30_1 */
435 [17979] = 0x0000, /* R17979 - ADCL_RETUNE_C30_0 */
436 [17980] = 0x0000, /* R17980 - ADCL_RETUNE_C31_1 */
437 [17981] = 0x0000, /* R17981 - ADCL_RETUNE_C31_0 */
438 [17982] = 0x0000, /* R17982 - ADCL_RETUNE_C32_1 */
439 [17983] = 0x0000, /* R17983 - ADCL_RETUNE_C32_0 */
440
441 [18432] = 0x0020, /* R18432 - RETUNEADC_PG2_1 */
442 [18433] = 0x0000, /* R18433 - RETUNEADC_PG2_0 */
443 [18434] = 0x0040, /* R18434 - RETUNEADC_PG_1 */
444 [18435] = 0x0000, /* R18435 - RETUNEADC_PG_0 */
445
446 [18944] = 0x007F, /* R18944 - ADCR_RETUNE_C1_1 */
447 [18945] = 0xFFFF, /* R18945 - ADCR_RETUNE_C1_0 */
448 [18946] = 0x0000, /* R18946 - ADCR_RETUNE_C2_1 */
449 [18947] = 0x0000, /* R18947 - ADCR_RETUNE_C2_0 */
450 [18948] = 0x0000, /* R18948 - ADCR_RETUNE_C3_1 */
451 [18949] = 0x0000, /* R18949 - ADCR_RETUNE_C3_0 */
452 [18950] = 0x0000, /* R18950 - ADCR_RETUNE_C4_1 */
453 [18951] = 0x0000, /* R18951 - ADCR_RETUNE_C4_0 */
454 [18952] = 0x0000, /* R18952 - ADCR_RETUNE_C5_1 */
455 [18953] = 0x0000, /* R18953 - ADCR_RETUNE_C5_0 */
456 [18954] = 0x0000, /* R18954 - ADCR_RETUNE_C6_1 */
457 [18955] = 0x0000, /* R18955 - ADCR_RETUNE_C6_0 */
458 [18956] = 0x0000, /* R18956 - ADCR_RETUNE_C7_1 */
459 [18957] = 0x0000, /* R18957 - ADCR_RETUNE_C7_0 */
460 [18958] = 0x0000, /* R18958 - ADCR_RETUNE_C8_1 */
461 [18959] = 0x0000, /* R18959 - ADCR_RETUNE_C8_0 */
462 [18960] = 0x0000, /* R18960 - ADCR_RETUNE_C9_1 */
463 [18961] = 0x0000, /* R18961 - ADCR_RETUNE_C9_0 */
464 [18962] = 0x0000, /* R18962 - ADCR_RETUNE_C10_1 */
465 [18963] = 0x0000, /* R18963 - ADCR_RETUNE_C10_0 */
466 [18964] = 0x0000, /* R18964 - ADCR_RETUNE_C11_1 */
467 [18965] = 0x0000, /* R18965 - ADCR_RETUNE_C11_0 */
468 [18966] = 0x0000, /* R18966 - ADCR_RETUNE_C12_1 */
469 [18967] = 0x0000, /* R18967 - ADCR_RETUNE_C12_0 */
470 [18968] = 0x0000, /* R18968 - ADCR_RETUNE_C13_1 */
471 [18969] = 0x0000, /* R18969 - ADCR_RETUNE_C13_0 */
472 [18970] = 0x0000, /* R18970 - ADCR_RETUNE_C14_1 */
473 [18971] = 0x0000, /* R18971 - ADCR_RETUNE_C14_0 */
474 [18972] = 0x0000, /* R18972 - ADCR_RETUNE_C15_1 */
475 [18973] = 0x0000, /* R18973 - ADCR_RETUNE_C15_0 */
476 [18974] = 0x0000, /* R18974 - ADCR_RETUNE_C16_1 */
477 [18975] = 0x0000, /* R18975 - ADCR_RETUNE_C16_0 */
478 [18976] = 0x0000, /* R18976 - ADCR_RETUNE_C17_1 */
479 [18977] = 0x0000, /* R18977 - ADCR_RETUNE_C17_0 */
480 [18978] = 0x0000, /* R18978 - ADCR_RETUNE_C18_1 */
481 [18979] = 0x0000, /* R18979 - ADCR_RETUNE_C18_0 */
482 [18980] = 0x0000, /* R18980 - ADCR_RETUNE_C19_1 */
483 [18981] = 0x0000, /* R18981 - ADCR_RETUNE_C19_0 */
484 [18982] = 0x0000, /* R18982 - ADCR_RETUNE_C20_1 */
485 [18983] = 0x0000, /* R18983 - ADCR_RETUNE_C20_0 */
486 [18984] = 0x0000, /* R18984 - ADCR_RETUNE_C21_1 */
487 [18985] = 0x0000, /* R18985 - ADCR_RETUNE_C21_0 */
488 [18986] = 0x0000, /* R18986 - ADCR_RETUNE_C22_1 */
489 [18987] = 0x0000, /* R18987 - ADCR_RETUNE_C22_0 */
490 [18988] = 0x0000, /* R18988 - ADCR_RETUNE_C23_1 */
491 [18989] = 0x0000, /* R18989 - ADCR_RETUNE_C23_0 */
492 [18990] = 0x0000, /* R18990 - ADCR_RETUNE_C24_1 */
493 [18991] = 0x0000, /* R18991 - ADCR_RETUNE_C24_0 */
494 [18992] = 0x0000, /* R18992 - ADCR_RETUNE_C25_1 */
495 [18993] = 0x0000, /* R18993 - ADCR_RETUNE_C25_0 */
496 [18994] = 0x0000, /* R18994 - ADCR_RETUNE_C26_1 */
497 [18995] = 0x0000, /* R18995 - ADCR_RETUNE_C26_0 */
498 [18996] = 0x0000, /* R18996 - ADCR_RETUNE_C27_1 */
499 [18997] = 0x0000, /* R18997 - ADCR_RETUNE_C27_0 */
500 [18998] = 0x0000, /* R18998 - ADCR_RETUNE_C28_1 */
501 [18999] = 0x0000, /* R18999 - ADCR_RETUNE_C28_0 */
502 [19000] = 0x0000, /* R19000 - ADCR_RETUNE_C29_1 */
503 [19001] = 0x0000, /* R19001 - ADCR_RETUNE_C29_0 */
504 [19002] = 0x0000, /* R19002 - ADCR_RETUNE_C30_1 */
505 [19003] = 0x0000, /* R19003 - ADCR_RETUNE_C30_0 */
506 [19004] = 0x0000, /* R19004 - ADCR_RETUNE_C31_1 */
507 [19005] = 0x0000, /* R19005 - ADCR_RETUNE_C31_0 */
508 [19006] = 0x0000, /* R19006 - ADCR_RETUNE_C32_1 */
509 [19007] = 0x0000, /* R19007 - ADCR_RETUNE_C32_0 */
510
511 [19456] = 0x007F, /* R19456 - DACL_RETUNE_C1_1 */
512 [19457] = 0xFFFF, /* R19457 - DACL_RETUNE_C1_0 */
513 [19458] = 0x0000, /* R19458 - DACL_RETUNE_C2_1 */
514 [19459] = 0x0000, /* R19459 - DACL_RETUNE_C2_0 */
515 [19460] = 0x0000, /* R19460 - DACL_RETUNE_C3_1 */
516 [19461] = 0x0000, /* R19461 - DACL_RETUNE_C3_0 */
517 [19462] = 0x0000, /* R19462 - DACL_RETUNE_C4_1 */
518 [19463] = 0x0000, /* R19463 - DACL_RETUNE_C4_0 */
519 [19464] = 0x0000, /* R19464 - DACL_RETUNE_C5_1 */
520 [19465] = 0x0000, /* R19465 - DACL_RETUNE_C5_0 */
521 [19466] = 0x0000, /* R19466 - DACL_RETUNE_C6_1 */
522 [19467] = 0x0000, /* R19467 - DACL_RETUNE_C6_0 */
523 [19468] = 0x0000, /* R19468 - DACL_RETUNE_C7_1 */
524 [19469] = 0x0000, /* R19469 - DACL_RETUNE_C7_0 */
525 [19470] = 0x0000, /* R19470 - DACL_RETUNE_C8_1 */
526 [19471] = 0x0000, /* R19471 - DACL_RETUNE_C8_0 */
527 [19472] = 0x0000, /* R19472 - DACL_RETUNE_C9_1 */
528 [19473] = 0x0000, /* R19473 - DACL_RETUNE_C9_0 */
529 [19474] = 0x0000, /* R19474 - DACL_RETUNE_C10_1 */
530 [19475] = 0x0000, /* R19475 - DACL_RETUNE_C10_0 */
531 [19476] = 0x0000, /* R19476 - DACL_RETUNE_C11_1 */
532 [19477] = 0x0000, /* R19477 - DACL_RETUNE_C11_0 */
533 [19478] = 0x0000, /* R19478 - DACL_RETUNE_C12_1 */
534 [19479] = 0x0000, /* R19479 - DACL_RETUNE_C12_0 */
535 [19480] = 0x0000, /* R19480 - DACL_RETUNE_C13_1 */
536 [19481] = 0x0000, /* R19481 - DACL_RETUNE_C13_0 */
537 [19482] = 0x0000, /* R19482 - DACL_RETUNE_C14_1 */
538 [19483] = 0x0000, /* R19483 - DACL_RETUNE_C14_0 */
539 [19484] = 0x0000, /* R19484 - DACL_RETUNE_C15_1 */
540 [19485] = 0x0000, /* R19485 - DACL_RETUNE_C15_0 */
541 [19486] = 0x0000, /* R19486 - DACL_RETUNE_C16_1 */
542 [19487] = 0x0000, /* R19487 - DACL_RETUNE_C16_0 */
543 [19488] = 0x0000, /* R19488 - DACL_RETUNE_C17_1 */
544 [19489] = 0x0000, /* R19489 - DACL_RETUNE_C17_0 */
545 [19490] = 0x0000, /* R19490 - DACL_RETUNE_C18_1 */
546 [19491] = 0x0000, /* R19491 - DACL_RETUNE_C18_0 */
547 [19492] = 0x0000, /* R19492 - DACL_RETUNE_C19_1 */
548 [19493] = 0x0000, /* R19493 - DACL_RETUNE_C19_0 */
549 [19494] = 0x0000, /* R19494 - DACL_RETUNE_C20_1 */
550 [19495] = 0x0000, /* R19495 - DACL_RETUNE_C20_0 */
551 [19496] = 0x0000, /* R19496 - DACL_RETUNE_C21_1 */
552 [19497] = 0x0000, /* R19497 - DACL_RETUNE_C21_0 */
553 [19498] = 0x0000, /* R19498 - DACL_RETUNE_C22_1 */
554 [19499] = 0x0000, /* R19499 - DACL_RETUNE_C22_0 */
555 [19500] = 0x0000, /* R19500 - DACL_RETUNE_C23_1 */
556 [19501] = 0x0000, /* R19501 - DACL_RETUNE_C23_0 */
557 [19502] = 0x0000, /* R19502 - DACL_RETUNE_C24_1 */
558 [19503] = 0x0000, /* R19503 - DACL_RETUNE_C24_0 */
559 [19504] = 0x0000, /* R19504 - DACL_RETUNE_C25_1 */
560 [19505] = 0x0000, /* R19505 - DACL_RETUNE_C25_0 */
561 [19506] = 0x0000, /* R19506 - DACL_RETUNE_C26_1 */
562 [19507] = 0x0000, /* R19507 - DACL_RETUNE_C26_0 */
563 [19508] = 0x0000, /* R19508 - DACL_RETUNE_C27_1 */
564 [19509] = 0x0000, /* R19509 - DACL_RETUNE_C27_0 */
565 [19510] = 0x0000, /* R19510 - DACL_RETUNE_C28_1 */
566 [19511] = 0x0000, /* R19511 - DACL_RETUNE_C28_0 */
567 [19512] = 0x0000, /* R19512 - DACL_RETUNE_C29_1 */
568 [19513] = 0x0000, /* R19513 - DACL_RETUNE_C29_0 */
569 [19514] = 0x0000, /* R19514 - DACL_RETUNE_C30_1 */
570 [19515] = 0x0000, /* R19515 - DACL_RETUNE_C30_0 */
571 [19516] = 0x0000, /* R19516 - DACL_RETUNE_C31_1 */
572 [19517] = 0x0000, /* R19517 - DACL_RETUNE_C31_0 */
573 [19518] = 0x0000, /* R19518 - DACL_RETUNE_C32_1 */
574 [19519] = 0x0000, /* R19519 - DACL_RETUNE_C32_0 */
575
576 [19968] = 0x0020, /* R19968 - RETUNEDAC_PG2_1 */
577 [19969] = 0x0000, /* R19969 - RETUNEDAC_PG2_0 */
578 [19970] = 0x0040, /* R19970 - RETUNEDAC_PG_1 */
579 [19971] = 0x0000, /* R19971 - RETUNEDAC_PG_0 */
580
581 [20480] = 0x007F, /* R20480 - DACR_RETUNE_C1_1 */
582 [20481] = 0xFFFF, /* R20481 - DACR_RETUNE_C1_0 */
583 [20482] = 0x0000, /* R20482 - DACR_RETUNE_C2_1 */
584 [20483] = 0x0000, /* R20483 - DACR_RETUNE_C2_0 */
585 [20484] = 0x0000, /* R20484 - DACR_RETUNE_C3_1 */
586 [20485] = 0x0000, /* R20485 - DACR_RETUNE_C3_0 */
587 [20486] = 0x0000, /* R20486 - DACR_RETUNE_C4_1 */
588 [20487] = 0x0000, /* R20487 - DACR_RETUNE_C4_0 */
589 [20488] = 0x0000, /* R20488 - DACR_RETUNE_C5_1 */
590 [20489] = 0x0000, /* R20489 - DACR_RETUNE_C5_0 */
591 [20490] = 0x0000, /* R20490 - DACR_RETUNE_C6_1 */
592 [20491] = 0x0000, /* R20491 - DACR_RETUNE_C6_0 */
593 [20492] = 0x0000, /* R20492 - DACR_RETUNE_C7_1 */
594 [20493] = 0x0000, /* R20493 - DACR_RETUNE_C7_0 */
595 [20494] = 0x0000, /* R20494 - DACR_RETUNE_C8_1 */
596 [20495] = 0x0000, /* R20495 - DACR_RETUNE_C8_0 */
597 [20496] = 0x0000, /* R20496 - DACR_RETUNE_C9_1 */
598 [20497] = 0x0000, /* R20497 - DACR_RETUNE_C9_0 */
599 [20498] = 0x0000, /* R20498 - DACR_RETUNE_C10_1 */
600 [20499] = 0x0000, /* R20499 - DACR_RETUNE_C10_0 */
601 [20500] = 0x0000, /* R20500 - DACR_RETUNE_C11_1 */
602 [20501] = 0x0000, /* R20501 - DACR_RETUNE_C11_0 */
603 [20502] = 0x0000, /* R20502 - DACR_RETUNE_C12_1 */
604 [20503] = 0x0000, /* R20503 - DACR_RETUNE_C12_0 */
605 [20504] = 0x0000, /* R20504 - DACR_RETUNE_C13_1 */
606 [20505] = 0x0000, /* R20505 - DACR_RETUNE_C13_0 */
607 [20506] = 0x0000, /* R20506 - DACR_RETUNE_C14_1 */
608 [20507] = 0x0000, /* R20507 - DACR_RETUNE_C14_0 */
609 [20508] = 0x0000, /* R20508 - DACR_RETUNE_C15_1 */
610 [20509] = 0x0000, /* R20509 - DACR_RETUNE_C15_0 */
611 [20510] = 0x0000, /* R20510 - DACR_RETUNE_C16_1 */
612 [20511] = 0x0000, /* R20511 - DACR_RETUNE_C16_0 */
613 [20512] = 0x0000, /* R20512 - DACR_RETUNE_C17_1 */
614 [20513] = 0x0000, /* R20513 - DACR_RETUNE_C17_0 */
615 [20514] = 0x0000, /* R20514 - DACR_RETUNE_C18_1 */
616 [20515] = 0x0000, /* R20515 - DACR_RETUNE_C18_0 */
617 [20516] = 0x0000, /* R20516 - DACR_RETUNE_C19_1 */
618 [20517] = 0x0000, /* R20517 - DACR_RETUNE_C19_0 */
619 [20518] = 0x0000, /* R20518 - DACR_RETUNE_C20_1 */
620 [20519] = 0x0000, /* R20519 - DACR_RETUNE_C20_0 */
621 [20520] = 0x0000, /* R20520 - DACR_RETUNE_C21_1 */
622 [20521] = 0x0000, /* R20521 - DACR_RETUNE_C21_0 */
623 [20522] = 0x0000, /* R20522 - DACR_RETUNE_C22_1 */
624 [20523] = 0x0000, /* R20523 - DACR_RETUNE_C22_0 */
625 [20524] = 0x0000, /* R20524 - DACR_RETUNE_C23_1 */
626 [20525] = 0x0000, /* R20525 - DACR_RETUNE_C23_0 */
627 [20526] = 0x0000, /* R20526 - DACR_RETUNE_C24_1 */
628 [20527] = 0x0000, /* R20527 - DACR_RETUNE_C24_0 */
629 [20528] = 0x0000, /* R20528 - DACR_RETUNE_C25_1 */
630 [20529] = 0x0000, /* R20529 - DACR_RETUNE_C25_0 */
631 [20530] = 0x0000, /* R20530 - DACR_RETUNE_C26_1 */
632 [20531] = 0x0000, /* R20531 - DACR_RETUNE_C26_0 */
633 [20532] = 0x0000, /* R20532 - DACR_RETUNE_C27_1 */
634 [20533] = 0x0000, /* R20533 - DACR_RETUNE_C27_0 */
635 [20534] = 0x0000, /* R20534 - DACR_RETUNE_C28_1 */
636 [20535] = 0x0000, /* R20535 - DACR_RETUNE_C28_0 */
637 [20536] = 0x0000, /* R20536 - DACR_RETUNE_C29_1 */
638 [20537] = 0x0000, /* R20537 - DACR_RETUNE_C29_0 */
639 [20538] = 0x0000, /* R20538 - DACR_RETUNE_C30_1 */
640 [20539] = 0x0000, /* R20539 - DACR_RETUNE_C30_0 */
641 [20540] = 0x0000, /* R20540 - DACR_RETUNE_C31_1 */
642 [20541] = 0x0000, /* R20541 - DACR_RETUNE_C31_0 */
643 [20542] = 0x0000, /* R20542 - DACR_RETUNE_C32_1 */
644 [20543] = 0x0000, /* R20543 - DACR_RETUNE_C32_0 */
645
646 [20992] = 0x008C, /* R20992 - VSS_XHD2_1 */
647 [20993] = 0x0200, /* R20993 - VSS_XHD2_0 */
648 [20994] = 0x0035, /* R20994 - VSS_XHD3_1 */
649 [20995] = 0x0700, /* R20995 - VSS_XHD3_0 */
650 [20996] = 0x003A, /* R20996 - VSS_XHN1_1 */
651 [20997] = 0x4100, /* R20997 - VSS_XHN1_0 */
652 [20998] = 0x008B, /* R20998 - VSS_XHN2_1 */
653 [20999] = 0x7D00, /* R20999 - VSS_XHN2_0 */
654 [21000] = 0x003A, /* R21000 - VSS_XHN3_1 */
655 [21001] = 0x4100, /* R21001 - VSS_XHN3_0 */
656 [21002] = 0x008C, /* R21002 - VSS_XLA_1 */
657 [21003] = 0xFEE8, /* R21003 - VSS_XLA_0 */
658 [21004] = 0x0078, /* R21004 - VSS_XLB_1 */
659 [21005] = 0x0000, /* R21005 - VSS_XLB_0 */
660 [21006] = 0x003F, /* R21006 - VSS_XLG_1 */
661 [21007] = 0xB260, /* R21007 - VSS_XLG_0 */
662 [21008] = 0x002D, /* R21008 - VSS_PG2_1 */
663 [21009] = 0x1818, /* R21009 - VSS_PG2_0 */
664 [21010] = 0x0020, /* R21010 - VSS_PG_1 */
665 [21011] = 0x0000, /* R21011 - VSS_PG_0 */
666 [21012] = 0x00F1, /* R21012 - VSS_XTD1_1 */
667 [21013] = 0x8340, /* R21013 - VSS_XTD1_0 */
668 [21014] = 0x00FB, /* R21014 - VSS_XTD2_1 */
669 [21015] = 0x8300, /* R21015 - VSS_XTD2_0 */
670 [21016] = 0x00EE, /* R21016 - VSS_XTD3_1 */
671 [21017] = 0xAEC0, /* R21017 - VSS_XTD3_0 */
672 [21018] = 0x00FB, /* R21018 - VSS_XTD4_1 */
673 [21019] = 0xAC40, /* R21019 - VSS_XTD4_0 */
674 [21020] = 0x00F1, /* R21020 - VSS_XTD5_1 */
675 [21021] = 0x7F80, /* R21021 - VSS_XTD5_0 */
676 [21022] = 0x00F4, /* R21022 - VSS_XTD6_1 */
677 [21023] = 0x3B40, /* R21023 - VSS_XTD6_0 */
678 [21024] = 0x00F5, /* R21024 - VSS_XTD7_1 */
679 [21025] = 0xFB00, /* R21025 - VSS_XTD7_0 */
680 [21026] = 0x00EA, /* R21026 - VSS_XTD8_1 */
681 [21027] = 0x10C0, /* R21027 - VSS_XTD8_0 */
682 [21028] = 0x00FC, /* R21028 - VSS_XTD9_1 */
683 [21029] = 0xC580, /* R21029 - VSS_XTD9_0 */
684 [21030] = 0x00E2, /* R21030 - VSS_XTD10_1 */
685 [21031] = 0x75C0, /* R21031 - VSS_XTD10_0 */
686 [21032] = 0x0004, /* R21032 - VSS_XTD11_1 */
687 [21033] = 0xB480, /* R21033 - VSS_XTD11_0 */
688 [21034] = 0x00D4, /* R21034 - VSS_XTD12_1 */
689 [21035] = 0xF980, /* R21035 - VSS_XTD12_0 */
690 [21036] = 0x0004, /* R21036 - VSS_XTD13_1 */
691 [21037] = 0x9140, /* R21037 - VSS_XTD13_0 */
692 [21038] = 0x00D8, /* R21038 - VSS_XTD14_1 */
693 [21039] = 0xA480, /* R21039 - VSS_XTD14_0 */
694 [21040] = 0x0002, /* R21040 - VSS_XTD15_1 */
695 [21041] = 0x3DC0, /* R21041 - VSS_XTD15_0 */
696 [21042] = 0x00CF, /* R21042 - VSS_XTD16_1 */
697 [21043] = 0x7A80, /* R21043 - VSS_XTD16_0 */
698 [21044] = 0x00DC, /* R21044 - VSS_XTD17_1 */
699 [21045] = 0x0600, /* R21045 - VSS_XTD17_0 */
700 [21046] = 0x00F2, /* R21046 - VSS_XTD18_1 */
701 [21047] = 0xDAC0, /* R21047 - VSS_XTD18_0 */
702 [21048] = 0x00BA, /* R21048 - VSS_XTD19_1 */
703 [21049] = 0xF340, /* R21049 - VSS_XTD19_0 */
704 [21050] = 0x000A, /* R21050 - VSS_XTD20_1 */
705 [21051] = 0x7940, /* R21051 - VSS_XTD20_0 */
706 [21052] = 0x001C, /* R21052 - VSS_XTD21_1 */
707 [21053] = 0x0680, /* R21053 - VSS_XTD21_0 */
708 [21054] = 0x00FD, /* R21054 - VSS_XTD22_1 */
709 [21055] = 0x2D00, /* R21055 - VSS_XTD22_0 */
710 [21056] = 0x001C, /* R21056 - VSS_XTD23_1 */
711 [21057] = 0xE840, /* R21057 - VSS_XTD23_0 */
712 [21058] = 0x000D, /* R21058 - VSS_XTD24_1 */
713 [21059] = 0xDC40, /* R21059 - VSS_XTD24_0 */
714 [21060] = 0x00FC, /* R21060 - VSS_XTD25_1 */
715 [21061] = 0x9D00, /* R21061 - VSS_XTD25_0 */
716 [21062] = 0x0009, /* R21062 - VSS_XTD26_1 */
717 [21063] = 0x5580, /* R21063 - VSS_XTD26_0 */
718 [21064] = 0x00FE, /* R21064 - VSS_XTD27_1 */
719 [21065] = 0x7E80, /* R21065 - VSS_XTD27_0 */
720 [21066] = 0x000E, /* R21066 - VSS_XTD28_1 */
721 [21067] = 0xAB40, /* R21067 - VSS_XTD28_0 */
722 [21068] = 0x00F9, /* R21068 - VSS_XTD29_1 */
723 [21069] = 0x9880, /* R21069 - VSS_XTD29_0 */
724 [21070] = 0x0009, /* R21070 - VSS_XTD30_1 */
725 [21071] = 0x87C0, /* R21071 - VSS_XTD30_0 */
726 [21072] = 0x00FD, /* R21072 - VSS_XTD31_1 */
727 [21073] = 0x2C40, /* R21073 - VSS_XTD31_0 */
728 [21074] = 0x0009, /* R21074 - VSS_XTD32_1 */
729 [21075] = 0x4800, /* R21075 - VSS_XTD32_0 */
730 [21076] = 0x0003, /* R21076 - VSS_XTS1_1 */
731 [21077] = 0x5F40, /* R21077 - VSS_XTS1_0 */
732 [21078] = 0x0000, /* R21078 - VSS_XTS2_1 */
733 [21079] = 0x8700, /* R21079 - VSS_XTS2_0 */
734 [21080] = 0x00FA, /* R21080 - VSS_XTS3_1 */
735 [21081] = 0xE4C0, /* R21081 - VSS_XTS3_0 */
736 [21082] = 0x0000, /* R21082 - VSS_XTS4_1 */
737 [21083] = 0x0B40, /* R21083 - VSS_XTS4_0 */
738 [21084] = 0x0004, /* R21084 - VSS_XTS5_1 */
739 [21085] = 0xE180, /* R21085 - VSS_XTS5_0 */
740 [21086] = 0x0001, /* R21086 - VSS_XTS6_1 */
741 [21087] = 0x1F40, /* R21087 - VSS_XTS6_0 */
742 [21088] = 0x00F8, /* R21088 - VSS_XTS7_1 */
743 [21089] = 0xB000, /* R21089 - VSS_XTS7_0 */
744 [21090] = 0x00FB, /* R21090 - VSS_XTS8_1 */
745 [21091] = 0xCBC0, /* R21091 - VSS_XTS8_0 */
746 [21092] = 0x0004, /* R21092 - VSS_XTS9_1 */
747 [21093] = 0xF380, /* R21093 - VSS_XTS9_0 */
748 [21094] = 0x0007, /* R21094 - VSS_XTS10_1 */
749 [21095] = 0xDF40, /* R21095 - VSS_XTS10_0 */
750 [21096] = 0x00FF, /* R21096 - VSS_XTS11_1 */
751 [21097] = 0x0700, /* R21097 - VSS_XTS11_0 */
752 [21098] = 0x00EF, /* R21098 - VSS_XTS12_1 */
753 [21099] = 0xD700, /* R21099 - VSS_XTS12_0 */
754 [21100] = 0x00FB, /* R21100 - VSS_XTS13_1 */
755 [21101] = 0xAF40, /* R21101 - VSS_XTS13_0 */
756 [21102] = 0x0010, /* R21102 - VSS_XTS14_1 */
757 [21103] = 0x8A80, /* R21103 - VSS_XTS14_0 */
758 [21104] = 0x0011, /* R21104 - VSS_XTS15_1 */
759 [21105] = 0x07C0, /* R21105 - VSS_XTS15_0 */
760 [21106] = 0x00E0, /* R21106 - VSS_XTS16_1 */
761 [21107] = 0x0800, /* R21107 - VSS_XTS16_0 */
762 [21108] = 0x00D2, /* R21108 - VSS_XTS17_1 */
763 [21109] = 0x7600, /* R21109 - VSS_XTS17_0 */
764 [21110] = 0x0020, /* R21110 - VSS_XTS18_1 */
765 [21111] = 0xCF40, /* R21111 - VSS_XTS18_0 */
766 [21112] = 0x0030, /* R21112 - VSS_XTS19_1 */
767 [21113] = 0x2340, /* R21113 - VSS_XTS19_0 */
768 [21114] = 0x00FD, /* R21114 - VSS_XTS20_1 */
769 [21115] = 0x69C0, /* R21115 - VSS_XTS20_0 */
770 [21116] = 0x0028, /* R21116 - VSS_XTS21_1 */
771 [21117] = 0x3500, /* R21117 - VSS_XTS21_0 */
772 [21118] = 0x0006, /* R21118 - VSS_XTS22_1 */
773 [21119] = 0x3300, /* R21119 - VSS_XTS22_0 */
774 [21120] = 0x00D9, /* R21120 - VSS_XTS23_1 */
775 [21121] = 0xF6C0, /* R21121 - VSS_XTS23_0 */
776 [21122] = 0x00F3, /* R21122 - VSS_XTS24_1 */
777 [21123] = 0x3340, /* R21123 - VSS_XTS24_0 */
778 [21124] = 0x000F, /* R21124 - VSS_XTS25_1 */
779 [21125] = 0x4200, /* R21125 - VSS_XTS25_0 */
780 [21126] = 0x0004, /* R21126 - VSS_XTS26_1 */
781 [21127] = 0x0C80, /* R21127 - VSS_XTS26_0 */
782 [21128] = 0x00FB, /* R21128 - VSS_XTS27_1 */
783 [21129] = 0x3F80, /* R21129 - VSS_XTS27_0 */
784 [21130] = 0x00F7, /* R21130 - VSS_XTS28_1 */
785 [21131] = 0x57C0, /* R21131 - VSS_XTS28_0 */
786 [21132] = 0x0003, /* R21132 - VSS_XTS29_1 */
787 [21133] = 0x5400, /* R21133 - VSS_XTS29_0 */
788 [21134] = 0x0000, /* R21134 - VSS_XTS30_1 */
789 [21135] = 0xC6C0, /* R21135 - VSS_XTS30_0 */
790 [21136] = 0x0003, /* R21136 - VSS_XTS31_1 */
791 [21137] = 0x12C0, /* R21137 - VSS_XTS31_0 */
792 [21138] = 0x00FD, /* R21138 - VSS_XTS32_1 */
793 [21139] = 0x8580, /* R21139 - VSS_XTS32_0 */
794};
795
796static const struct wm8962_reg_access {
797 u16 read;
798 u16 write;
799 u16 vol;
800} wm8962_reg_access[WM8962_MAX_REGISTER + 1] = {
801 [0] = { 0x00FF, 0x01FF, 0x0000 }, /* R0 - Left Input volume */
802 [1] = { 0xFEFF, 0x01FF, 0xFFFF }, /* R1 - Right Input volume */
803 [2] = { 0x00FF, 0x01FF, 0x0000 }, /* R2 - HPOUTL volume */
804 [3] = { 0x00FF, 0x01FF, 0x0000 }, /* R3 - HPOUTR volume */
805 [4] = { 0x07FE, 0x07FE, 0xFFFF }, /* R4 - Clocking1 */
806 [5] = { 0x007F, 0x007F, 0x0000 }, /* R5 - ADC & DAC Control 1 */
807 [6] = { 0x37ED, 0x37ED, 0x0000 }, /* R6 - ADC & DAC Control 2 */
808 [7] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R7 - Audio Interface 0 */
809 [8] = { 0x0FEF, 0x0FEF, 0xFFFF }, /* R8 - Clocking2 */
810 [9] = { 0x0B9F, 0x039F, 0x0000 }, /* R9 - Audio Interface 1 */
811 [10] = { 0x00FF, 0x01FF, 0x0000 }, /* R10 - Left DAC volume */
812 [11] = { 0x00FF, 0x01FF, 0x0000 }, /* R11 - Right DAC volume */
813 [14] = { 0x07FF, 0x07FF, 0x0000 }, /* R14 - Audio Interface 2 */
814 [15] = { 0xFFFF, 0xFFFF, 0xFFFF }, /* R15 - Software Reset */
815 [17] = { 0x07FF, 0x07FF, 0x0000 }, /* R17 - ALC1 */
816 [18] = { 0xF8FF, 0x00FF, 0xFFFF }, /* R18 - ALC2 */
817 [19] = { 0x1DFF, 0x1DFF, 0x0000 }, /* R19 - ALC3 */
818 [20] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20 - Noise Gate */
819 [21] = { 0x00FF, 0x01FF, 0x0000 }, /* R21 - Left ADC volume */
820 [22] = { 0x00FF, 0x01FF, 0x0000 }, /* R22 - Right ADC volume */
821 [23] = { 0x0161, 0x0161, 0x0000 }, /* R23 - Additional control(1) */
822 [24] = { 0x0008, 0x0008, 0x0000 }, /* R24 - Additional control(2) */
823 [25] = { 0x07FE, 0x07FE, 0x0000 }, /* R25 - Pwr Mgmt (1) */
824 [26] = { 0x01FB, 0x01FB, 0x0000 }, /* R26 - Pwr Mgmt (2) */
825 [27] = { 0x0017, 0x0017, 0x0000 }, /* R27 - Additional Control (3) */
826 [28] = { 0x001C, 0x001C, 0x0000 }, /* R28 - Anti-pop */
827
828 [30] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R30 - Clocking 3 */
829 [31] = { 0x000F, 0x000F, 0x0000 }, /* R31 - Input mixer control (1) */
830 [32] = { 0x01FF, 0x01FF, 0x0000 }, /* R32 - Left input mixer volume */
831 [33] = { 0x01FF, 0x01FF, 0x0000 }, /* R33 - Right input mixer volume */
832 [34] = { 0x003F, 0x003F, 0x0000 }, /* R34 - Input mixer control (2) */
833 [35] = { 0x003F, 0x003F, 0x0000 }, /* R35 - Input bias control */
834 [37] = { 0x001F, 0x001F, 0x0000 }, /* R37 - Left input PGA control */
835 [38] = { 0x001F, 0x001F, 0x0000 }, /* R38 - Right input PGA control */
836 [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */
837 [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */
838
839 [47] = { 0x000F, 0x0000, 0x0000 }, /* R47 - Thermal Shutdown Status */
840 [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */
841 [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */
842 [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */
843 [56] = { 0x001E, 0x001E, 0x0000 }, /* R56 - Clocking 4 */
844 [57] = { 0x02FC, 0x02FC, 0x0000 }, /* R57 - DAC DSP Mixing (1) */
845 [58] = { 0x00FC, 0x00FC, 0x0000 }, /* R58 - DAC DSP Mixing (2) */
846 [60] = { 0x00CC, 0x00CC, 0x0000 }, /* R60 - DC Servo 0 */
847 [61] = { 0x00DD, 0x00DD, 0x0000 }, /* R61 - DC Servo 1 */
848 [64] = { 0x3F80, 0x3F80, 0x0000 }, /* R64 - DC Servo 4 */
849 [66] = { 0x0780, 0x0000, 0xFFFF }, /* R66 - DC Servo 6 */
850 [68] = { 0x0007, 0x0007, 0x0000 }, /* R68 - Analogue PGA Bias */
851 [69] = { 0x00FF, 0x00FF, 0x0000 }, /* R69 - Analogue HP 0 */
852 [71] = { 0x01FF, 0x01FF, 0x0000 }, /* R71 - Analogue HP 2 */
853 [72] = { 0x0001, 0x0001, 0x0000 }, /* R72 - Charge Pump 1 */
854 [82] = { 0x0001, 0x0001, 0x0000 }, /* R82 - Charge Pump B */
855 [87] = { 0x00A0, 0x00A0, 0x0000 }, /* R87 - Write Sequencer Control 1 */
856 [90] = { 0x007F, 0x01FF, 0x0000 }, /* R90 - Write Sequencer Control 2 */
857 [93] = { 0x03F9, 0x0000, 0x0000 }, /* R93 - Write Sequencer Control 3 */
858 [94] = { 0x0070, 0x0070, 0x0000 }, /* R94 - Control Interface */
859 [99] = { 0x000F, 0x000F, 0x0000 }, /* R99 - Mixer Enables */
860 [100] = { 0x00BF, 0x00BF, 0x0000 }, /* R100 - Headphone Mixer (1) */
861 [101] = { 0x00BF, 0x00BF, 0x0000 }, /* R101 - Headphone Mixer (2) */
862 [102] = { 0x01FF, 0x01FF, 0x0000 }, /* R102 - Headphone Mixer (3) */
863 [103] = { 0x01FF, 0x01FF, 0x0000 }, /* R103 - Headphone Mixer (4) */
864 [105] = { 0x00BF, 0x00BF, 0x0000 }, /* R105 - Speaker Mixer (1) */
865 [106] = { 0x00BF, 0x00BF, 0x0000 }, /* R106 - Speaker Mixer (2) */
866 [107] = { 0x01FF, 0x01FF, 0x0000 }, /* R107 - Speaker Mixer (3) */
867 [108] = { 0x01FF, 0x01FF, 0x0000 }, /* R108 - Speaker Mixer (4) */
868 [109] = { 0x00F0, 0x00F0, 0x0000 }, /* R109 - Speaker Mixer (5) */
869 [110] = { 0x00F7, 0x00F7, 0x0000 }, /* R110 - Beep Generator (1) */
870 [115] = { 0x001F, 0x001F, 0x0000 }, /* R115 - Oscillator Trim (3) */
871 [116] = { 0x001F, 0x001F, 0x0000 }, /* R116 - Oscillator Trim (4) */
872 [119] = { 0x00FF, 0x00FF, 0x0000 }, /* R119 - Oscillator Trim (7) */
873 [124] = { 0x0079, 0x0079, 0x0000 }, /* R124 - Analogue Clocking1 */
874 [125] = { 0x00DF, 0x00DF, 0x0000 }, /* R125 - Analogue Clocking2 */
875 [126] = { 0x000D, 0x000D, 0x0000 }, /* R126 - Analogue Clocking3 */
876 [127] = { 0x0000, 0xFFFF, 0x0000 }, /* R127 - PLL Software Reset */
877 [129] = { 0x00B0, 0x00B0, 0x0000 }, /* R129 - PLL2 */
878 [131] = { 0x0003, 0x0003, 0x0000 }, /* R131 - PLL 4 */
879 [136] = { 0x005F, 0x005F, 0x0000 }, /* R136 - PLL 9 */
880 [137] = { 0x00FF, 0x00FF, 0x0000 }, /* R137 - PLL 10 */
881 [138] = { 0x00FF, 0x00FF, 0x0000 }, /* R138 - PLL 11 */
882 [139] = { 0x00FF, 0x00FF, 0x0000 }, /* R139 - PLL 12 */
883 [140] = { 0x005F, 0x005F, 0x0000 }, /* R140 - PLL 13 */
884 [141] = { 0x00FF, 0x00FF, 0x0000 }, /* R141 - PLL 14 */
885 [142] = { 0x00FF, 0x00FF, 0x0000 }, /* R142 - PLL 15 */
886 [143] = { 0x00FF, 0x00FF, 0x0000 }, /* R143 - PLL 16 */
887 [155] = { 0x0067, 0x0067, 0x0000 }, /* R155 - FLL Control (1) */
888 [156] = { 0x01FB, 0x01FB, 0x0000 }, /* R156 - FLL Control (2) */
889 [157] = { 0x0007, 0x0007, 0x0000 }, /* R157 - FLL Control (3) */
890 [159] = { 0x007F, 0x007F, 0x0000 }, /* R159 - FLL Control (5) */
891 [160] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R160 - FLL Control (6) */
892 [161] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R161 - FLL Control (7) */
893 [162] = { 0x03FF, 0x03FF, 0x0000 }, /* R162 - FLL Control (8) */
894 [252] = { 0x0005, 0x0005, 0x0000 }, /* R252 - General test 1 */
895 [256] = { 0x000F, 0x000F, 0x0000 }, /* R256 - DF1 */
896 [257] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R257 - DF2 */
897 [258] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R258 - DF3 */
898 [259] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R259 - DF4 */
899 [260] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R260 - DF5 */
900 [261] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R261 - DF6 */
901 [262] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R262 - DF7 */
902 [264] = { 0x0003, 0x0003, 0x0000 }, /* R264 - LHPF1 */
903 [265] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R265 - LHPF2 */
904 [268] = { 0x0077, 0x0077, 0x0000 }, /* R268 - THREED1 */
905 [269] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R269 - THREED2 */
906 [270] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R270 - THREED3 */
907 [271] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R271 - THREED4 */
908 [276] = { 0x7FFF, 0x7FFF, 0x0000 }, /* R276 - DRC 1 */
909 [277] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R277 - DRC 2 */
910 [278] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R278 - DRC 3 */
911 [279] = { 0x07FF, 0x07FF, 0x0000 }, /* R279 - DRC 4 */
912 [280] = { 0x03FF, 0x03FF, 0x0000 }, /* R280 - DRC 5 */
913 [285] = { 0x0003, 0x0003, 0x0000 }, /* R285 - Tloopback */
914 [335] = { 0x0007, 0x0007, 0x0000 }, /* R335 - EQ1 */
915 [336] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R336 - EQ2 */
916 [337] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R337 - EQ3 */
917 [338] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R338 - EQ4 */
918 [339] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R339 - EQ5 */
919 [340] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R340 - EQ6 */
920 [341] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R341 - EQ7 */
921 [342] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R342 - EQ8 */
922 [343] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R343 - EQ9 */
923 [344] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R344 - EQ10 */
924 [345] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R345 - EQ11 */
925 [346] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R346 - EQ12 */
926 [347] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R347 - EQ13 */
927 [348] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R348 - EQ14 */
928 [349] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R349 - EQ15 */
929 [350] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R350 - EQ16 */
930 [351] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R351 - EQ17 */
931 [352] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R352 - EQ18 */
932 [353] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R353 - EQ19 */
933 [354] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R354 - EQ20 */
934 [355] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R355 - EQ21 */
935 [356] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R356 - EQ22 */
936 [357] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R357 - EQ23 */
937 [358] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R358 - EQ24 */
938 [359] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R359 - EQ25 */
939 [360] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R360 - EQ26 */
940 [361] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R361 - EQ27 */
941 [362] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R362 - EQ28 */
942 [363] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R363 - EQ29 */
943 [364] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R364 - EQ30 */
944 [365] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R365 - EQ31 */
945 [366] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R366 - EQ32 */
946 [367] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R367 - EQ33 */
947 [368] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R368 - EQ34 */
948 [369] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R369 - EQ35 */
949 [370] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R370 - EQ36 */
950 [371] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R371 - EQ37 */
951 [372] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R372 - EQ38 */
952 [373] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R373 - EQ39 */
953 [374] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R374 - EQ40 */
954 [375] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R375 - EQ41 */
955 [513] = { 0x045F, 0x045F, 0x0000 }, /* R513 - GPIO 2 */
956 [514] = { 0x045F, 0x045F, 0x0000 }, /* R514 - GPIO 3 */
957 [516] = { 0xE75F, 0xE75F, 0x0000 }, /* R516 - GPIO 5 */
958 [517] = { 0xE75F, 0xE75F, 0x0000 }, /* R517 - GPIO 6 */
959 [560] = { 0x0030, 0x0030, 0xFFFF }, /* R560 - Interrupt Status 1 */
960 [561] = { 0xFFED, 0xFFED, 0xFFFF }, /* R561 - Interrupt Status 2 */
961 [568] = { 0x0030, 0x0030, 0x0000 }, /* R568 - Interrupt Status 1 Mask */
962 [569] = { 0xFFED, 0xFFED, 0x0000 }, /* R569 - Interrupt Status 2 Mask */
963 [576] = { 0x0001, 0x0001, 0x0000 }, /* R576 - Interrupt Control */
964 [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */
965 [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */
966 [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */
967 [1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */
968 [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */
969 [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */
970 [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */
971 [4099] = { 0x010F, 0x010F, 0x0000 }, /* R4099 - Write Sequencer 3 */
972 [4100] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4100 - Write Sequencer 4 */
973 [4101] = { 0x00FF, 0x00FF, 0x0000 }, /* R4101 - Write Sequencer 5 */
974 [4102] = { 0x070F, 0x070F, 0x0000 }, /* R4102 - Write Sequencer 6 */
975 [4103] = { 0x010F, 0x010F, 0x0000 }, /* R4103 - Write Sequencer 7 */
976 [4104] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4104 - Write Sequencer 8 */
977 [4105] = { 0x00FF, 0x00FF, 0x0000 }, /* R4105 - Write Sequencer 9 */
978 [4106] = { 0x070F, 0x070F, 0x0000 }, /* R4106 - Write Sequencer 10 */
979 [4107] = { 0x010F, 0x010F, 0x0000 }, /* R4107 - Write Sequencer 11 */
980 [4108] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4108 - Write Sequencer 12 */
981 [4109] = { 0x00FF, 0x00FF, 0x0000 }, /* R4109 - Write Sequencer 13 */
982 [4110] = { 0x070F, 0x070F, 0x0000 }, /* R4110 - Write Sequencer 14 */
983 [4111] = { 0x010F, 0x010F, 0x0000 }, /* R4111 - Write Sequencer 15 */
984 [4112] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4112 - Write Sequencer 16 */
985 [4113] = { 0x00FF, 0x00FF, 0x0000 }, /* R4113 - Write Sequencer 17 */
986 [4114] = { 0x070F, 0x070F, 0x0000 }, /* R4114 - Write Sequencer 18 */
987 [4115] = { 0x010F, 0x010F, 0x0000 }, /* R4115 - Write Sequencer 19 */
988 [4116] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4116 - Write Sequencer 20 */
989 [4117] = { 0x00FF, 0x00FF, 0x0000 }, /* R4117 - Write Sequencer 21 */
990 [4118] = { 0x070F, 0x070F, 0x0000 }, /* R4118 - Write Sequencer 22 */
991 [4119] = { 0x010F, 0x010F, 0x0000 }, /* R4119 - Write Sequencer 23 */
992 [4120] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4120 - Write Sequencer 24 */
993 [4121] = { 0x00FF, 0x00FF, 0x0000 }, /* R4121 - Write Sequencer 25 */
994 [4122] = { 0x070F, 0x070F, 0x0000 }, /* R4122 - Write Sequencer 26 */
995 [4123] = { 0x010F, 0x010F, 0x0000 }, /* R4123 - Write Sequencer 27 */
996 [4124] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4124 - Write Sequencer 28 */
997 [4125] = { 0x00FF, 0x00FF, 0x0000 }, /* R4125 - Write Sequencer 29 */
998 [4126] = { 0x070F, 0x070F, 0x0000 }, /* R4126 - Write Sequencer 30 */
999 [4127] = { 0x010F, 0x010F, 0x0000 }, /* R4127 - Write Sequencer 31 */
1000 [4128] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4128 - Write Sequencer 32 */
1001 [4129] = { 0x00FF, 0x00FF, 0x0000 }, /* R4129 - Write Sequencer 33 */
1002 [4130] = { 0x070F, 0x070F, 0x0000 }, /* R4130 - Write Sequencer 34 */
1003 [4131] = { 0x010F, 0x010F, 0x0000 }, /* R4131 - Write Sequencer 35 */
1004 [4132] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4132 - Write Sequencer 36 */
1005 [4133] = { 0x00FF, 0x00FF, 0x0000 }, /* R4133 - Write Sequencer 37 */
1006 [4134] = { 0x070F, 0x070F, 0x0000 }, /* R4134 - Write Sequencer 38 */
1007 [4135] = { 0x010F, 0x010F, 0x0000 }, /* R4135 - Write Sequencer 39 */
1008 [4136] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4136 - Write Sequencer 40 */
1009 [4137] = { 0x00FF, 0x00FF, 0x0000 }, /* R4137 - Write Sequencer 41 */
1010 [4138] = { 0x070F, 0x070F, 0x0000 }, /* R4138 - Write Sequencer 42 */
1011 [4139] = { 0x010F, 0x010F, 0x0000 }, /* R4139 - Write Sequencer 43 */
1012 [4140] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4140 - Write Sequencer 44 */
1013 [4141] = { 0x00FF, 0x00FF, 0x0000 }, /* R4141 - Write Sequencer 45 */
1014 [4142] = { 0x070F, 0x070F, 0x0000 }, /* R4142 - Write Sequencer 46 */
1015 [4143] = { 0x010F, 0x010F, 0x0000 }, /* R4143 - Write Sequencer 47 */
1016 [4144] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4144 - Write Sequencer 48 */
1017 [4145] = { 0x00FF, 0x00FF, 0x0000 }, /* R4145 - Write Sequencer 49 */
1018 [4146] = { 0x070F, 0x070F, 0x0000 }, /* R4146 - Write Sequencer 50 */
1019 [4147] = { 0x010F, 0x010F, 0x0000 }, /* R4147 - Write Sequencer 51 */
1020 [4148] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4148 - Write Sequencer 52 */
1021 [4149] = { 0x00FF, 0x00FF, 0x0000 }, /* R4149 - Write Sequencer 53 */
1022 [4150] = { 0x070F, 0x070F, 0x0000 }, /* R4150 - Write Sequencer 54 */
1023 [4151] = { 0x010F, 0x010F, 0x0000 }, /* R4151 - Write Sequencer 55 */
1024 [4152] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4152 - Write Sequencer 56 */
1025 [4153] = { 0x00FF, 0x00FF, 0x0000 }, /* R4153 - Write Sequencer 57 */
1026 [4154] = { 0x070F, 0x070F, 0x0000 }, /* R4154 - Write Sequencer 58 */
1027 [4155] = { 0x010F, 0x010F, 0x0000 }, /* R4155 - Write Sequencer 59 */
1028 [4156] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4156 - Write Sequencer 60 */
1029 [4157] = { 0x00FF, 0x00FF, 0x0000 }, /* R4157 - Write Sequencer 61 */
1030 [4158] = { 0x070F, 0x070F, 0x0000 }, /* R4158 - Write Sequencer 62 */
1031 [4159] = { 0x010F, 0x010F, 0x0000 }, /* R4159 - Write Sequencer 63 */
1032 [4160] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4160 - Write Sequencer 64 */
1033 [4161] = { 0x00FF, 0x00FF, 0x0000 }, /* R4161 - Write Sequencer 65 */
1034 [4162] = { 0x070F, 0x070F, 0x0000 }, /* R4162 - Write Sequencer 66 */
1035 [4163] = { 0x010F, 0x010F, 0x0000 }, /* R4163 - Write Sequencer 67 */
1036 [4164] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4164 - Write Sequencer 68 */
1037 [4165] = { 0x00FF, 0x00FF, 0x0000 }, /* R4165 - Write Sequencer 69 */
1038 [4166] = { 0x070F, 0x070F, 0x0000 }, /* R4166 - Write Sequencer 70 */
1039 [4167] = { 0x010F, 0x010F, 0x0000 }, /* R4167 - Write Sequencer 71 */
1040 [4168] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4168 - Write Sequencer 72 */
1041 [4169] = { 0x00FF, 0x00FF, 0x0000 }, /* R4169 - Write Sequencer 73 */
1042 [4170] = { 0x070F, 0x070F, 0x0000 }, /* R4170 - Write Sequencer 74 */
1043 [4171] = { 0x010F, 0x010F, 0x0000 }, /* R4171 - Write Sequencer 75 */
1044 [4172] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4172 - Write Sequencer 76 */
1045 [4173] = { 0x00FF, 0x00FF, 0x0000 }, /* R4173 - Write Sequencer 77 */
1046 [4174] = { 0x070F, 0x070F, 0x0000 }, /* R4174 - Write Sequencer 78 */
1047 [4175] = { 0x010F, 0x010F, 0x0000 }, /* R4175 - Write Sequencer 79 */
1048 [4176] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4176 - Write Sequencer 80 */
1049 [4177] = { 0x00FF, 0x00FF, 0x0000 }, /* R4177 - Write Sequencer 81 */
1050 [4178] = { 0x070F, 0x070F, 0x0000 }, /* R4178 - Write Sequencer 82 */
1051 [4179] = { 0x010F, 0x010F, 0x0000 }, /* R4179 - Write Sequencer 83 */
1052 [4180] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4180 - Write Sequencer 84 */
1053 [4181] = { 0x00FF, 0x00FF, 0x0000 }, /* R4181 - Write Sequencer 85 */
1054 [4182] = { 0x070F, 0x070F, 0x0000 }, /* R4182 - Write Sequencer 86 */
1055 [4183] = { 0x010F, 0x010F, 0x0000 }, /* R4183 - Write Sequencer 87 */
1056 [4184] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4184 - Write Sequencer 88 */
1057 [4185] = { 0x00FF, 0x00FF, 0x0000 }, /* R4185 - Write Sequencer 89 */
1058 [4186] = { 0x070F, 0x070F, 0x0000 }, /* R4186 - Write Sequencer 90 */
1059 [4187] = { 0x010F, 0x010F, 0x0000 }, /* R4187 - Write Sequencer 91 */
1060 [4188] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4188 - Write Sequencer 92 */
1061 [4189] = { 0x00FF, 0x00FF, 0x0000 }, /* R4189 - Write Sequencer 93 */
1062 [4190] = { 0x070F, 0x070F, 0x0000 }, /* R4190 - Write Sequencer 94 */
1063 [4191] = { 0x010F, 0x010F, 0x0000 }, /* R4191 - Write Sequencer 95 */
1064 [4192] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4192 - Write Sequencer 96 */
1065 [4193] = { 0x00FF, 0x00FF, 0x0000 }, /* R4193 - Write Sequencer 97 */
1066 [4194] = { 0x070F, 0x070F, 0x0000 }, /* R4194 - Write Sequencer 98 */
1067 [4195] = { 0x010F, 0x010F, 0x0000 }, /* R4195 - Write Sequencer 99 */
1068 [4196] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4196 - Write Sequencer 100 */
1069 [4197] = { 0x00FF, 0x00FF, 0x0000 }, /* R4197 - Write Sequencer 101 */
1070 [4198] = { 0x070F, 0x070F, 0x0000 }, /* R4198 - Write Sequencer 102 */
1071 [4199] = { 0x010F, 0x010F, 0x0000 }, /* R4199 - Write Sequencer 103 */
1072 [4200] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4200 - Write Sequencer 104 */
1073 [4201] = { 0x00FF, 0x00FF, 0x0000 }, /* R4201 - Write Sequencer 105 */
1074 [4202] = { 0x070F, 0x070F, 0x0000 }, /* R4202 - Write Sequencer 106 */
1075 [4203] = { 0x010F, 0x010F, 0x0000 }, /* R4203 - Write Sequencer 107 */
1076 [4204] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4204 - Write Sequencer 108 */
1077 [4205] = { 0x00FF, 0x00FF, 0x0000 }, /* R4205 - Write Sequencer 109 */
1078 [4206] = { 0x070F, 0x070F, 0x0000 }, /* R4206 - Write Sequencer 110 */
1079 [4207] = { 0x010F, 0x010F, 0x0000 }, /* R4207 - Write Sequencer 111 */
1080 [4208] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4208 - Write Sequencer 112 */
1081 [4209] = { 0x00FF, 0x00FF, 0x0000 }, /* R4209 - Write Sequencer 113 */
1082 [4210] = { 0x070F, 0x070F, 0x0000 }, /* R4210 - Write Sequencer 114 */
1083 [4211] = { 0x010F, 0x010F, 0x0000 }, /* R4211 - Write Sequencer 115 */
1084 [4212] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4212 - Write Sequencer 116 */
1085 [4213] = { 0x00FF, 0x00FF, 0x0000 }, /* R4213 - Write Sequencer 117 */
1086 [4214] = { 0x070F, 0x070F, 0x0000 }, /* R4214 - Write Sequencer 118 */
1087 [4215] = { 0x010F, 0x010F, 0x0000 }, /* R4215 - Write Sequencer 119 */
1088 [4216] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4216 - Write Sequencer 120 */
1089 [4217] = { 0x00FF, 0x00FF, 0x0000 }, /* R4217 - Write Sequencer 121 */
1090 [4218] = { 0x070F, 0x070F, 0x0000 }, /* R4218 - Write Sequencer 122 */
1091 [4219] = { 0x010F, 0x010F, 0x0000 }, /* R4219 - Write Sequencer 123 */
1092 [4220] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4220 - Write Sequencer 124 */
1093 [4221] = { 0x00FF, 0x00FF, 0x0000 }, /* R4221 - Write Sequencer 125 */
1094 [4222] = { 0x070F, 0x070F, 0x0000 }, /* R4222 - Write Sequencer 126 */
1095 [4223] = { 0x010F, 0x010F, 0x0000 }, /* R4223 - Write Sequencer 127 */
1096 [4224] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4224 - Write Sequencer 128 */
1097 [4225] = { 0x00FF, 0x00FF, 0x0000 }, /* R4225 - Write Sequencer 129 */
1098 [4226] = { 0x070F, 0x070F, 0x0000 }, /* R4226 - Write Sequencer 130 */
1099 [4227] = { 0x010F, 0x010F, 0x0000 }, /* R4227 - Write Sequencer 131 */
1100 [4228] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4228 - Write Sequencer 132 */
1101 [4229] = { 0x00FF, 0x00FF, 0x0000 }, /* R4229 - Write Sequencer 133 */
1102 [4230] = { 0x070F, 0x070F, 0x0000 }, /* R4230 - Write Sequencer 134 */
1103 [4231] = { 0x010F, 0x010F, 0x0000 }, /* R4231 - Write Sequencer 135 */
1104 [4232] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4232 - Write Sequencer 136 */
1105 [4233] = { 0x00FF, 0x00FF, 0x0000 }, /* R4233 - Write Sequencer 137 */
1106 [4234] = { 0x070F, 0x070F, 0x0000 }, /* R4234 - Write Sequencer 138 */
1107 [4235] = { 0x010F, 0x010F, 0x0000 }, /* R4235 - Write Sequencer 139 */
1108 [4236] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4236 - Write Sequencer 140 */
1109 [4237] = { 0x00FF, 0x00FF, 0x0000 }, /* R4237 - Write Sequencer 141 */
1110 [4238] = { 0x070F, 0x070F, 0x0000 }, /* R4238 - Write Sequencer 142 */
1111 [4239] = { 0x010F, 0x010F, 0x0000 }, /* R4239 - Write Sequencer 143 */
1112 [4240] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4240 - Write Sequencer 144 */
1113 [4241] = { 0x00FF, 0x00FF, 0x0000 }, /* R4241 - Write Sequencer 145 */
1114 [4242] = { 0x070F, 0x070F, 0x0000 }, /* R4242 - Write Sequencer 146 */
1115 [4243] = { 0x010F, 0x010F, 0x0000 }, /* R4243 - Write Sequencer 147 */
1116 [4244] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4244 - Write Sequencer 148 */
1117 [4245] = { 0x00FF, 0x00FF, 0x0000 }, /* R4245 - Write Sequencer 149 */
1118 [4246] = { 0x070F, 0x070F, 0x0000 }, /* R4246 - Write Sequencer 150 */
1119 [4247] = { 0x010F, 0x010F, 0x0000 }, /* R4247 - Write Sequencer 151 */
1120 [4248] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4248 - Write Sequencer 152 */
1121 [4249] = { 0x00FF, 0x00FF, 0x0000 }, /* R4249 - Write Sequencer 153 */
1122 [4250] = { 0x070F, 0x070F, 0x0000 }, /* R4250 - Write Sequencer 154 */
1123 [4251] = { 0x010F, 0x010F, 0x0000 }, /* R4251 - Write Sequencer 155 */
1124 [4252] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4252 - Write Sequencer 156 */
1125 [4253] = { 0x00FF, 0x00FF, 0x0000 }, /* R4253 - Write Sequencer 157 */
1126 [4254] = { 0x070F, 0x070F, 0x0000 }, /* R4254 - Write Sequencer 158 */
1127 [4255] = { 0x010F, 0x010F, 0x0000 }, /* R4255 - Write Sequencer 159 */
1128 [4256] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4256 - Write Sequencer 160 */
1129 [4257] = { 0x00FF, 0x00FF, 0x0000 }, /* R4257 - Write Sequencer 161 */
1130 [4258] = { 0x070F, 0x070F, 0x0000 }, /* R4258 - Write Sequencer 162 */
1131 [4259] = { 0x010F, 0x010F, 0x0000 }, /* R4259 - Write Sequencer 163 */
1132 [4260] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4260 - Write Sequencer 164 */
1133 [4261] = { 0x00FF, 0x00FF, 0x0000 }, /* R4261 - Write Sequencer 165 */
1134 [4262] = { 0x070F, 0x070F, 0x0000 }, /* R4262 - Write Sequencer 166 */
1135 [4263] = { 0x010F, 0x010F, 0x0000 }, /* R4263 - Write Sequencer 167 */
1136 [4264] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4264 - Write Sequencer 168 */
1137 [4265] = { 0x00FF, 0x00FF, 0x0000 }, /* R4265 - Write Sequencer 169 */
1138 [4266] = { 0x070F, 0x070F, 0x0000 }, /* R4266 - Write Sequencer 170 */
1139 [4267] = { 0x010F, 0x010F, 0x0000 }, /* R4267 - Write Sequencer 171 */
1140 [4268] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4268 - Write Sequencer 172 */
1141 [4269] = { 0x00FF, 0x00FF, 0x0000 }, /* R4269 - Write Sequencer 173 */
1142 [4270] = { 0x070F, 0x070F, 0x0000 }, /* R4270 - Write Sequencer 174 */
1143 [4271] = { 0x010F, 0x010F, 0x0000 }, /* R4271 - Write Sequencer 175 */
1144 [4272] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4272 - Write Sequencer 176 */
1145 [4273] = { 0x00FF, 0x00FF, 0x0000 }, /* R4273 - Write Sequencer 177 */
1146 [4274] = { 0x070F, 0x070F, 0x0000 }, /* R4274 - Write Sequencer 178 */
1147 [4275] = { 0x010F, 0x010F, 0x0000 }, /* R4275 - Write Sequencer 179 */
1148 [4276] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4276 - Write Sequencer 180 */
1149 [4277] = { 0x00FF, 0x00FF, 0x0000 }, /* R4277 - Write Sequencer 181 */
1150 [4278] = { 0x070F, 0x070F, 0x0000 }, /* R4278 - Write Sequencer 182 */
1151 [4279] = { 0x010F, 0x010F, 0x0000 }, /* R4279 - Write Sequencer 183 */
1152 [4280] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4280 - Write Sequencer 184 */
1153 [4281] = { 0x00FF, 0x00FF, 0x0000 }, /* R4281 - Write Sequencer 185 */
1154 [4282] = { 0x070F, 0x070F, 0x0000 }, /* R4282 - Write Sequencer 186 */
1155 [4283] = { 0x010F, 0x010F, 0x0000 }, /* R4283 - Write Sequencer 187 */
1156 [4284] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4284 - Write Sequencer 188 */
1157 [4285] = { 0x00FF, 0x00FF, 0x0000 }, /* R4285 - Write Sequencer 189 */
1158 [4286] = { 0x070F, 0x070F, 0x0000 }, /* R4286 - Write Sequencer 190 */
1159 [4287] = { 0x010F, 0x010F, 0x0000 }, /* R4287 - Write Sequencer 191 */
1160 [4288] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4288 - Write Sequencer 192 */
1161 [4289] = { 0x00FF, 0x00FF, 0x0000 }, /* R4289 - Write Sequencer 193 */
1162 [4290] = { 0x070F, 0x070F, 0x0000 }, /* R4290 - Write Sequencer 194 */
1163 [4291] = { 0x010F, 0x010F, 0x0000 }, /* R4291 - Write Sequencer 195 */
1164 [4292] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4292 - Write Sequencer 196 */
1165 [4293] = { 0x00FF, 0x00FF, 0x0000 }, /* R4293 - Write Sequencer 197 */
1166 [4294] = { 0x070F, 0x070F, 0x0000 }, /* R4294 - Write Sequencer 198 */
1167 [4295] = { 0x010F, 0x010F, 0x0000 }, /* R4295 - Write Sequencer 199 */
1168 [4296] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4296 - Write Sequencer 200 */
1169 [4297] = { 0x00FF, 0x00FF, 0x0000 }, /* R4297 - Write Sequencer 201 */
1170 [4298] = { 0x070F, 0x070F, 0x0000 }, /* R4298 - Write Sequencer 202 */
1171 [4299] = { 0x010F, 0x010F, 0x0000 }, /* R4299 - Write Sequencer 203 */
1172 [4300] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4300 - Write Sequencer 204 */
1173 [4301] = { 0x00FF, 0x00FF, 0x0000 }, /* R4301 - Write Sequencer 205 */
1174 [4302] = { 0x070F, 0x070F, 0x0000 }, /* R4302 - Write Sequencer 206 */
1175 [4303] = { 0x010F, 0x010F, 0x0000 }, /* R4303 - Write Sequencer 207 */
1176 [4304] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4304 - Write Sequencer 208 */
1177 [4305] = { 0x00FF, 0x00FF, 0x0000 }, /* R4305 - Write Sequencer 209 */
1178 [4306] = { 0x070F, 0x070F, 0x0000 }, /* R4306 - Write Sequencer 210 */
1179 [4307] = { 0x010F, 0x010F, 0x0000 }, /* R4307 - Write Sequencer 211 */
1180 [4308] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4308 - Write Sequencer 212 */
1181 [4309] = { 0x00FF, 0x00FF, 0x0000 }, /* R4309 - Write Sequencer 213 */
1182 [4310] = { 0x070F, 0x070F, 0x0000 }, /* R4310 - Write Sequencer 214 */
1183 [4311] = { 0x010F, 0x010F, 0x0000 }, /* R4311 - Write Sequencer 215 */
1184 [4312] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4312 - Write Sequencer 216 */
1185 [4313] = { 0x00FF, 0x00FF, 0x0000 }, /* R4313 - Write Sequencer 217 */
1186 [4314] = { 0x070F, 0x070F, 0x0000 }, /* R4314 - Write Sequencer 218 */
1187 [4315] = { 0x010F, 0x010F, 0x0000 }, /* R4315 - Write Sequencer 219 */
1188 [4316] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4316 - Write Sequencer 220 */
1189 [4317] = { 0x00FF, 0x00FF, 0x0000 }, /* R4317 - Write Sequencer 221 */
1190 [4318] = { 0x070F, 0x070F, 0x0000 }, /* R4318 - Write Sequencer 222 */
1191 [4319] = { 0x010F, 0x010F, 0x0000 }, /* R4319 - Write Sequencer 223 */
1192 [4320] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4320 - Write Sequencer 224 */
1193 [4321] = { 0x00FF, 0x00FF, 0x0000 }, /* R4321 - Write Sequencer 225 */
1194 [4322] = { 0x070F, 0x070F, 0x0000 }, /* R4322 - Write Sequencer 226 */
1195 [4323] = { 0x010F, 0x010F, 0x0000 }, /* R4323 - Write Sequencer 227 */
1196 [4324] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4324 - Write Sequencer 228 */
1197 [4325] = { 0x00FF, 0x00FF, 0x0000 }, /* R4325 - Write Sequencer 229 */
1198 [4326] = { 0x070F, 0x070F, 0x0000 }, /* R4326 - Write Sequencer 230 */
1199 [4327] = { 0x010F, 0x010F, 0x0000 }, /* R4327 - Write Sequencer 231 */
1200 [4328] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4328 - Write Sequencer 232 */
1201 [4329] = { 0x00FF, 0x00FF, 0x0000 }, /* R4329 - Write Sequencer 233 */
1202 [4330] = { 0x070F, 0x070F, 0x0000 }, /* R4330 - Write Sequencer 234 */
1203 [4331] = { 0x010F, 0x010F, 0x0000 }, /* R4331 - Write Sequencer 235 */
1204 [4332] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4332 - Write Sequencer 236 */
1205 [4333] = { 0x00FF, 0x00FF, 0x0000 }, /* R4333 - Write Sequencer 237 */
1206 [4334] = { 0x070F, 0x070F, 0x0000 }, /* R4334 - Write Sequencer 238 */
1207 [4335] = { 0x010F, 0x010F, 0x0000 }, /* R4335 - Write Sequencer 239 */
1208 [4336] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4336 - Write Sequencer 240 */
1209 [4337] = { 0x00FF, 0x00FF, 0x0000 }, /* R4337 - Write Sequencer 241 */
1210 [4338] = { 0x070F, 0x070F, 0x0000 }, /* R4338 - Write Sequencer 242 */
1211 [4339] = { 0x010F, 0x010F, 0x0000 }, /* R4339 - Write Sequencer 243 */
1212 [4340] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4340 - Write Sequencer 244 */
1213 [4341] = { 0x00FF, 0x00FF, 0x0000 }, /* R4341 - Write Sequencer 245 */
1214 [4342] = { 0x070F, 0x070F, 0x0000 }, /* R4342 - Write Sequencer 246 */
1215 [4343] = { 0x010F, 0x010F, 0x0000 }, /* R4343 - Write Sequencer 247 */
1216 [4344] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4344 - Write Sequencer 248 */
1217 [4345] = { 0x00FF, 0x00FF, 0x0000 }, /* R4345 - Write Sequencer 249 */
1218 [4346] = { 0x070F, 0x070F, 0x0000 }, /* R4346 - Write Sequencer 250 */
1219 [4347] = { 0x010F, 0x010F, 0x0000 }, /* R4347 - Write Sequencer 251 */
1220 [4348] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4348 - Write Sequencer 252 */
1221 [4349] = { 0x00FF, 0x00FF, 0x0000 }, /* R4349 - Write Sequencer 253 */
1222 [4350] = { 0x070F, 0x070F, 0x0000 }, /* R4350 - Write Sequencer 254 */
1223 [4351] = { 0x010F, 0x010F, 0x0000 }, /* R4351 - Write Sequencer 255 */
1224 [4352] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4352 - Write Sequencer 256 */
1225 [4353] = { 0x00FF, 0x00FF, 0x0000 }, /* R4353 - Write Sequencer 257 */
1226 [4354] = { 0x070F, 0x070F, 0x0000 }, /* R4354 - Write Sequencer 258 */
1227 [4355] = { 0x010F, 0x010F, 0x0000 }, /* R4355 - Write Sequencer 259 */
1228 [4356] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4356 - Write Sequencer 260 */
1229 [4357] = { 0x00FF, 0x00FF, 0x0000 }, /* R4357 - Write Sequencer 261 */
1230 [4358] = { 0x070F, 0x070F, 0x0000 }, /* R4358 - Write Sequencer 262 */
1231 [4359] = { 0x010F, 0x010F, 0x0000 }, /* R4359 - Write Sequencer 263 */
1232 [4360] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4360 - Write Sequencer 264 */
1233 [4361] = { 0x00FF, 0x00FF, 0x0000 }, /* R4361 - Write Sequencer 265 */
1234 [4362] = { 0x070F, 0x070F, 0x0000 }, /* R4362 - Write Sequencer 266 */
1235 [4363] = { 0x010F, 0x010F, 0x0000 }, /* R4363 - Write Sequencer 267 */
1236 [4364] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4364 - Write Sequencer 268 */
1237 [4365] = { 0x00FF, 0x00FF, 0x0000 }, /* R4365 - Write Sequencer 269 */
1238 [4366] = { 0x070F, 0x070F, 0x0000 }, /* R4366 - Write Sequencer 270 */
1239 [4367] = { 0x010F, 0x010F, 0x0000 }, /* R4367 - Write Sequencer 271 */
1240 [4368] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4368 - Write Sequencer 272 */
1241 [4369] = { 0x00FF, 0x00FF, 0x0000 }, /* R4369 - Write Sequencer 273 */
1242 [4370] = { 0x070F, 0x070F, 0x0000 }, /* R4370 - Write Sequencer 274 */
1243 [4371] = { 0x010F, 0x010F, 0x0000 }, /* R4371 - Write Sequencer 275 */
1244 [4372] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4372 - Write Sequencer 276 */
1245 [4373] = { 0x00FF, 0x00FF, 0x0000 }, /* R4373 - Write Sequencer 277 */
1246 [4374] = { 0x070F, 0x070F, 0x0000 }, /* R4374 - Write Sequencer 278 */
1247 [4375] = { 0x010F, 0x010F, 0x0000 }, /* R4375 - Write Sequencer 279 */
1248 [4376] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4376 - Write Sequencer 280 */
1249 [4377] = { 0x00FF, 0x00FF, 0x0000 }, /* R4377 - Write Sequencer 281 */
1250 [4378] = { 0x070F, 0x070F, 0x0000 }, /* R4378 - Write Sequencer 282 */
1251 [4379] = { 0x010F, 0x010F, 0x0000 }, /* R4379 - Write Sequencer 283 */
1252 [4380] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4380 - Write Sequencer 284 */
1253 [4381] = { 0x00FF, 0x00FF, 0x0000 }, /* R4381 - Write Sequencer 285 */
1254 [4382] = { 0x070F, 0x070F, 0x0000 }, /* R4382 - Write Sequencer 286 */
1255 [4383] = { 0x010F, 0x010F, 0x0000 }, /* R4383 - Write Sequencer 287 */
1256 [4384] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4384 - Write Sequencer 288 */
1257 [4385] = { 0x00FF, 0x00FF, 0x0000 }, /* R4385 - Write Sequencer 289 */
1258 [4386] = { 0x070F, 0x070F, 0x0000 }, /* R4386 - Write Sequencer 290 */
1259 [4387] = { 0x010F, 0x010F, 0x0000 }, /* R4387 - Write Sequencer 291 */
1260 [4388] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4388 - Write Sequencer 292 */
1261 [4389] = { 0x00FF, 0x00FF, 0x0000 }, /* R4389 - Write Sequencer 293 */
1262 [4390] = { 0x070F, 0x070F, 0x0000 }, /* R4390 - Write Sequencer 294 */
1263 [4391] = { 0x010F, 0x010F, 0x0000 }, /* R4391 - Write Sequencer 295 */
1264 [4392] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4392 - Write Sequencer 296 */
1265 [4393] = { 0x00FF, 0x00FF, 0x0000 }, /* R4393 - Write Sequencer 297 */
1266 [4394] = { 0x070F, 0x070F, 0x0000 }, /* R4394 - Write Sequencer 298 */
1267 [4395] = { 0x010F, 0x010F, 0x0000 }, /* R4395 - Write Sequencer 299 */
1268 [4396] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4396 - Write Sequencer 300 */
1269 [4397] = { 0x00FF, 0x00FF, 0x0000 }, /* R4397 - Write Sequencer 301 */
1270 [4398] = { 0x070F, 0x070F, 0x0000 }, /* R4398 - Write Sequencer 302 */
1271 [4399] = { 0x010F, 0x010F, 0x0000 }, /* R4399 - Write Sequencer 303 */
1272 [4400] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4400 - Write Sequencer 304 */
1273 [4401] = { 0x00FF, 0x00FF, 0x0000 }, /* R4401 - Write Sequencer 305 */
1274 [4402] = { 0x070F, 0x070F, 0x0000 }, /* R4402 - Write Sequencer 306 */
1275 [4403] = { 0x010F, 0x010F, 0x0000 }, /* R4403 - Write Sequencer 307 */
1276 [4404] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4404 - Write Sequencer 308 */
1277 [4405] = { 0x00FF, 0x00FF, 0x0000 }, /* R4405 - Write Sequencer 309 */
1278 [4406] = { 0x070F, 0x070F, 0x0000 }, /* R4406 - Write Sequencer 310 */
1279 [4407] = { 0x010F, 0x010F, 0x0000 }, /* R4407 - Write Sequencer 311 */
1280 [4408] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4408 - Write Sequencer 312 */
1281 [4409] = { 0x00FF, 0x00FF, 0x0000 }, /* R4409 - Write Sequencer 313 */
1282 [4410] = { 0x070F, 0x070F, 0x0000 }, /* R4410 - Write Sequencer 314 */
1283 [4411] = { 0x010F, 0x010F, 0x0000 }, /* R4411 - Write Sequencer 315 */
1284 [4412] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4412 - Write Sequencer 316 */
1285 [4413] = { 0x00FF, 0x00FF, 0x0000 }, /* R4413 - Write Sequencer 317 */
1286 [4414] = { 0x070F, 0x070F, 0x0000 }, /* R4414 - Write Sequencer 318 */
1287 [4415] = { 0x010F, 0x010F, 0x0000 }, /* R4415 - Write Sequencer 319 */
1288 [4416] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4416 - Write Sequencer 320 */
1289 [4417] = { 0x00FF, 0x00FF, 0x0000 }, /* R4417 - Write Sequencer 321 */
1290 [4418] = { 0x070F, 0x070F, 0x0000 }, /* R4418 - Write Sequencer 322 */
1291 [4419] = { 0x010F, 0x010F, 0x0000 }, /* R4419 - Write Sequencer 323 */
1292 [4420] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4420 - Write Sequencer 324 */
1293 [4421] = { 0x00FF, 0x00FF, 0x0000 }, /* R4421 - Write Sequencer 325 */
1294 [4422] = { 0x070F, 0x070F, 0x0000 }, /* R4422 - Write Sequencer 326 */
1295 [4423] = { 0x010F, 0x010F, 0x0000 }, /* R4423 - Write Sequencer 327 */
1296 [4424] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4424 - Write Sequencer 328 */
1297 [4425] = { 0x00FF, 0x00FF, 0x0000 }, /* R4425 - Write Sequencer 329 */
1298 [4426] = { 0x070F, 0x070F, 0x0000 }, /* R4426 - Write Sequencer 330 */
1299 [4427] = { 0x010F, 0x010F, 0x0000 }, /* R4427 - Write Sequencer 331 */
1300 [4428] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4428 - Write Sequencer 332 */
1301 [4429] = { 0x00FF, 0x00FF, 0x0000 }, /* R4429 - Write Sequencer 333 */
1302 [4430] = { 0x070F, 0x070F, 0x0000 }, /* R4430 - Write Sequencer 334 */
1303 [4431] = { 0x010F, 0x010F, 0x0000 }, /* R4431 - Write Sequencer 335 */
1304 [4432] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4432 - Write Sequencer 336 */
1305 [4433] = { 0x00FF, 0x00FF, 0x0000 }, /* R4433 - Write Sequencer 337 */
1306 [4434] = { 0x070F, 0x070F, 0x0000 }, /* R4434 - Write Sequencer 338 */
1307 [4435] = { 0x010F, 0x010F, 0x0000 }, /* R4435 - Write Sequencer 339 */
1308 [4436] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4436 - Write Sequencer 340 */
1309 [4437] = { 0x00FF, 0x00FF, 0x0000 }, /* R4437 - Write Sequencer 341 */
1310 [4438] = { 0x070F, 0x070F, 0x0000 }, /* R4438 - Write Sequencer 342 */
1311 [4439] = { 0x010F, 0x010F, 0x0000 }, /* R4439 - Write Sequencer 343 */
1312 [4440] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4440 - Write Sequencer 344 */
1313 [4441] = { 0x00FF, 0x00FF, 0x0000 }, /* R4441 - Write Sequencer 345 */
1314 [4442] = { 0x070F, 0x070F, 0x0000 }, /* R4442 - Write Sequencer 346 */
1315 [4443] = { 0x010F, 0x010F, 0x0000 }, /* R4443 - Write Sequencer 347 */
1316 [4444] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4444 - Write Sequencer 348 */
1317 [4445] = { 0x00FF, 0x00FF, 0x0000 }, /* R4445 - Write Sequencer 349 */
1318 [4446] = { 0x070F, 0x070F, 0x0000 }, /* R4446 - Write Sequencer 350 */
1319 [4447] = { 0x010F, 0x010F, 0x0000 }, /* R4447 - Write Sequencer 351 */
1320 [4448] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4448 - Write Sequencer 352 */
1321 [4449] = { 0x00FF, 0x00FF, 0x0000 }, /* R4449 - Write Sequencer 353 */
1322 [4450] = { 0x070F, 0x070F, 0x0000 }, /* R4450 - Write Sequencer 354 */
1323 [4451] = { 0x010F, 0x010F, 0x0000 }, /* R4451 - Write Sequencer 355 */
1324 [4452] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4452 - Write Sequencer 356 */
1325 [4453] = { 0x00FF, 0x00FF, 0x0000 }, /* R4453 - Write Sequencer 357 */
1326 [4454] = { 0x070F, 0x070F, 0x0000 }, /* R4454 - Write Sequencer 358 */
1327 [4455] = { 0x010F, 0x010F, 0x0000 }, /* R4455 - Write Sequencer 359 */
1328 [4456] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4456 - Write Sequencer 360 */
1329 [4457] = { 0x00FF, 0x00FF, 0x0000 }, /* R4457 - Write Sequencer 361 */
1330 [4458] = { 0x070F, 0x070F, 0x0000 }, /* R4458 - Write Sequencer 362 */
1331 [4459] = { 0x010F, 0x010F, 0x0000 }, /* R4459 - Write Sequencer 363 */
1332 [4460] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4460 - Write Sequencer 364 */
1333 [4461] = { 0x00FF, 0x00FF, 0x0000 }, /* R4461 - Write Sequencer 365 */
1334 [4462] = { 0x070F, 0x070F, 0x0000 }, /* R4462 - Write Sequencer 366 */
1335 [4463] = { 0x010F, 0x010F, 0x0000 }, /* R4463 - Write Sequencer 367 */
1336 [4464] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4464 - Write Sequencer 368 */
1337 [4465] = { 0x00FF, 0x00FF, 0x0000 }, /* R4465 - Write Sequencer 369 */
1338 [4466] = { 0x070F, 0x070F, 0x0000 }, /* R4466 - Write Sequencer 370 */
1339 [4467] = { 0x010F, 0x010F, 0x0000 }, /* R4467 - Write Sequencer 371 */
1340 [4468] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4468 - Write Sequencer 372 */
1341 [4469] = { 0x00FF, 0x00FF, 0x0000 }, /* R4469 - Write Sequencer 373 */
1342 [4470] = { 0x070F, 0x070F, 0x0000 }, /* R4470 - Write Sequencer 374 */
1343 [4471] = { 0x010F, 0x010F, 0x0000 }, /* R4471 - Write Sequencer 375 */
1344 [4472] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4472 - Write Sequencer 376 */
1345 [4473] = { 0x00FF, 0x00FF, 0x0000 }, /* R4473 - Write Sequencer 377 */
1346 [4474] = { 0x070F, 0x070F, 0x0000 }, /* R4474 - Write Sequencer 378 */
1347 [4475] = { 0x010F, 0x010F, 0x0000 }, /* R4475 - Write Sequencer 379 */
1348 [4476] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4476 - Write Sequencer 380 */
1349 [4477] = { 0x00FF, 0x00FF, 0x0000 }, /* R4477 - Write Sequencer 381 */
1350 [4478] = { 0x070F, 0x070F, 0x0000 }, /* R4478 - Write Sequencer 382 */
1351 [4479] = { 0x010F, 0x010F, 0x0000 }, /* R4479 - Write Sequencer 383 */
1352 [4480] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4480 - Write Sequencer 384 */
1353 [4481] = { 0x00FF, 0x00FF, 0x0000 }, /* R4481 - Write Sequencer 385 */
1354 [4482] = { 0x070F, 0x070F, 0x0000 }, /* R4482 - Write Sequencer 386 */
1355 [4483] = { 0x010F, 0x010F, 0x0000 }, /* R4483 - Write Sequencer 387 */
1356 [4484] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4484 - Write Sequencer 388 */
1357 [4485] = { 0x00FF, 0x00FF, 0x0000 }, /* R4485 - Write Sequencer 389 */
1358 [4486] = { 0x070F, 0x070F, 0x0000 }, /* R4486 - Write Sequencer 390 */
1359 [4487] = { 0x010F, 0x010F, 0x0000 }, /* R4487 - Write Sequencer 391 */
1360 [4488] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4488 - Write Sequencer 392 */
1361 [4489] = { 0x00FF, 0x00FF, 0x0000 }, /* R4489 - Write Sequencer 393 */
1362 [4490] = { 0x070F, 0x070F, 0x0000 }, /* R4490 - Write Sequencer 394 */
1363 [4491] = { 0x010F, 0x010F, 0x0000 }, /* R4491 - Write Sequencer 395 */
1364 [4492] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4492 - Write Sequencer 396 */
1365 [4493] = { 0x00FF, 0x00FF, 0x0000 }, /* R4493 - Write Sequencer 397 */
1366 [4494] = { 0x070F, 0x070F, 0x0000 }, /* R4494 - Write Sequencer 398 */
1367 [4495] = { 0x010F, 0x010F, 0x0000 }, /* R4495 - Write Sequencer 399 */
1368 [4496] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4496 - Write Sequencer 400 */
1369 [4497] = { 0x00FF, 0x00FF, 0x0000 }, /* R4497 - Write Sequencer 401 */
1370 [4498] = { 0x070F, 0x070F, 0x0000 }, /* R4498 - Write Sequencer 402 */
1371 [4499] = { 0x010F, 0x010F, 0x0000 }, /* R4499 - Write Sequencer 403 */
1372 [4500] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4500 - Write Sequencer 404 */
1373 [4501] = { 0x00FF, 0x00FF, 0x0000 }, /* R4501 - Write Sequencer 405 */
1374 [4502] = { 0x070F, 0x070F, 0x0000 }, /* R4502 - Write Sequencer 406 */
1375 [4503] = { 0x010F, 0x010F, 0x0000 }, /* R4503 - Write Sequencer 407 */
1376 [4504] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4504 - Write Sequencer 408 */
1377 [4505] = { 0x00FF, 0x00FF, 0x0000 }, /* R4505 - Write Sequencer 409 */
1378 [4506] = { 0x070F, 0x070F, 0x0000 }, /* R4506 - Write Sequencer 410 */
1379 [4507] = { 0x010F, 0x010F, 0x0000 }, /* R4507 - Write Sequencer 411 */
1380 [4508] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4508 - Write Sequencer 412 */
1381 [4509] = { 0x00FF, 0x00FF, 0x0000 }, /* R4509 - Write Sequencer 413 */
1382 [4510] = { 0x070F, 0x070F, 0x0000 }, /* R4510 - Write Sequencer 414 */
1383 [4511] = { 0x010F, 0x010F, 0x0000 }, /* R4511 - Write Sequencer 415 */
1384 [4512] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4512 - Write Sequencer 416 */
1385 [4513] = { 0x00FF, 0x00FF, 0x0000 }, /* R4513 - Write Sequencer 417 */
1386 [4514] = { 0x070F, 0x070F, 0x0000 }, /* R4514 - Write Sequencer 418 */
1387 [4515] = { 0x010F, 0x010F, 0x0000 }, /* R4515 - Write Sequencer 419 */
1388 [4516] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4516 - Write Sequencer 420 */
1389 [4517] = { 0x00FF, 0x00FF, 0x0000 }, /* R4517 - Write Sequencer 421 */
1390 [4518] = { 0x070F, 0x070F, 0x0000 }, /* R4518 - Write Sequencer 422 */
1391 [4519] = { 0x010F, 0x010F, 0x0000 }, /* R4519 - Write Sequencer 423 */
1392 [4520] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4520 - Write Sequencer 424 */
1393 [4521] = { 0x00FF, 0x00FF, 0x0000 }, /* R4521 - Write Sequencer 425 */
1394 [4522] = { 0x070F, 0x070F, 0x0000 }, /* R4522 - Write Sequencer 426 */
1395 [4523] = { 0x010F, 0x010F, 0x0000 }, /* R4523 - Write Sequencer 427 */
1396 [4524] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4524 - Write Sequencer 428 */
1397 [4525] = { 0x00FF, 0x00FF, 0x0000 }, /* R4525 - Write Sequencer 429 */
1398 [4526] = { 0x070F, 0x070F, 0x0000 }, /* R4526 - Write Sequencer 430 */
1399 [4527] = { 0x010F, 0x010F, 0x0000 }, /* R4527 - Write Sequencer 431 */
1400 [4528] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4528 - Write Sequencer 432 */
1401 [4529] = { 0x00FF, 0x00FF, 0x0000 }, /* R4529 - Write Sequencer 433 */
1402 [4530] = { 0x070F, 0x070F, 0x0000 }, /* R4530 - Write Sequencer 434 */
1403 [4531] = { 0x010F, 0x010F, 0x0000 }, /* R4531 - Write Sequencer 435 */
1404 [4532] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4532 - Write Sequencer 436 */
1405 [4533] = { 0x00FF, 0x00FF, 0x0000 }, /* R4533 - Write Sequencer 437 */
1406 [4534] = { 0x070F, 0x070F, 0x0000 }, /* R4534 - Write Sequencer 438 */
1407 [4535] = { 0x010F, 0x010F, 0x0000 }, /* R4535 - Write Sequencer 439 */
1408 [4536] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4536 - Write Sequencer 440 */
1409 [4537] = { 0x00FF, 0x00FF, 0x0000 }, /* R4537 - Write Sequencer 441 */
1410 [4538] = { 0x070F, 0x070F, 0x0000 }, /* R4538 - Write Sequencer 442 */
1411 [4539] = { 0x010F, 0x010F, 0x0000 }, /* R4539 - Write Sequencer 443 */
1412 [4540] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4540 - Write Sequencer 444 */
1413 [4541] = { 0x00FF, 0x00FF, 0x0000 }, /* R4541 - Write Sequencer 445 */
1414 [4542] = { 0x070F, 0x070F, 0x0000 }, /* R4542 - Write Sequencer 446 */
1415 [4543] = { 0x010F, 0x010F, 0x0000 }, /* R4543 - Write Sequencer 447 */
1416 [4544] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4544 - Write Sequencer 448 */
1417 [4545] = { 0x00FF, 0x00FF, 0x0000 }, /* R4545 - Write Sequencer 449 */
1418 [4546] = { 0x070F, 0x070F, 0x0000 }, /* R4546 - Write Sequencer 450 */
1419 [4547] = { 0x010F, 0x010F, 0x0000 }, /* R4547 - Write Sequencer 451 */
1420 [4548] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4548 - Write Sequencer 452 */
1421 [4549] = { 0x00FF, 0x00FF, 0x0000 }, /* R4549 - Write Sequencer 453 */
1422 [4550] = { 0x070F, 0x070F, 0x0000 }, /* R4550 - Write Sequencer 454 */
1423 [4551] = { 0x010F, 0x010F, 0x0000 }, /* R4551 - Write Sequencer 455 */
1424 [4552] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4552 - Write Sequencer 456 */
1425 [4553] = { 0x00FF, 0x00FF, 0x0000 }, /* R4553 - Write Sequencer 457 */
1426 [4554] = { 0x070F, 0x070F, 0x0000 }, /* R4554 - Write Sequencer 458 */
1427 [4555] = { 0x010F, 0x010F, 0x0000 }, /* R4555 - Write Sequencer 459 */
1428 [4556] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4556 - Write Sequencer 460 */
1429 [4557] = { 0x00FF, 0x00FF, 0x0000 }, /* R4557 - Write Sequencer 461 */
1430 [4558] = { 0x070F, 0x070F, 0x0000 }, /* R4558 - Write Sequencer 462 */
1431 [4559] = { 0x010F, 0x010F, 0x0000 }, /* R4559 - Write Sequencer 463 */
1432 [4560] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4560 - Write Sequencer 464 */
1433 [4561] = { 0x00FF, 0x00FF, 0x0000 }, /* R4561 - Write Sequencer 465 */
1434 [4562] = { 0x070F, 0x070F, 0x0000 }, /* R4562 - Write Sequencer 466 */
1435 [4563] = { 0x010F, 0x010F, 0x0000 }, /* R4563 - Write Sequencer 467 */
1436 [4564] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4564 - Write Sequencer 468 */
1437 [4565] = { 0x00FF, 0x00FF, 0x0000 }, /* R4565 - Write Sequencer 469 */
1438 [4566] = { 0x070F, 0x070F, 0x0000 }, /* R4566 - Write Sequencer 470 */
1439 [4567] = { 0x010F, 0x010F, 0x0000 }, /* R4567 - Write Sequencer 471 */
1440 [4568] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4568 - Write Sequencer 472 */
1441 [4569] = { 0x00FF, 0x00FF, 0x0000 }, /* R4569 - Write Sequencer 473 */
1442 [4570] = { 0x070F, 0x070F, 0x0000 }, /* R4570 - Write Sequencer 474 */
1443 [4571] = { 0x010F, 0x010F, 0x0000 }, /* R4571 - Write Sequencer 475 */
1444 [4572] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4572 - Write Sequencer 476 */
1445 [4573] = { 0x00FF, 0x00FF, 0x0000 }, /* R4573 - Write Sequencer 477 */
1446 [4574] = { 0x070F, 0x070F, 0x0000 }, /* R4574 - Write Sequencer 478 */
1447 [4575] = { 0x010F, 0x010F, 0x0000 }, /* R4575 - Write Sequencer 479 */
1448 [4576] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4576 - Write Sequencer 480 */
1449 [4577] = { 0x00FF, 0x00FF, 0x0000 }, /* R4577 - Write Sequencer 481 */
1450 [4578] = { 0x070F, 0x070F, 0x0000 }, /* R4578 - Write Sequencer 482 */
1451 [4579] = { 0x010F, 0x010F, 0x0000 }, /* R4579 - Write Sequencer 483 */
1452 [4580] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4580 - Write Sequencer 484 */
1453 [4581] = { 0x00FF, 0x00FF, 0x0000 }, /* R4581 - Write Sequencer 485 */
1454 [4582] = { 0x070F, 0x070F, 0x0000 }, /* R4582 - Write Sequencer 486 */
1455 [4583] = { 0x010F, 0x010F, 0x0000 }, /* R4583 - Write Sequencer 487 */
1456 [4584] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4584 - Write Sequencer 488 */
1457 [4585] = { 0x00FF, 0x00FF, 0x0000 }, /* R4585 - Write Sequencer 489 */
1458 [4586] = { 0x070F, 0x070F, 0x0000 }, /* R4586 - Write Sequencer 490 */
1459 [4587] = { 0x010F, 0x010F, 0x0000 }, /* R4587 - Write Sequencer 491 */
1460 [4588] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4588 - Write Sequencer 492 */
1461 [4589] = { 0x00FF, 0x00FF, 0x0000 }, /* R4589 - Write Sequencer 493 */
1462 [4590] = { 0x070F, 0x070F, 0x0000 }, /* R4590 - Write Sequencer 494 */
1463 [4591] = { 0x010F, 0x010F, 0x0000 }, /* R4591 - Write Sequencer 495 */
1464 [4592] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4592 - Write Sequencer 496 */
1465 [4593] = { 0x00FF, 0x00FF, 0x0000 }, /* R4593 - Write Sequencer 497 */
1466 [4594] = { 0x070F, 0x070F, 0x0000 }, /* R4594 - Write Sequencer 498 */
1467 [4595] = { 0x010F, 0x010F, 0x0000 }, /* R4595 - Write Sequencer 499 */
1468 [4596] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4596 - Write Sequencer 500 */
1469 [4597] = { 0x00FF, 0x00FF, 0x0000 }, /* R4597 - Write Sequencer 501 */
1470 [4598] = { 0x070F, 0x070F, 0x0000 }, /* R4598 - Write Sequencer 502 */
1471 [4599] = { 0x010F, 0x010F, 0x0000 }, /* R4599 - Write Sequencer 503 */
1472 [4600] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4600 - Write Sequencer 504 */
1473 [4601] = { 0x00FF, 0x00FF, 0x0000 }, /* R4601 - Write Sequencer 505 */
1474 [4602] = { 0x070F, 0x070F, 0x0000 }, /* R4602 - Write Sequencer 506 */
1475 [4603] = { 0x010F, 0x010F, 0x0000 }, /* R4603 - Write Sequencer 507 */
1476 [4604] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4604 - Write Sequencer 508 */
1477 [4605] = { 0x00FF, 0x00FF, 0x0000 }, /* R4605 - Write Sequencer 509 */
1478 [4606] = { 0x070F, 0x070F, 0x0000 }, /* R4606 - Write Sequencer 510 */
1479 [4607] = { 0x010F, 0x010F, 0x0000 }, /* R4607 - Write Sequencer 511 */
1480 [8192] = { 0x03FF, 0x03FF, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */
1481 [9216] = { 0x003F, 0x003F, 0x0000 }, /* R9216 - DSP2 Address RAM 2 */
1482 [9217] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9217 - DSP2 Address RAM 1 */
1483 [9218] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9218 - DSP2 Address RAM 0 */
1484 [12288] = { 0x00FF, 0x00FF, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */
1485 [12289] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */
1486 [13312] = { 0x00FF, 0x00FF, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */
1487 [13313] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */
1488 [14336] = { 0x00FF, 0x00FF, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */
1489 [14337] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */
1490 [15360] = { 0x07FF, 0x07FF, 0x0000 }, /* R15360 - DSP2 Coeff RAM 0 */
1491 [16384] = { 0x00FF, 0x00FF, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
1492 [16385] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
1493 [16386] = { 0x00FF, 0x00FF, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
1494 [16387] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
1495 [16388] = { 0x00FF, 0x00FF, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */
1496 [16389] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */
1497 [16896] = { 0x00FF, 0x00FF, 0x0000 }, /* R16896 - HDBASS_AI_1 */
1498 [16897] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16897 - HDBASS_AI_0 */
1499 [16898] = { 0x00FF, 0x00FF, 0x0000 }, /* R16898 - HDBASS_AR_1 */
1500 [16899] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16899 - HDBASS_AR_0 */
1501 [16900] = { 0x00FF, 0x00FF, 0x0000 }, /* R16900 - HDBASS_B_1 */
1502 [16901] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16901 - HDBASS_B_0 */
1503 [16902] = { 0x00FF, 0x00FF, 0x0000 }, /* R16902 - HDBASS_K_1 */
1504 [16903] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16903 - HDBASS_K_0 */
1505 [16904] = { 0x00FF, 0x00FF, 0x0000 }, /* R16904 - HDBASS_N1_1 */
1506 [16905] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16905 - HDBASS_N1_0 */
1507 [16906] = { 0x00FF, 0x00FF, 0x0000 }, /* R16906 - HDBASS_N2_1 */
1508 [16907] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16907 - HDBASS_N2_0 */
1509 [16908] = { 0x00FF, 0x00FF, 0x0000 }, /* R16908 - HDBASS_N3_1 */
1510 [16909] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16909 - HDBASS_N3_0 */
1511 [16910] = { 0x00FF, 0x00FF, 0x0000 }, /* R16910 - HDBASS_N4_1 */
1512 [16911] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16911 - HDBASS_N4_0 */
1513 [16912] = { 0x00FF, 0x00FF, 0x0000 }, /* R16912 - HDBASS_N5_1 */
1514 [16913] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16913 - HDBASS_N5_0 */
1515 [16914] = { 0x00FF, 0x00FF, 0x0000 }, /* R16914 - HDBASS_X1_1 */
1516 [16915] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16915 - HDBASS_X1_0 */
1517 [16916] = { 0x00FF, 0x00FF, 0x0000 }, /* R16916 - HDBASS_X2_1 */
1518 [16917] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16917 - HDBASS_X2_0 */
1519 [16918] = { 0x00FF, 0x00FF, 0x0000 }, /* R16918 - HDBASS_X3_1 */
1520 [16919] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16919 - HDBASS_X3_0 */
1521 [16920] = { 0x00FF, 0x00FF, 0x0000 }, /* R16920 - HDBASS_ATK_1 */
1522 [16921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16921 - HDBASS_ATK_0 */
1523 [16922] = { 0x00FF, 0x00FF, 0x0000 }, /* R16922 - HDBASS_DCY_1 */
1524 [16923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16923 - HDBASS_DCY_0 */
1525 [16924] = { 0x00FF, 0x00FF, 0x0000 }, /* R16924 - HDBASS_PG_1 */
1526 [16925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16925 - HDBASS_PG_0 */
1527 [17408] = { 0x00FF, 0x00FF, 0x0000 }, /* R17408 - HPF_C_1 */
1528 [17409] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17409 - HPF_C_0 */
1529 [17920] = { 0x00FF, 0x00FF, 0x0000 }, /* R17920 - ADCL_RETUNE_C1_1 */
1530 [17921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17921 - ADCL_RETUNE_C1_0 */
1531 [17922] = { 0x00FF, 0x00FF, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */
1532 [17923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */
1533 [17924] = { 0x00FF, 0x00FF, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */
1534 [17925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */
1535 [17926] = { 0x00FF, 0x00FF, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */
1536 [17927] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */
1537 [17928] = { 0x00FF, 0x00FF, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */
1538 [17929] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */
1539 [17930] = { 0x00FF, 0x00FF, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */
1540 [17931] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */
1541 [17932] = { 0x00FF, 0x00FF, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */
1542 [17933] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */
1543 [17934] = { 0x00FF, 0x00FF, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */
1544 [17935] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */
1545 [17936] = { 0x00FF, 0x00FF, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */
1546 [17937] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */
1547 [17938] = { 0x00FF, 0x00FF, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */
1548 [17939] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */
1549 [17940] = { 0x00FF, 0x00FF, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */
1550 [17941] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */
1551 [17942] = { 0x00FF, 0x00FF, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */
1552 [17943] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */
1553 [17944] = { 0x00FF, 0x00FF, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */
1554 [17945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */
1555 [17946] = { 0x00FF, 0x00FF, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */
1556 [17947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */
1557 [17948] = { 0x00FF, 0x00FF, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */
1558 [17949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */
1559 [17950] = { 0x00FF, 0x00FF, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */
1560 [17951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */
1561 [17952] = { 0x00FF, 0x00FF, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */
1562 [17953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */
1563 [17954] = { 0x00FF, 0x00FF, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */
1564 [17955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */
1565 [17956] = { 0x00FF, 0x00FF, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */
1566 [17957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */
1567 [17958] = { 0x00FF, 0x00FF, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */
1568 [17959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */
1569 [17960] = { 0x00FF, 0x00FF, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */
1570 [17961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */
1571 [17962] = { 0x00FF, 0x00FF, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */
1572 [17963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */
1573 [17964] = { 0x00FF, 0x00FF, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */
1574 [17965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */
1575 [17966] = { 0x00FF, 0x00FF, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */
1576 [17967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */
1577 [17968] = { 0x00FF, 0x00FF, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */
1578 [17969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */
1579 [17970] = { 0x00FF, 0x00FF, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */
1580 [17971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */
1581 [17972] = { 0x00FF, 0x00FF, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */
1582 [17973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */
1583 [17974] = { 0x00FF, 0x00FF, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */
1584 [17975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */
1585 [17976] = { 0x00FF, 0x00FF, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */
1586 [17977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */
1587 [17978] = { 0x00FF, 0x00FF, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */
1588 [17979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */
1589 [17980] = { 0x00FF, 0x00FF, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */
1590 [17981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */
1591 [17982] = { 0x00FF, 0x00FF, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */
1592 [17983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */
1593 [18432] = { 0x00FF, 0x00FF, 0x0000 }, /* R18432 - RETUNEADC_PG2_1 */
1594 [18433] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */
1595 [18434] = { 0x00FF, 0x00FF, 0x0000 }, /* R18434 - RETUNEADC_PG_1 */
1596 [18435] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */
1597 [18944] = { 0x00FF, 0x00FF, 0x0000 }, /* R18944 - ADCR_RETUNE_C1_1 */
1598 [18945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18945 - ADCR_RETUNE_C1_0 */
1599 [18946] = { 0x00FF, 0x00FF, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */
1600 [18947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */
1601 [18948] = { 0x00FF, 0x00FF, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */
1602 [18949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */
1603 [18950] = { 0x00FF, 0x00FF, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */
1604 [18951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */
1605 [18952] = { 0x00FF, 0x00FF, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */
1606 [18953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */
1607 [18954] = { 0x00FF, 0x00FF, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */
1608 [18955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */
1609 [18956] = { 0x00FF, 0x00FF, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */
1610 [18957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */
1611 [18958] = { 0x00FF, 0x00FF, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */
1612 [18959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */
1613 [18960] = { 0x00FF, 0x00FF, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */
1614 [18961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */
1615 [18962] = { 0x00FF, 0x00FF, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */
1616 [18963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */
1617 [18964] = { 0x00FF, 0x00FF, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */
1618 [18965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */
1619 [18966] = { 0x00FF, 0x00FF, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */
1620 [18967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */
1621 [18968] = { 0x00FF, 0x00FF, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */
1622 [18969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */
1623 [18970] = { 0x00FF, 0x00FF, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */
1624 [18971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */
1625 [18972] = { 0x00FF, 0x00FF, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */
1626 [18973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */
1627 [18974] = { 0x00FF, 0x00FF, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */
1628 [18975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */
1629 [18976] = { 0x00FF, 0x00FF, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */
1630 [18977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */
1631 [18978] = { 0x00FF, 0x00FF, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */
1632 [18979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */
1633 [18980] = { 0x00FF, 0x00FF, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */
1634 [18981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */
1635 [18982] = { 0x00FF, 0x00FF, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */
1636 [18983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */
1637 [18984] = { 0x00FF, 0x00FF, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */
1638 [18985] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */
1639 [18986] = { 0x00FF, 0x00FF, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */
1640 [18987] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */
1641 [18988] = { 0x00FF, 0x00FF, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */
1642 [18989] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */
1643 [18990] = { 0x00FF, 0x00FF, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */
1644 [18991] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */
1645 [18992] = { 0x00FF, 0x00FF, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */
1646 [18993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */
1647 [18994] = { 0x00FF, 0x00FF, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */
1648 [18995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */
1649 [18996] = { 0x00FF, 0x00FF, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */
1650 [18997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */
1651 [18998] = { 0x00FF, 0x00FF, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */
1652 [18999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */
1653 [19000] = { 0x00FF, 0x00FF, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */
1654 [19001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */
1655 [19002] = { 0x00FF, 0x00FF, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */
1656 [19003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */
1657 [19004] = { 0x00FF, 0x00FF, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */
1658 [19005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */
1659 [19006] = { 0x00FF, 0x00FF, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */
1660 [19007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */
1661 [19456] = { 0x00FF, 0x00FF, 0x0000 }, /* R19456 - DACL_RETUNE_C1_1 */
1662 [19457] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19457 - DACL_RETUNE_C1_0 */
1663 [19458] = { 0x00FF, 0x00FF, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */
1664 [19459] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */
1665 [19460] = { 0x00FF, 0x00FF, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */
1666 [19461] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */
1667 [19462] = { 0x00FF, 0x00FF, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */
1668 [19463] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */
1669 [19464] = { 0x00FF, 0x00FF, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */
1670 [19465] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */
1671 [19466] = { 0x00FF, 0x00FF, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */
1672 [19467] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */
1673 [19468] = { 0x00FF, 0x00FF, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */
1674 [19469] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */
1675 [19470] = { 0x00FF, 0x00FF, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */
1676 [19471] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */
1677 [19472] = { 0x00FF, 0x00FF, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */
1678 [19473] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */
1679 [19474] = { 0x00FF, 0x00FF, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */
1680 [19475] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */
1681 [19476] = { 0x00FF, 0x00FF, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */
1682 [19477] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */
1683 [19478] = { 0x00FF, 0x00FF, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */
1684 [19479] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */
1685 [19480] = { 0x00FF, 0x00FF, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */
1686 [19481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */
1687 [19482] = { 0x00FF, 0x00FF, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */
1688 [19483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */
1689 [19484] = { 0x00FF, 0x00FF, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */
1690 [19485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */
1691 [19486] = { 0x00FF, 0x00FF, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */
1692 [19487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */
1693 [19488] = { 0x00FF, 0x00FF, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */
1694 [19489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */
1695 [19490] = { 0x00FF, 0x00FF, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */
1696 [19491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */
1697 [19492] = { 0x00FF, 0x00FF, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */
1698 [19493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */
1699 [19494] = { 0x00FF, 0x00FF, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */
1700 [19495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */
1701 [19496] = { 0x00FF, 0x00FF, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */
1702 [19497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */
1703 [19498] = { 0x00FF, 0x00FF, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */
1704 [19499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */
1705 [19500] = { 0x00FF, 0x00FF, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */
1706 [19501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */
1707 [19502] = { 0x00FF, 0x00FF, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */
1708 [19503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */
1709 [19504] = { 0x00FF, 0x00FF, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */
1710 [19505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */
1711 [19506] = { 0x00FF, 0x00FF, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */
1712 [19507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */
1713 [19508] = { 0x00FF, 0x00FF, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */
1714 [19509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */
1715 [19510] = { 0x00FF, 0x00FF, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */
1716 [19511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */
1717 [19512] = { 0x00FF, 0x00FF, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */
1718 [19513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */
1719 [19514] = { 0x00FF, 0x00FF, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */
1720 [19515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */
1721 [19516] = { 0x00FF, 0x00FF, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */
1722 [19517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */
1723 [19518] = { 0x00FF, 0x00FF, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */
1724 [19519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */
1725 [19968] = { 0x00FF, 0x00FF, 0x0000 }, /* R19968 - RETUNEDAC_PG2_1 */
1726 [19969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */
1727 [19970] = { 0x00FF, 0x00FF, 0x0000 }, /* R19970 - RETUNEDAC_PG_1 */
1728 [19971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */
1729 [20480] = { 0x00FF, 0x00FF, 0x0000 }, /* R20480 - DACR_RETUNE_C1_1 */
1730 [20481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20481 - DACR_RETUNE_C1_0 */
1731 [20482] = { 0x00FF, 0x00FF, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */
1732 [20483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */
1733 [20484] = { 0x00FF, 0x00FF, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */
1734 [20485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */
1735 [20486] = { 0x00FF, 0x00FF, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */
1736 [20487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */
1737 [20488] = { 0x00FF, 0x00FF, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */
1738 [20489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */
1739 [20490] = { 0x00FF, 0x00FF, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */
1740 [20491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */
1741 [20492] = { 0x00FF, 0x00FF, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */
1742 [20493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */
1743 [20494] = { 0x00FF, 0x00FF, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */
1744 [20495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */
1745 [20496] = { 0x00FF, 0x00FF, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */
1746 [20497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */
1747 [20498] = { 0x00FF, 0x00FF, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */
1748 [20499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */
1749 [20500] = { 0x00FF, 0x00FF, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */
1750 [20501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */
1751 [20502] = { 0x00FF, 0x00FF, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */
1752 [20503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */
1753 [20504] = { 0x00FF, 0x00FF, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */
1754 [20505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */
1755 [20506] = { 0x00FF, 0x00FF, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */
1756 [20507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */
1757 [20508] = { 0x00FF, 0x00FF, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */
1758 [20509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */
1759 [20510] = { 0x00FF, 0x00FF, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */
1760 [20511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */
1761 [20512] = { 0x00FF, 0x00FF, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */
1762 [20513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */
1763 [20514] = { 0x00FF, 0x00FF, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */
1764 [20515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */
1765 [20516] = { 0x00FF, 0x00FF, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */
1766 [20517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */
1767 [20518] = { 0x00FF, 0x00FF, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */
1768 [20519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */
1769 [20520] = { 0x00FF, 0x00FF, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */
1770 [20521] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */
1771 [20522] = { 0x00FF, 0x00FF, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */
1772 [20523] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */
1773 [20524] = { 0x00FF, 0x00FF, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */
1774 [20525] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */
1775 [20526] = { 0x00FF, 0x00FF, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */
1776 [20527] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */
1777 [20528] = { 0x00FF, 0x00FF, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */
1778 [20529] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */
1779 [20530] = { 0x00FF, 0x00FF, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */
1780 [20531] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */
1781 [20532] = { 0x00FF, 0x00FF, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */
1782 [20533] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */
1783 [20534] = { 0x00FF, 0x00FF, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */
1784 [20535] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */
1785 [20536] = { 0x00FF, 0x00FF, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */
1786 [20537] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */
1787 [20538] = { 0x00FF, 0x00FF, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */
1788 [20539] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */
1789 [20540] = { 0x00FF, 0x00FF, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */
1790 [20541] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */
1791 [20542] = { 0x00FF, 0x00FF, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */
1792 [20543] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */
1793 [20992] = { 0x00FF, 0x00FF, 0x0000 }, /* R20992 - VSS_XHD2_1 */
1794 [20993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20993 - VSS_XHD2_0 */
1795 [20994] = { 0x00FF, 0x00FF, 0x0000 }, /* R20994 - VSS_XHD3_1 */
1796 [20995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20995 - VSS_XHD3_0 */
1797 [20996] = { 0x00FF, 0x00FF, 0x0000 }, /* R20996 - VSS_XHN1_1 */
1798 [20997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20997 - VSS_XHN1_0 */
1799 [20998] = { 0x00FF, 0x00FF, 0x0000 }, /* R20998 - VSS_XHN2_1 */
1800 [20999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20999 - VSS_XHN2_0 */
1801 [21000] = { 0x00FF, 0x00FF, 0x0000 }, /* R21000 - VSS_XHN3_1 */
1802 [21001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21001 - VSS_XHN3_0 */
1803 [21002] = { 0x00FF, 0x00FF, 0x0000 }, /* R21002 - VSS_XLA_1 */
1804 [21003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21003 - VSS_XLA_0 */
1805 [21004] = { 0x00FF, 0x00FF, 0x0000 }, /* R21004 - VSS_XLB_1 */
1806 [21005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21005 - VSS_XLB_0 */
1807 [21006] = { 0x00FF, 0x00FF, 0x0000 }, /* R21006 - VSS_XLG_1 */
1808 [21007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21007 - VSS_XLG_0 */
1809 [21008] = { 0x00FF, 0x00FF, 0x0000 }, /* R21008 - VSS_PG2_1 */
1810 [21009] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21009 - VSS_PG2_0 */
1811 [21010] = { 0x00FF, 0x00FF, 0x0000 }, /* R21010 - VSS_PG_1 */
1812 [21011] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21011 - VSS_PG_0 */
1813 [21012] = { 0x00FF, 0x00FF, 0x0000 }, /* R21012 - VSS_XTD1_1 */
1814 [21013] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21013 - VSS_XTD1_0 */
1815 [21014] = { 0x00FF, 0x00FF, 0x0000 }, /* R21014 - VSS_XTD2_1 */
1816 [21015] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21015 - VSS_XTD2_0 */
1817 [21016] = { 0x00FF, 0x00FF, 0x0000 }, /* R21016 - VSS_XTD3_1 */
1818 [21017] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21017 - VSS_XTD3_0 */
1819 [21018] = { 0x00FF, 0x00FF, 0x0000 }, /* R21018 - VSS_XTD4_1 */
1820 [21019] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21019 - VSS_XTD4_0 */
1821 [21020] = { 0x00FF, 0x00FF, 0x0000 }, /* R21020 - VSS_XTD5_1 */
1822 [21021] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21021 - VSS_XTD5_0 */
1823 [21022] = { 0x00FF, 0x00FF, 0x0000 }, /* R21022 - VSS_XTD6_1 */
1824 [21023] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21023 - VSS_XTD6_0 */
1825 [21024] = { 0x00FF, 0x00FF, 0x0000 }, /* R21024 - VSS_XTD7_1 */
1826 [21025] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21025 - VSS_XTD7_0 */
1827 [21026] = { 0x00FF, 0x00FF, 0x0000 }, /* R21026 - VSS_XTD8_1 */
1828 [21027] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21027 - VSS_XTD8_0 */
1829 [21028] = { 0x00FF, 0x00FF, 0x0000 }, /* R21028 - VSS_XTD9_1 */
1830 [21029] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21029 - VSS_XTD9_0 */
1831 [21030] = { 0x00FF, 0x00FF, 0x0000 }, /* R21030 - VSS_XTD10_1 */
1832 [21031] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21031 - VSS_XTD10_0 */
1833 [21032] = { 0x00FF, 0x00FF, 0x0000 }, /* R21032 - VSS_XTD11_1 */
1834 [21033] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21033 - VSS_XTD11_0 */
1835 [21034] = { 0x00FF, 0x00FF, 0x0000 }, /* R21034 - VSS_XTD12_1 */
1836 [21035] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21035 - VSS_XTD12_0 */
1837 [21036] = { 0x00FF, 0x00FF, 0x0000 }, /* R21036 - VSS_XTD13_1 */
1838 [21037] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21037 - VSS_XTD13_0 */
1839 [21038] = { 0x00FF, 0x00FF, 0x0000 }, /* R21038 - VSS_XTD14_1 */
1840 [21039] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21039 - VSS_XTD14_0 */
1841 [21040] = { 0x00FF, 0x00FF, 0x0000 }, /* R21040 - VSS_XTD15_1 */
1842 [21041] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21041 - VSS_XTD15_0 */
1843 [21042] = { 0x00FF, 0x00FF, 0x0000 }, /* R21042 - VSS_XTD16_1 */
1844 [21043] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21043 - VSS_XTD16_0 */
1845 [21044] = { 0x00FF, 0x00FF, 0x0000 }, /* R21044 - VSS_XTD17_1 */
1846 [21045] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21045 - VSS_XTD17_0 */
1847 [21046] = { 0x00FF, 0x00FF, 0x0000 }, /* R21046 - VSS_XTD18_1 */
1848 [21047] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21047 - VSS_XTD18_0 */
1849 [21048] = { 0x00FF, 0x00FF, 0x0000 }, /* R21048 - VSS_XTD19_1 */
1850 [21049] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21049 - VSS_XTD19_0 */
1851 [21050] = { 0x00FF, 0x00FF, 0x0000 }, /* R21050 - VSS_XTD20_1 */
1852 [21051] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21051 - VSS_XTD20_0 */
1853 [21052] = { 0x00FF, 0x00FF, 0x0000 }, /* R21052 - VSS_XTD21_1 */
1854 [21053] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21053 - VSS_XTD21_0 */
1855 [21054] = { 0x00FF, 0x00FF, 0x0000 }, /* R21054 - VSS_XTD22_1 */
1856 [21055] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21055 - VSS_XTD22_0 */
1857 [21056] = { 0x00FF, 0x00FF, 0x0000 }, /* R21056 - VSS_XTD23_1 */
1858 [21057] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21057 - VSS_XTD23_0 */
1859 [21058] = { 0x00FF, 0x00FF, 0x0000 }, /* R21058 - VSS_XTD24_1 */
1860 [21059] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21059 - VSS_XTD24_0 */
1861 [21060] = { 0x00FF, 0x00FF, 0x0000 }, /* R21060 - VSS_XTD25_1 */
1862 [21061] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21061 - VSS_XTD25_0 */
1863 [21062] = { 0x00FF, 0x00FF, 0x0000 }, /* R21062 - VSS_XTD26_1 */
1864 [21063] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21063 - VSS_XTD26_0 */
1865 [21064] = { 0x00FF, 0x00FF, 0x0000 }, /* R21064 - VSS_XTD27_1 */
1866 [21065] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21065 - VSS_XTD27_0 */
1867 [21066] = { 0x00FF, 0x00FF, 0x0000 }, /* R21066 - VSS_XTD28_1 */
1868 [21067] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21067 - VSS_XTD28_0 */
1869 [21068] = { 0x00FF, 0x00FF, 0x0000 }, /* R21068 - VSS_XTD29_1 */
1870 [21069] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21069 - VSS_XTD29_0 */
1871 [21070] = { 0x00FF, 0x00FF, 0x0000 }, /* R21070 - VSS_XTD30_1 */
1872 [21071] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21071 - VSS_XTD30_0 */
1873 [21072] = { 0x00FF, 0x00FF, 0x0000 }, /* R21072 - VSS_XTD31_1 */
1874 [21073] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21073 - VSS_XTD31_0 */
1875 [21074] = { 0x00FF, 0x00FF, 0x0000 }, /* R21074 - VSS_XTD32_1 */
1876 [21075] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21075 - VSS_XTD32_0 */
1877 [21076] = { 0x00FF, 0x00FF, 0x0000 }, /* R21076 - VSS_XTS1_1 */
1878 [21077] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21077 - VSS_XTS1_0 */
1879 [21078] = { 0x00FF, 0x00FF, 0x0000 }, /* R21078 - VSS_XTS2_1 */
1880 [21079] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21079 - VSS_XTS2_0 */
1881 [21080] = { 0x00FF, 0x00FF, 0x0000 }, /* R21080 - VSS_XTS3_1 */
1882 [21081] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21081 - VSS_XTS3_0 */
1883 [21082] = { 0x00FF, 0x00FF, 0x0000 }, /* R21082 - VSS_XTS4_1 */
1884 [21083] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21083 - VSS_XTS4_0 */
1885 [21084] = { 0x00FF, 0x00FF, 0x0000 }, /* R21084 - VSS_XTS5_1 */
1886 [21085] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21085 - VSS_XTS5_0 */
1887 [21086] = { 0x00FF, 0x00FF, 0x0000 }, /* R21086 - VSS_XTS6_1 */
1888 [21087] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21087 - VSS_XTS6_0 */
1889 [21088] = { 0x00FF, 0x00FF, 0x0000 }, /* R21088 - VSS_XTS7_1 */
1890 [21089] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21089 - VSS_XTS7_0 */
1891 [21090] = { 0x00FF, 0x00FF, 0x0000 }, /* R21090 - VSS_XTS8_1 */
1892 [21091] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21091 - VSS_XTS8_0 */
1893 [21092] = { 0x00FF, 0x00FF, 0x0000 }, /* R21092 - VSS_XTS9_1 */
1894 [21093] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21093 - VSS_XTS9_0 */
1895 [21094] = { 0x00FF, 0x00FF, 0x0000 }, /* R21094 - VSS_XTS10_1 */
1896 [21095] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21095 - VSS_XTS10_0 */
1897 [21096] = { 0x00FF, 0x00FF, 0x0000 }, /* R21096 - VSS_XTS11_1 */
1898 [21097] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21097 - VSS_XTS11_0 */
1899 [21098] = { 0x00FF, 0x00FF, 0x0000 }, /* R21098 - VSS_XTS12_1 */
1900 [21099] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21099 - VSS_XTS12_0 */
1901 [21100] = { 0x00FF, 0x00FF, 0x0000 }, /* R21100 - VSS_XTS13_1 */
1902 [21101] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21101 - VSS_XTS13_0 */
1903 [21102] = { 0x00FF, 0x00FF, 0x0000 }, /* R21102 - VSS_XTS14_1 */
1904 [21103] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21103 - VSS_XTS14_0 */
1905 [21104] = { 0x00FF, 0x00FF, 0x0000 }, /* R21104 - VSS_XTS15_1 */
1906 [21105] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21105 - VSS_XTS15_0 */
1907 [21106] = { 0x00FF, 0x00FF, 0x0000 }, /* R21106 - VSS_XTS16_1 */
1908 [21107] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21107 - VSS_XTS16_0 */
1909 [21108] = { 0x00FF, 0x00FF, 0x0000 }, /* R21108 - VSS_XTS17_1 */
1910 [21109] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21109 - VSS_XTS17_0 */
1911 [21110] = { 0x00FF, 0x00FF, 0x0000 }, /* R21110 - VSS_XTS18_1 */
1912 [21111] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21111 - VSS_XTS18_0 */
1913 [21112] = { 0x00FF, 0x00FF, 0x0000 }, /* R21112 - VSS_XTS19_1 */
1914 [21113] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21113 - VSS_XTS19_0 */
1915 [21114] = { 0x00FF, 0x00FF, 0x0000 }, /* R21114 - VSS_XTS20_1 */
1916 [21115] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21115 - VSS_XTS20_0 */
1917 [21116] = { 0x00FF, 0x00FF, 0x0000 }, /* R21116 - VSS_XTS21_1 */
1918 [21117] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21117 - VSS_XTS21_0 */
1919 [21118] = { 0x00FF, 0x00FF, 0x0000 }, /* R21118 - VSS_XTS22_1 */
1920 [21119] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21119 - VSS_XTS22_0 */
1921 [21120] = { 0x00FF, 0x00FF, 0x0000 }, /* R21120 - VSS_XTS23_1 */
1922 [21121] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21121 - VSS_XTS23_0 */
1923 [21122] = { 0x00FF, 0x00FF, 0x0000 }, /* R21122 - VSS_XTS24_1 */
1924 [21123] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21123 - VSS_XTS24_0 */
1925 [21124] = { 0x00FF, 0x00FF, 0x0000 }, /* R21124 - VSS_XTS25_1 */
1926 [21125] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21125 - VSS_XTS25_0 */
1927 [21126] = { 0x00FF, 0x00FF, 0x0000 }, /* R21126 - VSS_XTS26_1 */
1928 [21127] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21127 - VSS_XTS26_0 */
1929 [21128] = { 0x00FF, 0x00FF, 0x0000 }, /* R21128 - VSS_XTS27_1 */
1930 [21129] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21129 - VSS_XTS27_0 */
1931 [21130] = { 0x00FF, 0x00FF, 0x0000 }, /* R21130 - VSS_XTS28_1 */
1932 [21131] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21131 - VSS_XTS28_0 */
1933 [21132] = { 0x00FF, 0x00FF, 0x0000 }, /* R21132 - VSS_XTS29_1 */
1934 [21133] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21133 - VSS_XTS29_0 */
1935 [21134] = { 0x00FF, 0x00FF, 0x0000 }, /* R21134 - VSS_XTS30_1 */
1936 [21135] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21135 - VSS_XTS30_0 */
1937 [21136] = { 0x00FF, 0x00FF, 0x0000 }, /* R21136 - VSS_XTS31_1 */
1938 [21137] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21137 - VSS_XTS31_0 */
1939 [21138] = { 0x00FF, 0x00FF, 0x0000 }, /* R21138 - VSS_XTS32_1 */
1940 [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
1941};
1942
1943static int wm8962_volatile_register(unsigned int reg)
1944{
1945 if (wm8962_reg_access[reg].vol)
1946 return 1;
1947 else
1948 return 0;
1949}
1950
1951static int wm8962_readable_register(unsigned int reg)
1952{
1953 if (wm8962_reg_access[reg].read)
1954 return 1;
1955 else
1956 return 0;
1957}
1958
1959static int wm8962_reset(struct snd_soc_codec *codec)
1960{
1961 return snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0);
1962}
1963
1964static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
1965static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0);
1966static const unsigned int mixinpga_tlv[] = {
1967 TLV_DB_RANGE_HEAD(7),
1968 0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
1969 2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0),
1970 3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0),
1971 5, 5, TLV_DB_SCALE_ITEM(2400, 0, 0),
1972 6, 7, TLV_DB_SCALE_ITEM(2700, 300, 0),
1973};
1974static const DECLARE_TLV_DB_SCALE(beep_tlv, -9600, 600, 1);
1975static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
1976static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
1977static const DECLARE_TLV_DB_SCALE(inmix_tlv, -600, 600, 0);
1978static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
1979static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
1980static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0);
1981static const unsigned int classd_tlv[] = {
1982 TLV_DB_RANGE_HEAD(7),
1983 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
1984 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
1985};
1986
1987/* The VU bits for the headphones are in a different register to the mute
1988 * bits and only take effect on the PGA if it is actually powered.
1989 */
1990static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
1991 struct snd_ctl_elem_value *ucontrol)
1992{
1993 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1994 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
1995 u16 *reg_cache = wm8962->reg_cache;
1996 int ret;
1997
1998 /* Apply the update (if any) */
1999 ret = snd_soc_put_volsw(kcontrol, ucontrol);
2000 if (ret == 0)
2001 return 0;
2002
2003 /* If the left PGA is enabled hit that VU bit... */
2004 if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA)
2005 return snd_soc_write(codec, WM8962_HPOUTL_VOLUME,
2006 reg_cache[WM8962_HPOUTL_VOLUME]);
2007
2008 /* ...otherwise the right. The VU is stereo. */
2009 if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA)
2010 return snd_soc_write(codec, WM8962_HPOUTR_VOLUME,
2011 reg_cache[WM8962_HPOUTR_VOLUME]);
2012
2013 return 0;
2014}
2015
2016/* The VU bits for the speakers are in a different register to the mute
2017 * bits and only take effect on the PGA if it is actually powered.
2018 */
2019static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
2020 struct snd_ctl_elem_value *ucontrol)
2021{
2022 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2023 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2024 u16 *reg_cache = wm8962->reg_cache;
2025 int ret;
2026
2027 /* Apply the update (if any) */
2028 ret = snd_soc_put_volsw(kcontrol, ucontrol);
2029 if (ret == 0)
2030 return 0;
2031
2032 /* If the left PGA is enabled hit that VU bit... */
2033 if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
2034 return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
2035 reg_cache[WM8962_SPKOUTL_VOLUME]);
2036
2037 /* ...otherwise the right. The VU is stereo. */
2038 if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
2039 return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
2040 reg_cache[WM8962_SPKOUTR_VOLUME]);
2041
2042 return 0;
2043}
2044
2045static const struct snd_kcontrol_new wm8962_snd_controls[] = {
2046SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1),
2047
2048SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 6, 7, 0,
2049 mixin_tlv),
2050SOC_SINGLE_TLV("MIXINL PGA Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 3, 7, 0,
2051 mixinpga_tlv),
2052SOC_SINGLE_TLV("MIXINL IN3L Volume", WM8962_LEFT_INPUT_MIXER_VOLUME, 0, 7, 0,
2053 mixin_tlv),
2054
2055SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 6, 7, 0,
2056 mixin_tlv),
2057SOC_SINGLE_TLV("MIXINR PGA Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 3, 7, 0,
2058 mixinpga_tlv),
2059SOC_SINGLE_TLV("MIXINR IN3R Volume", WM8962_RIGHT_INPUT_MIXER_VOLUME, 0, 7, 0,
2060 mixin_tlv),
2061
2062SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8962_LEFT_ADC_VOLUME,
2063 WM8962_RIGHT_ADC_VOLUME, 1, 127, 0, digital_tlv),
2064SOC_DOUBLE_R_TLV("Capture Volume", WM8962_LEFT_INPUT_VOLUME,
2065 WM8962_RIGHT_INPUT_VOLUME, 0, 63, 0, inpga_tlv),
2066SOC_DOUBLE_R("Capture Switch", WM8962_LEFT_INPUT_VOLUME,
2067 WM8962_RIGHT_INPUT_VOLUME, 7, 1, 1),
2068SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME,
2069 WM8962_RIGHT_INPUT_VOLUME, 6, 1, 1),
2070
2071SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
2072 WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv),
2073
2074SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME,
2075 WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv),
2076SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0),
2077
2078SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1,
2079 5, 1, 0),
2080
2081SOC_SINGLE_TLV("Beep Volume", WM8962_BEEP_GENERATOR_1, 4, 15, 0, beep_tlv),
2082
2083SOC_DOUBLE_R_TLV("Headphone Volume", WM8962_HPOUTL_VOLUME,
2084 WM8962_HPOUTR_VOLUME, 0, 127, 0, out_tlv),
2085SOC_DOUBLE_EXT("Headphone Switch", WM8962_PWR_MGMT_2, 1, 0, 1, 1,
2086 snd_soc_get_volsw, wm8962_put_hp_sw),
2087SOC_DOUBLE_R("Headphone ZC Switch", WM8962_HPOUTL_VOLUME, WM8962_HPOUTR_VOLUME,
2088 7, 1, 0),
2089SOC_DOUBLE_TLV("Headphone Aux Volume", WM8962_ANALOGUE_HP_2, 3, 6, 7, 0,
2090 hp_tlv),
2091
2092SOC_DOUBLE_R("Headphone Mixer Switch", WM8962_HEADPHONE_MIXER_3,
2093 WM8962_HEADPHONE_MIXER_4, 8, 1, 1),
2094
2095SOC_SINGLE_TLV("HPMIXL IN4L Volume", WM8962_HEADPHONE_MIXER_3,
2096 3, 7, 0, bypass_tlv),
2097SOC_SINGLE_TLV("HPMIXL IN4R Volume", WM8962_HEADPHONE_MIXER_3,
2098 0, 7, 0, bypass_tlv),
2099SOC_SINGLE_TLV("HPMIXL MIXINL Volume", WM8962_HEADPHONE_MIXER_3,
2100 7, 1, 1, inmix_tlv),
2101SOC_SINGLE_TLV("HPMIXL MIXINR Volume", WM8962_HEADPHONE_MIXER_3,
2102 6, 1, 1, inmix_tlv),
2103
2104SOC_SINGLE_TLV("HPMIXR IN4L Volume", WM8962_HEADPHONE_MIXER_4,
2105 3, 7, 0, bypass_tlv),
2106SOC_SINGLE_TLV("HPMIXR IN4R Volume", WM8962_HEADPHONE_MIXER_4,
2107 0, 7, 0, bypass_tlv),
2108SOC_SINGLE_TLV("HPMIXR MIXINL Volume", WM8962_HEADPHONE_MIXER_4,
2109 7, 1, 1, inmix_tlv),
2110SOC_SINGLE_TLV("HPMIXR MIXINR Volume", WM8962_HEADPHONE_MIXER_4,
2111 6, 1, 1, inmix_tlv),
2112
2113SOC_SINGLE_TLV("Speaker Boost Volume", WM8962_CLASS_D_CONTROL_2, 0, 7, 0,
2114 classd_tlv),
2115};
2116
2117static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
2118SOC_SINGLE_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME, 0, 127, 0, out_tlv),
2119SOC_SINGLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 1, 1,
2120 snd_soc_get_volsw, wm8962_put_spk_sw),
2121SOC_SINGLE("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, 7, 1, 0),
2122
2123SOC_SINGLE("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3, 8, 1, 1),
2124SOC_SINGLE_TLV("Speaker Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3,
2125 3, 7, 0, bypass_tlv),
2126SOC_SINGLE_TLV("Speaker Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3,
2127 0, 7, 0, bypass_tlv),
2128SOC_SINGLE_TLV("Speaker Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3,
2129 7, 1, 1, inmix_tlv),
2130SOC_SINGLE_TLV("Speaker Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3,
2131 6, 1, 1, inmix_tlv),
2132SOC_SINGLE_TLV("Speaker Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
2133 7, 1, 0, inmix_tlv),
2134SOC_SINGLE_TLV("Speaker Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
2135 6, 1, 0, inmix_tlv),
2136};
2137
2138static const struct snd_kcontrol_new wm8962_spk_stereo_controls[] = {
2139SOC_DOUBLE_R_TLV("Speaker Volume", WM8962_SPKOUTL_VOLUME,
2140 WM8962_SPKOUTR_VOLUME, 0, 127, 0, out_tlv),
2141SOC_DOUBLE_EXT("Speaker Switch", WM8962_CLASS_D_CONTROL_1, 1, 0, 1, 1,
2142 snd_soc_get_volsw, wm8962_put_spk_sw),
2143SOC_DOUBLE_R("Speaker ZC Switch", WM8962_SPKOUTL_VOLUME, WM8962_SPKOUTR_VOLUME,
2144 7, 1, 0),
2145
2146SOC_DOUBLE_R("Speaker Mixer Switch", WM8962_SPEAKER_MIXER_3,
2147 WM8962_SPEAKER_MIXER_4, 8, 1, 1),
2148
2149SOC_SINGLE_TLV("SPKOUTL Mixer IN4L Volume", WM8962_SPEAKER_MIXER_3,
2150 3, 7, 0, bypass_tlv),
2151SOC_SINGLE_TLV("SPKOUTL Mixer IN4R Volume", WM8962_SPEAKER_MIXER_3,
2152 0, 7, 0, bypass_tlv),
2153SOC_SINGLE_TLV("SPKOUTL Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_3,
2154 7, 1, 1, inmix_tlv),
2155SOC_SINGLE_TLV("SPKOUTL Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_3,
2156 6, 1, 1, inmix_tlv),
2157SOC_SINGLE_TLV("SPKOUTL Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
2158 7, 1, 0, inmix_tlv),
2159SOC_SINGLE_TLV("SPKOUTL Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
2160 6, 1, 0, inmix_tlv),
2161
2162SOC_SINGLE_TLV("SPKOUTR Mixer IN4L Volume", WM8962_SPEAKER_MIXER_4,
2163 3, 7, 0, bypass_tlv),
2164SOC_SINGLE_TLV("SPKOUTR Mixer IN4R Volume", WM8962_SPEAKER_MIXER_4,
2165 0, 7, 0, bypass_tlv),
2166SOC_SINGLE_TLV("SPKOUTR Mixer MIXINL Volume", WM8962_SPEAKER_MIXER_4,
2167 7, 1, 1, inmix_tlv),
2168SOC_SINGLE_TLV("SPKOUTR Mixer MIXINR Volume", WM8962_SPEAKER_MIXER_4,
2169 6, 1, 1, inmix_tlv),
2170SOC_SINGLE_TLV("SPKOUTR Mixer DACL Volume", WM8962_SPEAKER_MIXER_5,
2171 5, 1, 0, inmix_tlv),
2172SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
2173 4, 1, 0, inmix_tlv),
2174};
2175
2176static int sysclk_event(struct snd_soc_dapm_widget *w,
2177 struct snd_kcontrol *kcontrol, int event)
2178{
2179 struct snd_soc_codec *codec = w->codec;
2180 int src;
2181 int fll;
2182
2183 src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK;
2184
2185 switch (src) {
2186 case 0: /* MCLK */
2187 fll = 0;
2188 break;
2189 case 0x200: /* FLL */
2190 fll = 1;
2191 break;
2192 default:
2193 dev_err(codec->dev, "Unknown SYSCLK source %x\n", src);
2194 return -EINVAL;
2195 }
2196
2197 switch (event) {
2198 case SND_SOC_DAPM_PRE_PMU:
2199 if (fll)
2200 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
2201 WM8962_FLL_ENA, WM8962_FLL_ENA);
2202 break;
2203
2204 case SND_SOC_DAPM_POST_PMD:
2205 if (fll)
2206 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
2207 WM8962_FLL_ENA, 0);
2208 break;
2209
2210 default:
2211 BUG();
2212 return -EINVAL;
2213 }
2214
2215 return 0;
2216}
2217
2218static int cp_event(struct snd_soc_dapm_widget *w,
2219 struct snd_kcontrol *kcontrol, int event)
2220{
2221 switch (event) {
2222 case SND_SOC_DAPM_POST_PMU:
2223 msleep(5);
2224 break;
2225
2226 default:
2227 BUG();
2228 return -EINVAL;
2229 }
2230
2231 return 0;
2232}
2233
2234static int hp_event(struct snd_soc_dapm_widget *w,
2235 struct snd_kcontrol *kcontrol, int event)
2236{
2237 struct snd_soc_codec *codec = w->codec;
2238 int timeout;
2239 int reg;
2240 int expected = (WM8962_DCS_STARTUP_DONE_HP1L |
2241 WM8962_DCS_STARTUP_DONE_HP1R);
2242
2243 switch (event) {
2244 case SND_SOC_DAPM_POST_PMU:
2245 snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
2246 WM8962_HP1L_ENA | WM8962_HP1R_ENA,
2247 WM8962_HP1L_ENA | WM8962_HP1R_ENA);
2248 udelay(20);
2249
2250 snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
2251 WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY,
2252 WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY);
2253
2254 /* Start the DC servo */
2255 snd_soc_update_bits(codec, WM8962_DC_SERVO_1,
2256 WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
2257 WM8962_HP1L_DCS_STARTUP |
2258 WM8962_HP1R_DCS_STARTUP,
2259 WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
2260 WM8962_HP1L_DCS_STARTUP |
2261 WM8962_HP1R_DCS_STARTUP);
2262
2263 /* Wait for it to complete, should be well under 100ms */
2264 timeout = 0;
2265 do {
2266 msleep(1);
2267 reg = snd_soc_read(codec, WM8962_DC_SERVO_6);
2268 if (reg < 0) {
2269 dev_err(codec->dev,
2270 "Failed to read DCS status: %d\n",
2271 reg);
2272 continue;
2273 }
2274 dev_dbg(codec->dev, "DCS status: %x\n", reg);
2275 } while (++timeout < 200 && (reg & expected) != expected);
2276
2277 if ((reg & expected) != expected)
2278 dev_err(codec->dev, "DC servo timed out\n");
2279 else
2280 dev_dbg(codec->dev, "DC servo complete after %dms\n",
2281 timeout);
2282
2283 snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
2284 WM8962_HP1L_ENA_OUTP |
2285 WM8962_HP1R_ENA_OUTP,
2286 WM8962_HP1L_ENA_OUTP |
2287 WM8962_HP1R_ENA_OUTP);
2288 udelay(20);
2289
2290 snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
2291 WM8962_HP1L_RMV_SHORT |
2292 WM8962_HP1R_RMV_SHORT,
2293 WM8962_HP1L_RMV_SHORT |
2294 WM8962_HP1R_RMV_SHORT);
2295 break;
2296
2297 case SND_SOC_DAPM_PRE_PMD:
2298 snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
2299 WM8962_HP1L_RMV_SHORT |
2300 WM8962_HP1R_RMV_SHORT, 0);
2301
2302 udelay(20);
2303
2304 snd_soc_update_bits(codec, WM8962_DC_SERVO_1,
2305 WM8962_HP1L_DCS_ENA | WM8962_HP1R_DCS_ENA |
2306 WM8962_HP1L_DCS_STARTUP |
2307 WM8962_HP1R_DCS_STARTUP,
2308 0);
2309
2310 snd_soc_update_bits(codec, WM8962_ANALOGUE_HP_0,
2311 WM8962_HP1L_ENA | WM8962_HP1R_ENA |
2312 WM8962_HP1L_ENA_DLY | WM8962_HP1R_ENA_DLY |
2313 WM8962_HP1L_ENA_OUTP |
2314 WM8962_HP1R_ENA_OUTP, 0);
2315
2316 break;
2317
2318 default:
2319 BUG();
2320 return -EINVAL;
2321
2322 }
2323
2324 return 0;
2325}
2326
2327/* VU bits for the output PGAs only take effect while the PGA is powered */
2328static int out_pga_event(struct snd_soc_dapm_widget *w,
2329 struct snd_kcontrol *kcontrol, int event)
2330{
2331 struct snd_soc_codec *codec = w->codec;
2332 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2333 u16 *reg_cache = wm8962->reg_cache;
2334 int reg;
2335
2336 switch (w->shift) {
2337 case WM8962_HPOUTR_PGA_ENA_SHIFT:
2338 reg = WM8962_HPOUTR_VOLUME;
2339 break;
2340 case WM8962_HPOUTL_PGA_ENA_SHIFT:
2341 reg = WM8962_HPOUTL_VOLUME;
2342 break;
2343 case WM8962_SPKOUTR_PGA_ENA_SHIFT:
2344 reg = WM8962_SPKOUTR_VOLUME;
2345 break;
2346 case WM8962_SPKOUTL_PGA_ENA_SHIFT:
2347 reg = WM8962_SPKOUTL_VOLUME;
2348 break;
2349 default:
2350 BUG();
2351 return -EINVAL;
2352 }
2353
2354 switch (event) {
2355 case SND_SOC_DAPM_POST_PMU:
2356 return snd_soc_write(codec, reg, reg_cache[reg]);
2357 default:
2358 BUG();
2359 return -EINVAL;
2360 }
2361}
2362
2363static const char *st_text[] = { "None", "Right", "Left" };
2364
2365static const struct soc_enum str_enum =
2366 SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text);
2367
2368static const struct snd_kcontrol_new str_mux =
2369 SOC_DAPM_ENUM("Right Sidetone", str_enum);
2370
2371static const struct soc_enum stl_enum =
2372 SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_2, 2, 3, st_text);
2373
2374static const struct snd_kcontrol_new stl_mux =
2375 SOC_DAPM_ENUM("Left Sidetone", stl_enum);
2376
2377static const char *outmux_text[] = { "DAC", "Mixer" };
2378
2379static const struct soc_enum spkoutr_enum =
2380 SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_2, 7, 2, outmux_text);
2381
2382static const struct snd_kcontrol_new spkoutr_mux =
2383 SOC_DAPM_ENUM("SPKOUTR Mux", spkoutr_enum);
2384
2385static const struct soc_enum spkoutl_enum =
2386 SOC_ENUM_SINGLE(WM8962_SPEAKER_MIXER_1, 7, 2, outmux_text);
2387
2388static const struct snd_kcontrol_new spkoutl_mux =
2389 SOC_DAPM_ENUM("SPKOUTL Mux", spkoutl_enum);
2390
2391static const struct soc_enum hpoutr_enum =
2392 SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_2, 7, 2, outmux_text);
2393
2394static const struct snd_kcontrol_new hpoutr_mux =
2395 SOC_DAPM_ENUM("HPOUTR Mux", hpoutr_enum);
2396
2397static const struct soc_enum hpoutl_enum =
2398 SOC_ENUM_SINGLE(WM8962_HEADPHONE_MIXER_1, 7, 2, outmux_text);
2399
2400static const struct snd_kcontrol_new hpoutl_mux =
2401 SOC_DAPM_ENUM("HPOUTL Mux", hpoutl_enum);
2402
2403static const struct snd_kcontrol_new inpgal[] = {
2404SOC_DAPM_SINGLE("IN1L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 3, 1, 0),
2405SOC_DAPM_SINGLE("IN2L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 2, 1, 0),
2406SOC_DAPM_SINGLE("IN3L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 1, 1, 0),
2407SOC_DAPM_SINGLE("IN4L Switch", WM8962_LEFT_INPUT_PGA_CONTROL, 0, 1, 0),
2408};
2409
2410static const struct snd_kcontrol_new inpgar[] = {
2411SOC_DAPM_SINGLE("IN1R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 3, 1, 0),
2412SOC_DAPM_SINGLE("IN2R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 2, 1, 0),
2413SOC_DAPM_SINGLE("IN3R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 1, 1, 0),
2414SOC_DAPM_SINGLE("IN4R Switch", WM8962_RIGHT_INPUT_PGA_CONTROL, 0, 1, 0),
2415};
2416
2417static const struct snd_kcontrol_new mixinl[] = {
2418SOC_DAPM_SINGLE("IN2L Switch", WM8962_INPUT_MIXER_CONTROL_2, 5, 1, 0),
2419SOC_DAPM_SINGLE("IN3L Switch", WM8962_INPUT_MIXER_CONTROL_2, 4, 1, 0),
2420SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 3, 1, 0),
2421};
2422
2423static const struct snd_kcontrol_new mixinr[] = {
2424SOC_DAPM_SINGLE("IN2R Switch", WM8962_INPUT_MIXER_CONTROL_2, 2, 1, 0),
2425SOC_DAPM_SINGLE("IN3R Switch", WM8962_INPUT_MIXER_CONTROL_2, 1, 1, 0),
2426SOC_DAPM_SINGLE("PGA Switch", WM8962_INPUT_MIXER_CONTROL_2, 0, 1, 0),
2427};
2428
2429static const struct snd_kcontrol_new hpmixl[] = {
2430SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_1, 5, 1, 0),
2431SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_1, 4, 1, 0),
2432SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_1, 3, 1, 0),
2433SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_1, 2, 1, 0),
2434SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_1, 1, 1, 0),
2435SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_1, 0, 1, 0),
2436};
2437
2438static const struct snd_kcontrol_new hpmixr[] = {
2439SOC_DAPM_SINGLE("DACL Switch", WM8962_HEADPHONE_MIXER_2, 5, 1, 0),
2440SOC_DAPM_SINGLE("DACR Switch", WM8962_HEADPHONE_MIXER_2, 4, 1, 0),
2441SOC_DAPM_SINGLE("MIXINL Switch", WM8962_HEADPHONE_MIXER_2, 3, 1, 0),
2442SOC_DAPM_SINGLE("MIXINR Switch", WM8962_HEADPHONE_MIXER_2, 2, 1, 0),
2443SOC_DAPM_SINGLE("IN4L Switch", WM8962_HEADPHONE_MIXER_2, 1, 1, 0),
2444SOC_DAPM_SINGLE("IN4R Switch", WM8962_HEADPHONE_MIXER_2, 0, 1, 0),
2445};
2446
2447static const struct snd_kcontrol_new spkmixl[] = {
2448SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_1, 5, 1, 0),
2449SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_1, 4, 1, 0),
2450SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_1, 3, 1, 0),
2451SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_1, 2, 1, 0),
2452SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_1, 1, 1, 0),
2453SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_1, 0, 1, 0),
2454};
2455
2456static const struct snd_kcontrol_new spkmixr[] = {
2457SOC_DAPM_SINGLE("DACL Switch", WM8962_SPEAKER_MIXER_2, 5, 1, 0),
2458SOC_DAPM_SINGLE("DACR Switch", WM8962_SPEAKER_MIXER_2, 4, 1, 0),
2459SOC_DAPM_SINGLE("MIXINL Switch", WM8962_SPEAKER_MIXER_2, 3, 1, 0),
2460SOC_DAPM_SINGLE("MIXINR Switch", WM8962_SPEAKER_MIXER_2, 2, 1, 0),
2461SOC_DAPM_SINGLE("IN4L Switch", WM8962_SPEAKER_MIXER_2, 1, 1, 0),
2462SOC_DAPM_SINGLE("IN4R Switch", WM8962_SPEAKER_MIXER_2, 0, 1, 0),
2463};
2464
2465static const struct snd_soc_dapm_widget wm8962_dapm_widgets[] = {
2466SND_SOC_DAPM_INPUT("IN1L"),
2467SND_SOC_DAPM_INPUT("IN1R"),
2468SND_SOC_DAPM_INPUT("IN2L"),
2469SND_SOC_DAPM_INPUT("IN2R"),
2470SND_SOC_DAPM_INPUT("IN3L"),
2471SND_SOC_DAPM_INPUT("IN3R"),
2472SND_SOC_DAPM_INPUT("IN4L"),
2473SND_SOC_DAPM_INPUT("IN4R"),
2474SND_SOC_DAPM_INPUT("Beep"),
2475
2476SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0),
2477
2478SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
2479SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
2480 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
2481SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event,
2482 SND_SOC_DAPM_POST_PMU),
2483SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
2484
2485SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
2486 inpgal, ARRAY_SIZE(inpgal)),
2487SND_SOC_DAPM_MIXER("INPGAR", WM8962_RIGHT_INPUT_PGA_CONTROL, 4, 0,
2488 inpgar, ARRAY_SIZE(inpgar)),
2489SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0,
2490 mixinl, ARRAY_SIZE(mixinl)),
2491SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0,
2492 mixinr, ARRAY_SIZE(mixinr)),
2493
2494SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0),
2495SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0),
2496
2497SND_SOC_DAPM_MUX("STL", SND_SOC_NOPM, 0, 0, &stl_mux),
2498SND_SOC_DAPM_MUX("STR", SND_SOC_NOPM, 0, 0, &str_mux),
2499
2500SND_SOC_DAPM_DAC("DACL", "Playback", WM8962_PWR_MGMT_2, 8, 0),
2501SND_SOC_DAPM_DAC("DACR", "Playback", WM8962_PWR_MGMT_2, 7, 0),
2502
2503SND_SOC_DAPM_PGA("Left Bypass", SND_SOC_NOPM, 0, 0, NULL, 0),
2504SND_SOC_DAPM_PGA("Right Bypass", SND_SOC_NOPM, 0, 0, NULL, 0),
2505
2506SND_SOC_DAPM_MIXER("HPMIXL", WM8962_MIXER_ENABLES, 3, 0,
2507 hpmixl, ARRAY_SIZE(hpmixl)),
2508SND_SOC_DAPM_MIXER("HPMIXR", WM8962_MIXER_ENABLES, 2, 0,
2509 hpmixr, ARRAY_SIZE(hpmixr)),
2510
2511SND_SOC_DAPM_MUX_E("HPOUTL PGA", WM8962_PWR_MGMT_2, 6, 0, &hpoutl_mux,
2512 out_pga_event, SND_SOC_DAPM_POST_PMU),
2513SND_SOC_DAPM_MUX_E("HPOUTR PGA", WM8962_PWR_MGMT_2, 5, 0, &hpoutr_mux,
2514 out_pga_event, SND_SOC_DAPM_POST_PMU),
2515
2516SND_SOC_DAPM_PGA_E("HPOUT", SND_SOC_NOPM, 0, 0, NULL, 0, hp_event,
2517 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
2518
2519SND_SOC_DAPM_OUTPUT("HPOUTL"),
2520SND_SOC_DAPM_OUTPUT("HPOUTR"),
2521};
2522
2523static const struct snd_soc_dapm_widget wm8962_dapm_spk_mono_widgets[] = {
2524SND_SOC_DAPM_MIXER("Speaker Mixer", WM8962_MIXER_ENABLES, 1, 0,
2525 spkmixl, ARRAY_SIZE(spkmixl)),
2526SND_SOC_DAPM_MUX_E("Speaker PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
2527 out_pga_event, SND_SOC_DAPM_POST_PMU),
2528SND_SOC_DAPM_PGA("Speaker Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
2529SND_SOC_DAPM_OUTPUT("SPKOUT"),
2530};
2531
2532static const struct snd_soc_dapm_widget wm8962_dapm_spk_stereo_widgets[] = {
2533SND_SOC_DAPM_MIXER("SPKOUTL Mixer", WM8962_MIXER_ENABLES, 1, 0,
2534 spkmixl, ARRAY_SIZE(spkmixl)),
2535SND_SOC_DAPM_MIXER("SPKOUTR Mixer", WM8962_MIXER_ENABLES, 0, 0,
2536 spkmixr, ARRAY_SIZE(spkmixr)),
2537
2538SND_SOC_DAPM_MUX_E("SPKOUTL PGA", WM8962_PWR_MGMT_2, 4, 0, &spkoutl_mux,
2539 out_pga_event, SND_SOC_DAPM_POST_PMU),
2540SND_SOC_DAPM_MUX_E("SPKOUTR PGA", WM8962_PWR_MGMT_2, 3, 0, &spkoutr_mux,
2541 out_pga_event, SND_SOC_DAPM_POST_PMU),
2542
2543SND_SOC_DAPM_PGA("SPKOUTR Output", WM8962_CLASS_D_CONTROL_1, 7, 0, NULL, 0),
2544SND_SOC_DAPM_PGA("SPKOUTL Output", WM8962_CLASS_D_CONTROL_1, 6, 0, NULL, 0),
2545
2546SND_SOC_DAPM_OUTPUT("SPKOUTL"),
2547SND_SOC_DAPM_OUTPUT("SPKOUTR"),
2548};
2549
2550static const struct snd_soc_dapm_route wm8962_intercon[] = {
2551 { "INPGAL", "IN1L Switch", "IN1L" },
2552 { "INPGAL", "IN2L Switch", "IN2L" },
2553 { "INPGAL", "IN3L Switch", "IN3L" },
2554 { "INPGAL", "IN4L Switch", "IN4L" },
2555
2556 { "INPGAR", "IN1R Switch", "IN1R" },
2557 { "INPGAR", "IN2R Switch", "IN2R" },
2558 { "INPGAR", "IN3R Switch", "IN3R" },
2559 { "INPGAR", "IN4R Switch", "IN4R" },
2560
2561 { "MIXINL", "IN2L Switch", "IN2L" },
2562 { "MIXINL", "IN3L Switch", "IN3L" },
2563 { "MIXINL", "PGA Switch", "INPGAL" },
2564
2565 { "MIXINR", "IN2R Switch", "IN2R" },
2566 { "MIXINR", "IN3R Switch", "IN3R" },
2567 { "MIXINR", "PGA Switch", "INPGAR" },
2568
2569 { "MICBIAS", NULL, "SYSCLK" },
2570
2571 { "ADCL", NULL, "SYSCLK" },
2572 { "ADCL", NULL, "TOCLK" },
2573 { "ADCL", NULL, "MIXINL" },
2574
2575 { "ADCR", NULL, "SYSCLK" },
2576 { "ADCR", NULL, "TOCLK" },
2577 { "ADCR", NULL, "MIXINR" },
2578
2579 { "STL", "Left", "ADCL" },
2580 { "STL", "Right", "ADCR" },
2581
2582 { "STR", "Left", "ADCL" },
2583 { "STR", "Right", "ADCR" },
2584
2585 { "DACL", NULL, "SYSCLK" },
2586 { "DACL", NULL, "TOCLK" },
2587 { "DACL", NULL, "Beep" },
2588 { "DACL", NULL, "STL" },
2589
2590 { "DACR", NULL, "SYSCLK" },
2591 { "DACR", NULL, "TOCLK" },
2592 { "DACR", NULL, "Beep" },
2593 { "DACR", NULL, "STR" },
2594
2595 { "HPMIXL", "IN4L Switch", "IN4L" },
2596 { "HPMIXL", "IN4R Switch", "IN4R" },
2597 { "HPMIXL", "DACL Switch", "DACL" },
2598 { "HPMIXL", "DACR Switch", "DACR" },
2599 { "HPMIXL", "MIXINL Switch", "MIXINL" },
2600 { "HPMIXL", "MIXINR Switch", "MIXINR" },
2601
2602 { "HPMIXR", "IN4L Switch", "IN4L" },
2603 { "HPMIXR", "IN4R Switch", "IN4R" },
2604 { "HPMIXR", "DACL Switch", "DACL" },
2605 { "HPMIXR", "DACR Switch", "DACR" },
2606 { "HPMIXR", "MIXINL Switch", "MIXINL" },
2607 { "HPMIXR", "MIXINR Switch", "MIXINR" },
2608
2609 { "Left Bypass", NULL, "HPMIXL" },
2610 { "Left Bypass", NULL, "Class G" },
2611
2612 { "Right Bypass", NULL, "HPMIXR" },
2613 { "Right Bypass", NULL, "Class G" },
2614
2615 { "HPOUTL PGA", "Mixer", "Left Bypass" },
2616 { "HPOUTL PGA", "DAC", "DACL" },
2617
2618 { "HPOUTR PGA", "Mixer", "Right Bypass" },
2619 { "HPOUTR PGA", "DAC", "DACR" },
2620
2621 { "HPOUT", NULL, "HPOUTL PGA" },
2622 { "HPOUT", NULL, "HPOUTR PGA" },
2623 { "HPOUT", NULL, "Charge Pump" },
2624 { "HPOUT", NULL, "SYSCLK" },
2625 { "HPOUT", NULL, "TOCLK" },
2626
2627 { "HPOUTL", NULL, "HPOUT" },
2628 { "HPOUTR", NULL, "HPOUT" },
2629};
2630
2631static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
2632 { "Speaker Mixer", "IN4L Switch", "IN4L" },
2633 { "Speaker Mixer", "IN4R Switch", "IN4R" },
2634 { "Speaker Mixer", "DACL Switch", "DACL" },
2635 { "Speaker Mixer", "DACR Switch", "DACR" },
2636 { "Speaker Mixer", "MIXINL Switch", "MIXINL" },
2637 { "Speaker Mixer", "MIXINR Switch", "MIXINR" },
2638
2639 { "Speaker PGA", "Mixer", "Speaker Mixer" },
2640 { "Speaker PGA", "DAC", "DACL" },
2641
2642 { "Speaker Output", NULL, "Speaker PGA" },
2643 { "Speaker Output", NULL, "SYSCLK" },
2644 { "Speaker Output", NULL, "TOCLK" },
2645
2646 { "SPKOUT", NULL, "Speaker Output" },
2647};
2648
2649static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = {
2650 { "SPKOUTL Mixer", "IN4L Switch", "IN4L" },
2651 { "SPKOUTL Mixer", "IN4R Switch", "IN4R" },
2652 { "SPKOUTL Mixer", "DACL Switch", "DACL" },
2653 { "SPKOUTL Mixer", "DACR Switch", "DACR" },
2654 { "SPKOUTL Mixer", "MIXINL Switch", "MIXINL" },
2655 { "SPKOUTL Mixer", "MIXINR Switch", "MIXINR" },
2656
2657 { "SPKOUTR Mixer", "IN4L Switch", "IN4L" },
2658 { "SPKOUTR Mixer", "IN4R Switch", "IN4R" },
2659 { "SPKOUTR Mixer", "DACL Switch", "DACL" },
2660 { "SPKOUTR Mixer", "DACR Switch", "DACR" },
2661 { "SPKOUTR Mixer", "MIXINL Switch", "MIXINL" },
2662 { "SPKOUTR Mixer", "MIXINR Switch", "MIXINR" },
2663
2664 { "SPKOUTL PGA", "Mixer", "SPKOUTL Mixer" },
2665 { "SPKOUTL PGA", "DAC", "DACL" },
2666
2667 { "SPKOUTR PGA", "Mixer", "SPKOUTR Mixer" },
2668 { "SPKOUTR PGA", "DAC", "DACR" },
2669
2670 { "SPKOUTL Output", NULL, "SPKOUTL PGA" },
2671 { "SPKOUTL Output", NULL, "SYSCLK" },
2672 { "SPKOUTL Output", NULL, "TOCLK" },
2673
2674 { "SPKOUTR Output", NULL, "SPKOUTR PGA" },
2675 { "SPKOUTR Output", NULL, "SYSCLK" },
2676 { "SPKOUTR Output", NULL, "TOCLK" },
2677
2678 { "SPKOUTL", NULL, "SPKOUTL Output" },
2679 { "SPKOUTR", NULL, "SPKOUTR Output" },
2680};
2681
2682static int wm8962_add_widgets(struct snd_soc_codec *codec)
2683{
2684 struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
2685
2686 snd_soc_add_controls(codec, wm8962_snd_controls,
2687 ARRAY_SIZE(wm8962_snd_controls));
2688 if (pdata && pdata->spk_mono)
2689 snd_soc_add_controls(codec, wm8962_spk_mono_controls,
2690 ARRAY_SIZE(wm8962_spk_mono_controls));
2691 else
2692 snd_soc_add_controls(codec, wm8962_spk_stereo_controls,
2693 ARRAY_SIZE(wm8962_spk_stereo_controls));
2694
2695
2696 snd_soc_dapm_new_controls(codec, wm8962_dapm_widgets,
2697 ARRAY_SIZE(wm8962_dapm_widgets));
2698 if (pdata && pdata->spk_mono)
2699 snd_soc_dapm_new_controls(codec, wm8962_dapm_spk_mono_widgets,
2700 ARRAY_SIZE(wm8962_dapm_spk_mono_widgets));
2701 else
2702 snd_soc_dapm_new_controls(codec, wm8962_dapm_spk_stereo_widgets,
2703 ARRAY_SIZE(wm8962_dapm_spk_stereo_widgets));
2704
2705 snd_soc_dapm_add_routes(codec, wm8962_intercon,
2706 ARRAY_SIZE(wm8962_intercon));
2707 if (pdata && pdata->spk_mono)
2708 snd_soc_dapm_add_routes(codec, wm8962_spk_mono_intercon,
2709 ARRAY_SIZE(wm8962_spk_mono_intercon));
2710 else
2711 snd_soc_dapm_add_routes(codec, wm8962_spk_stereo_intercon,
2712 ARRAY_SIZE(wm8962_spk_stereo_intercon));
2713
2714
2715 snd_soc_dapm_disable_pin(codec, "Beep");
2716
2717 return 0;
2718}
2719
2720static void wm8962_sync_cache(struct snd_soc_codec *codec)
2721{
2722 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2723 int i;
2724
2725 if (!codec->cache_sync)
2726 return;
2727
2728 dev_dbg(codec->dev, "Syncing cache\n");
2729
2730 codec->cache_only = 0;
2731
2732 /* Sync back cached values if they're different from the
2733 * hardware default.
2734 */
2735 for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
2736 if (i == WM8962_SOFTWARE_RESET)
2737 continue;
2738 if (wm8962->reg_cache[i] == wm8962_reg[i])
2739 continue;
2740
2741 snd_soc_write(codec, i, wm8962->reg_cache[i]);
2742 }
2743
2744 codec->cache_sync = 0;
2745}
2746
2747/* -1 for reserved values */
2748static const int bclk_divs[] = {
2749 1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
2750};
2751
2752static void wm8962_configure_bclk(struct snd_soc_codec *codec)
2753{
2754 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2755 int dspclk, i;
2756 int clocking2 = 0;
2757 int aif2 = 0;
2758
2759 if (!wm8962->bclk) {
2760 dev_dbg(codec->dev, "No BCLK rate configured\n");
2761 return;
2762 }
2763
2764 dspclk = snd_soc_read(codec, WM8962_CLOCKING1);
2765 if (dspclk < 0) {
2766 dev_err(codec->dev, "Failed to read DSPCLK: %d\n", dspclk);
2767 return;
2768 }
2769
2770 dspclk = (dspclk & WM8962_DSPCLK_DIV_MASK) >> WM8962_DSPCLK_DIV_SHIFT;
2771 switch (dspclk) {
2772 case 0:
2773 dspclk = wm8962->sysclk_rate;
2774 break;
2775 case 1:
2776 dspclk = wm8962->sysclk_rate / 2;
2777 break;
2778 case 2:
2779 dspclk = wm8962->sysclk_rate / 4;
2780 break;
2781 default:
2782 dev_warn(codec->dev, "Unknown DSPCLK divisor read back\n");
2783 dspclk = wm8962->sysclk;
2784 }
2785
2786 dev_dbg(codec->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk);
2787
2788 /* We're expecting an exact match */
2789 for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) {
2790 if (bclk_divs[i] < 0)
2791 continue;
2792
2793 if (dspclk / bclk_divs[i] == wm8962->bclk) {
2794 dev_dbg(codec->dev, "Selected BCLK_DIV %d for %dHz\n",
2795 bclk_divs[i], wm8962->bclk);
2796 clocking2 |= i;
2797 break;
2798 }
2799 }
2800 if (i == ARRAY_SIZE(bclk_divs)) {
2801 dev_err(codec->dev, "Unsupported BCLK ratio %d\n",
2802 dspclk / wm8962->bclk);
2803 return;
2804 }
2805
2806 aif2 |= wm8962->bclk / wm8962->lrclk;
2807 dev_dbg(codec->dev, "Selected LRCLK divisor %d for %dHz\n",
2808 wm8962->bclk / wm8962->lrclk, wm8962->lrclk);
2809
2810 snd_soc_update_bits(codec, WM8962_CLOCKING2,
2811 WM8962_BCLK_DIV_MASK, clocking2);
2812 snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_2,
2813 WM8962_AIF_RATE_MASK, aif2);
2814}
2815
2816static int wm8962_set_bias_level(struct snd_soc_codec *codec,
2817 enum snd_soc_bias_level level)
2818{
2819 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2820 int ret;
2821
2822 if (level == codec->bias_level)
2823 return 0;
2824
2825 switch (level) {
2826 case SND_SOC_BIAS_ON:
2827 break;
2828
2829 case SND_SOC_BIAS_PREPARE:
2830 /* VMID 2*50k */
2831 snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
2832 WM8962_VMID_SEL_MASK, 0x80);
2833 break;
2834
2835 case SND_SOC_BIAS_STANDBY:
2836 if (codec->bias_level == SND_SOC_BIAS_OFF) {
2837 ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
2838 wm8962->supplies);
2839 if (ret != 0) {
2840 dev_err(codec->dev,
2841 "Failed to enable supplies: %d\n",
2842 ret);
2843 return ret;
2844 }
2845
2846 wm8962_sync_cache(codec);
2847
2848 snd_soc_update_bits(codec, WM8962_ANTI_POP,
2849 WM8962_STARTUP_BIAS_ENA |
2850 WM8962_VMID_BUF_ENA,
2851 WM8962_STARTUP_BIAS_ENA |
2852 WM8962_VMID_BUF_ENA);
2853
2854 /* Bias enable at 2*50k for ramp */
2855 snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
2856 WM8962_VMID_SEL_MASK |
2857 WM8962_BIAS_ENA,
2858 WM8962_BIAS_ENA | 0x180);
2859
2860 msleep(5);
2861
2862 snd_soc_update_bits(codec, WM8962_CLOCKING2,
2863 WM8962_CLKREG_OVD,
2864 WM8962_CLKREG_OVD);
2865
2866 wm8962_configure_bclk(codec);
2867 }
2868
2869 /* VMID 2*250k */
2870 snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
2871 WM8962_VMID_SEL_MASK, 0x100);
2872 break;
2873
2874 case SND_SOC_BIAS_OFF:
2875 snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
2876 WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
2877
2878 snd_soc_update_bits(codec, WM8962_ANTI_POP,
2879 WM8962_STARTUP_BIAS_ENA |
2880 WM8962_VMID_BUF_ENA, 0);
2881
2882 regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
2883 wm8962->supplies);
2884 break;
2885 }
2886 codec->bias_level = level;
2887 return 0;
2888}
2889
2890static const struct {
2891 int rate;
2892 int reg;
2893} sr_vals[] = {
2894 { 48000, 0 },
2895 { 44100, 0 },
2896 { 32000, 1 },
2897 { 22050, 2 },
2898 { 24000, 2 },
2899 { 16000, 3 },
2900 { 11025, 4 },
2901 { 12000, 4 },
2902 { 8000, 5 },
2903 { 88200, 6 },
2904 { 96000, 6 },
2905};
2906
2907static const int sysclk_rates[] = {
2908 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
2909};
2910
2911static int wm8962_hw_params(struct snd_pcm_substream *substream,
2912 struct snd_pcm_hw_params *params,
2913 struct snd_soc_dai *dai)
2914{
2915 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2916 struct snd_soc_codec *codec = rtd->codec;
2917 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2918 int rate = params_rate(params);
2919 int i;
2920 int aif0 = 0;
2921 int adctl3 = 0;
2922 int clocking4 = 0;
2923
2924 wm8962->bclk = snd_soc_params_to_bclk(params);
2925 wm8962->lrclk = params_rate(params);
2926
2927 for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
2928 if (sr_vals[i].rate == rate) {
2929 adctl3 |= sr_vals[i].reg;
2930 break;
2931 }
2932 }
2933 if (i == ARRAY_SIZE(sr_vals)) {
2934 dev_err(codec->dev, "Unsupported rate %dHz\n", rate);
2935 return -EINVAL;
2936 }
2937
2938 if (rate % 8000 == 0)
2939 adctl3 |= WM8962_SAMPLE_RATE_INT_MODE;
2940
2941 for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) {
2942 if (sysclk_rates[i] == wm8962->sysclk_rate / rate) {
2943 clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT;
2944 break;
2945 }
2946 }
2947 if (i == ARRAY_SIZE(sysclk_rates)) {
2948 dev_err(codec->dev, "Unsupported sysclk ratio %d\n",
2949 wm8962->sysclk_rate / rate);
2950 return -EINVAL;
2951 }
2952
2953 switch (params_format(params)) {
2954 case SNDRV_PCM_FORMAT_S16_LE:
2955 break;
2956 case SNDRV_PCM_FORMAT_S20_3LE:
2957 aif0 |= 0x40;
2958 break;
2959 case SNDRV_PCM_FORMAT_S24_LE:
2960 aif0 |= 0x80;
2961 break;
2962 case SNDRV_PCM_FORMAT_S32_LE:
2963 aif0 |= 0xc0;
2964 break;
2965 default:
2966 return -EINVAL;
2967 }
2968
2969 snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0,
2970 WM8962_WL_MASK, aif0);
2971 snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_3,
2972 WM8962_SAMPLE_RATE_INT_MODE |
2973 WM8962_SAMPLE_RATE_MASK, adctl3);
2974 snd_soc_update_bits(codec, WM8962_CLOCKING_4,
2975 WM8962_SYSCLK_RATE_MASK, clocking4);
2976
2977 wm8962_configure_bclk(codec);
2978
2979 return 0;
2980}
2981
2982static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
2983 unsigned int freq, int dir)
2984{
2985 struct snd_soc_codec *codec = dai->codec;
2986 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
2987 int src;
2988
2989 switch (clk_id) {
2990 case WM8962_SYSCLK_MCLK:
2991 wm8962->sysclk = WM8962_SYSCLK_MCLK;
2992 src = 0;
2993 break;
2994 case WM8962_SYSCLK_FLL:
2995 wm8962->sysclk = WM8962_SYSCLK_FLL;
2996 src = 1 << WM8962_SYSCLK_SRC_SHIFT;
2997 WARN_ON(freq != wm8962->fll_fout);
2998 break;
2999 default:
3000 return -EINVAL;
3001 }
3002
3003 snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_SRC_MASK,
3004 src);
3005
3006 wm8962->sysclk_rate = freq;
3007
3008 return 0;
3009}
3010
3011static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
3012{
3013 struct snd_soc_codec *codec = dai->codec;
3014 int aif0 = 0;
3015
3016 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
3017 case SND_SOC_DAIFMT_DSP_A:
3018 aif0 |= WM8962_LRCLK_INV;
3019 case SND_SOC_DAIFMT_DSP_B:
3020 aif0 |= 3;
3021
3022 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
3023 case SND_SOC_DAIFMT_NB_NF:
3024 case SND_SOC_DAIFMT_IB_NF:
3025 break;
3026 default:
3027 return -EINVAL;
3028 }
3029 break;
3030
3031 case SND_SOC_DAIFMT_RIGHT_J:
3032 break;
3033 case SND_SOC_DAIFMT_LEFT_J:
3034 aif0 |= 1;
3035 break;
3036 case SND_SOC_DAIFMT_I2S:
3037 aif0 |= 2;
3038 break;
3039 default:
3040 return -EINVAL;
3041 }
3042
3043 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
3044 case SND_SOC_DAIFMT_NB_NF:
3045 break;
3046 case SND_SOC_DAIFMT_IB_NF:
3047 aif0 |= WM8962_BCLK_INV;
3048 break;
3049 case SND_SOC_DAIFMT_NB_IF:
3050 aif0 |= WM8962_LRCLK_INV;
3051 break;
3052 case SND_SOC_DAIFMT_IB_IF:
3053 aif0 |= WM8962_BCLK_INV | WM8962_LRCLK_INV;
3054 break;
3055 default:
3056 return -EINVAL;
3057 }
3058
3059 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
3060 case SND_SOC_DAIFMT_CBM_CFM:
3061 aif0 |= WM8962_MSTR;
3062 break;
3063 case SND_SOC_DAIFMT_CBS_CFS:
3064 break;
3065 default:
3066 return -EINVAL;
3067 }
3068
3069 snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0,
3070 WM8962_FMT_MASK | WM8962_BCLK_INV | WM8962_MSTR |
3071 WM8962_LRCLK_INV, aif0);
3072
3073 return 0;
3074}
3075
3076struct _fll_div {
3077 u16 fll_fratio;
3078 u16 fll_outdiv;
3079 u16 fll_refclk_div;
3080 u16 n;
3081 u16 theta;
3082 u16 lambda;
3083};
3084
3085/* The size in bits of the FLL divide multiplied by 10
3086 * to allow rounding later */
3087#define FIXED_FLL_SIZE ((1 << 16) * 10)
3088
3089static struct {
3090 unsigned int min;
3091 unsigned int max;
3092 u16 fll_fratio;
3093 int ratio;
3094} fll_fratios[] = {
3095 { 0, 64000, 4, 16 },
3096 { 64000, 128000, 3, 8 },
3097 { 128000, 256000, 2, 4 },
3098 { 256000, 1000000, 1, 2 },
3099 { 1000000, 13500000, 0, 1 },
3100};
3101
3102static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
3103 unsigned int Fout)
3104{
3105 unsigned int target;
3106 unsigned int div;
3107 unsigned int fratio, gcd_fll;
3108 int i;
3109
3110 /* Fref must be <=13.5MHz */
3111 div = 1;
3112 fll_div->fll_refclk_div = 0;
3113 while ((Fref / div) > 13500000) {
3114 div *= 2;
3115 fll_div->fll_refclk_div++;
3116
3117 if (div > 4) {
3118 pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
3119 Fref);
3120 return -EINVAL;
3121 }
3122 }
3123
3124 pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
3125
3126 /* Apply the division for our remaining calculations */
3127 Fref /= div;
3128
3129 /* Fvco should be 90-100MHz; don't check the upper bound */
3130 div = 2;
3131 while (Fout * div < 90000000) {
3132 div++;
3133 if (div > 64) {
3134 pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
3135 Fout);
3136 return -EINVAL;
3137 }
3138 }
3139 target = Fout * div;
3140 fll_div->fll_outdiv = div - 1;
3141
3142 pr_debug("FLL Fvco=%dHz\n", target);
3143
3144 /* Find an appropraite FLL_FRATIO and factor it out of the target */
3145 for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
3146 if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
3147 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
3148 fratio = fll_fratios[i].ratio;
3149 break;
3150 }
3151 }
3152 if (i == ARRAY_SIZE(fll_fratios)) {
3153 pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
3154 return -EINVAL;
3155 }
3156
3157 fll_div->n = target / (fratio * Fref);
3158
3159 if (target % Fref == 0) {
3160 fll_div->theta = 0;
3161 fll_div->lambda = 0;
3162 } else {
3163 gcd_fll = gcd(target, fratio * Fref);
3164
3165 fll_div->theta = (target - (fll_div->n * fratio * Fref))
3166 / gcd_fll;
3167 fll_div->lambda = (fratio * Fref) / gcd_fll;
3168 }
3169
3170 pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
3171 fll_div->n, fll_div->theta, fll_div->lambda);
3172 pr_debug("FLL_FRATIO=%x FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
3173 fll_div->fll_fratio, fll_div->fll_outdiv,
3174 fll_div->fll_refclk_div);
3175
3176 return 0;
3177}
3178
3179static int wm8962_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
3180 unsigned int Fref, unsigned int Fout)
3181{
3182 struct snd_soc_codec *codec = dai->codec;
3183 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3184 struct _fll_div fll_div;
3185 int ret;
3186 int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
3187
3188 /* Any change? */
3189 if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
3190 Fout == wm8962->fll_fout)
3191 return 0;
3192
3193 if (Fout == 0) {
3194 dev_dbg(codec->dev, "FLL disabled\n");
3195
3196 wm8962->fll_fref = 0;
3197 wm8962->fll_fout = 0;
3198
3199 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
3200 WM8962_FLL_ENA, 0);
3201
3202 return 0;
3203 }
3204
3205 ret = fll_factors(&fll_div, Fref, Fout);
3206 if (ret != 0)
3207 return ret;
3208
3209 switch (fll_id) {
3210 case WM8962_FLL_MCLK:
3211 case WM8962_FLL_BCLK:
3212 case WM8962_FLL_OSC:
3213 fll1 |= (fll_id - 1) << WM8962_FLL_REFCLK_SRC_SHIFT;
3214 break;
3215 case WM8962_FLL_INT:
3216 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
3217 WM8962_FLL_OSC_ENA, WM8962_FLL_OSC_ENA);
3218 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_5,
3219 WM8962_FLL_FRC_NCO, WM8962_FLL_FRC_NCO);
3220 break;
3221 default:
3222 dev_err(codec->dev, "Unknown FLL source %d\n", ret);
3223 return -EINVAL;
3224 }
3225
3226 if (fll_div.theta || fll_div.lambda)
3227 fll1 |= WM8962_FLL_FRAC;
3228
3229 /* Stop the FLL while we reconfigure */
3230 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
3231
3232 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_2,
3233 WM8962_FLL_OUTDIV_MASK |
3234 WM8962_FLL_REFCLK_DIV_MASK,
3235 (fll_div.fll_outdiv << WM8962_FLL_OUTDIV_SHIFT) |
3236 (fll_div.fll_refclk_div));
3237
3238 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_3,
3239 WM8962_FLL_FRATIO_MASK, fll_div.fll_fratio);
3240
3241 snd_soc_write(codec, WM8962_FLL_CONTROL_6, fll_div.theta);
3242 snd_soc_write(codec, WM8962_FLL_CONTROL_7, fll_div.lambda);
3243 snd_soc_write(codec, WM8962_FLL_CONTROL_8, fll_div.n);
3244
3245 snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
3246 WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
3247 WM8962_FLL_ENA, fll1);
3248
3249 dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
3250
3251 wm8962->fll_fref = Fref;
3252 wm8962->fll_fout = Fout;
3253 wm8962->fll_src = source;
3254
3255 return 0;
3256}
3257
3258static int wm8962_mute(struct snd_soc_dai *dai, int mute)
3259{
3260 struct snd_soc_codec *codec = dai->codec;
3261 int val;
3262
3263 if (mute)
3264 val = WM8962_DAC_MUTE;
3265 else
3266 val = 0;
3267
3268 return snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
3269 WM8962_DAC_MUTE, val);
3270}
3271
3272#define WM8962_RATES SNDRV_PCM_RATE_8000_96000
3273
3274#define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
3275 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
3276
3277static struct snd_soc_dai_ops wm8962_dai_ops = {
3278 .hw_params = wm8962_hw_params,
3279 .set_sysclk = wm8962_set_dai_sysclk,
3280 .set_fmt = wm8962_set_dai_fmt,
3281 .set_pll = wm8962_set_fll,
3282 .digital_mute = wm8962_mute,
3283};
3284
3285static struct snd_soc_dai_driver wm8962_dai = {
3286 .name = "wm8962",
3287 .playback = {
3288 .stream_name = "Playback",
3289 .channels_min = 2,
3290 .channels_max = 2,
3291 .rates = WM8962_RATES,
3292 .formats = WM8962_FORMATS,
3293 },
3294 .capture = {
3295 .stream_name = "Capture",
3296 .channels_min = 2,
3297 .channels_max = 2,
3298 .rates = WM8962_RATES,
3299 .formats = WM8962_FORMATS,
3300 },
3301 .ops = &wm8962_dai_ops,
3302 .symmetric_rates = 1,
3303};
3304
3305static void wm8962_mic_work(struct work_struct *work)
3306{
3307 struct wm8962_priv *wm8962 = container_of(work,
3308 struct wm8962_priv,
3309 mic_work.work);
3310 struct snd_soc_codec *codec = wm8962->codec;
3311 int status = 0;
3312 int irq_pol = 0;
3313 int reg;
3314
3315 reg = snd_soc_read(codec, WM8962_ADDITIONAL_CONTROL_4);
3316
3317 if (reg & WM8962_MICDET_STS) {
3318 status |= SND_JACK_MICROPHONE;
3319 irq_pol |= WM8962_MICD_IRQ_POL;
3320 }
3321
3322 if (reg & WM8962_MICSHORT_STS) {
3323 status |= SND_JACK_BTN_0;
3324 irq_pol |= WM8962_MICSCD_IRQ_POL;
3325 }
3326
3327 snd_soc_jack_report(wm8962->jack, status,
3328 SND_JACK_MICROPHONE | SND_JACK_BTN_0);
3329
3330 snd_soc_update_bits(codec, WM8962_MICINT_SOURCE_POL,
3331 WM8962_MICSCD_IRQ_POL |
3332 WM8962_MICD_IRQ_POL, irq_pol);
3333}
3334
3335static irqreturn_t wm8962_irq(int irq, void *data)
3336{
3337 struct snd_soc_codec *codec = data;
3338 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3339 int mask;
3340 int active;
3341
3342 mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
3343
3344 active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
3345 active &= ~mask;
3346
3347 if (active & WM8962_FIFOS_ERR_EINT)
3348 dev_err(codec->dev, "FIFO error\n");
3349
3350 if (active & WM8962_TEMP_SHUT_EINT)
3351 dev_crit(codec->dev, "Thermal shutdown\n");
3352
3353 if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
3354 dev_dbg(codec->dev, "Microphone event detected\n");
3355
3356 schedule_delayed_work(&wm8962->mic_work,
3357 msecs_to_jiffies(250));
3358 }
3359
3360 /* Acknowledge the interrupts */
3361 snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
3362
3363 return IRQ_HANDLED;
3364}
3365
3366/**
3367 * wm8962_mic_detect - Enable microphone detection via the WM8962 IRQ
3368 *
3369 * @codec: WM8962 codec
3370 * @jack: jack to report detection events on
3371 *
3372 * Enable microphone detection via IRQ on the WM8962. If GPIOs are
3373 * being used to bring out signals to the processor then only platform
3374 * data configuration is needed for WM8962 and processor GPIOs should
3375 * be configured using snd_soc_jack_add_gpios() instead.
3376 *
3377 * If no jack is supplied detection will be disabled.
3378 */
3379int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
3380{
3381 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3382 int irq_mask, enable;
3383
3384 wm8962->jack = jack;
3385 if (jack) {
3386 irq_mask = 0;
3387 enable = WM8962_MICDET_ENA;
3388 } else {
3389 irq_mask = WM8962_MICD_EINT | WM8962_MICSCD_EINT;
3390 enable = 0;
3391 }
3392
3393 snd_soc_update_bits(codec, WM8962_INTERRUPT_STATUS_2_MASK,
3394 WM8962_MICD_EINT | WM8962_MICSCD_EINT, irq_mask);
3395 snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
3396 WM8962_MICDET_ENA, enable);
3397
3398 /* Send an initial empty report */
3399 snd_soc_jack_report(wm8962->jack, 0,
3400 SND_JACK_MICROPHONE | SND_JACK_BTN_0);
3401
3402 return 0;
3403}
3404EXPORT_SYMBOL_GPL(wm8962_mic_detect);
3405
3406#ifdef CONFIG_PM
3407static int wm8962_resume(struct snd_soc_codec *codec)
3408{
3409 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3410 u16 *reg_cache = codec->reg_cache;
3411 int i;
3412
3413 /* Restore the registers */
3414 for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
3415 switch (i) {
3416 case WM8962_SOFTWARE_RESET:
3417 continue;
3418 default:
3419 break;
3420 }
3421
3422 if (reg_cache[i] != wm8962_reg[i])
3423 snd_soc_write(codec, i, reg_cache[i]);
3424 }
3425
3426 return 0;
3427}
3428#else
3429#define wm8962_resume NULL
3430#endif
3431
3432#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
3433static int beep_rates[] = {
3434 500, 1000, 2000, 4000,
3435};
3436
3437static void wm8962_beep_work(struct work_struct *work)
3438{
3439 struct wm8962_priv *wm8962 =
3440 container_of(work, struct wm8962_priv, beep_work);
3441 struct snd_soc_codec *codec = wm8962->codec;
3442 int i;
3443 int reg = 0;
3444 int best = 0;
3445
3446 if (wm8962->beep_rate) {
3447 for (i = 0; i < ARRAY_SIZE(beep_rates); i++) {
3448 if (abs(wm8962->beep_rate - beep_rates[i]) <
3449 abs(wm8962->beep_rate - beep_rates[best]))
3450 best = i;
3451 }
3452
3453 dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n",
3454 beep_rates[best], wm8962->beep_rate);
3455
3456 reg = WM8962_BEEP_ENA | (best << WM8962_BEEP_RATE_SHIFT);
3457
3458 snd_soc_dapm_enable_pin(codec, "Beep");
3459 } else {
3460 dev_dbg(codec->dev, "Disabling beep\n");
3461 snd_soc_dapm_disable_pin(codec, "Beep");
3462 }
3463
3464 snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1,
3465 WM8962_BEEP_ENA | WM8962_BEEP_RATE_MASK, reg);
3466
3467 snd_soc_dapm_sync(codec);
3468}
3469
3470/* For usability define a way of injecting beep events for the device -
3471 * many systems will not have a keyboard.
3472 */
3473static int wm8962_beep_event(struct input_dev *dev, unsigned int type,
3474 unsigned int code, int hz)
3475{
3476 struct snd_soc_codec *codec = input_get_drvdata(dev);
3477 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3478
3479 dev_dbg(codec->dev, "Beep event %x %x\n", code, hz);
3480
3481 switch (code) {
3482 case SND_BELL:
3483 if (hz)
3484 hz = 1000;
3485 case SND_TONE:
3486 break;
3487 default:
3488 return -1;
3489 }
3490
3491 /* Kick the beep from a workqueue */
3492 wm8962->beep_rate = hz;
3493 schedule_work(&wm8962->beep_work);
3494 return 0;
3495}
3496
3497static ssize_t wm8962_beep_set(struct device *dev,
3498 struct device_attribute *attr,
3499 const char *buf, size_t count)
3500{
3501 struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
3502 long int time;
3503
3504 strict_strtol(buf, 10, &time);
3505
3506 input_event(wm8962->beep, EV_SND, SND_TONE, time);
3507
3508 return count;
3509}
3510
3511static DEVICE_ATTR(beep, 0200, NULL, wm8962_beep_set);
3512
3513static void wm8962_init_beep(struct snd_soc_codec *codec)
3514{
3515 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3516 int ret;
3517
3518 wm8962->beep = input_allocate_device();
3519 if (!wm8962->beep) {
3520 dev_err(codec->dev, "Failed to allocate beep device\n");
3521 return;
3522 }
3523
3524 INIT_WORK(&wm8962->beep_work, wm8962_beep_work);
3525 wm8962->beep_rate = 0;
3526
3527 wm8962->beep->name = "WM8962 Beep Generator";
3528 wm8962->beep->phys = dev_name(codec->dev);
3529 wm8962->beep->id.bustype = BUS_I2C;
3530
3531 wm8962->beep->evbit[0] = BIT_MASK(EV_SND);
3532 wm8962->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
3533 wm8962->beep->event = wm8962_beep_event;
3534 wm8962->beep->dev.parent = codec->dev;
3535 input_set_drvdata(wm8962->beep, codec);
3536
3537 ret = input_register_device(wm8962->beep);
3538 if (ret != 0) {
3539 input_free_device(wm8962->beep);
3540 wm8962->beep = NULL;
3541 dev_err(codec->dev, "Failed to register beep device\n");
3542 }
3543
3544 ret = device_create_file(codec->dev, &dev_attr_beep);
3545 if (ret != 0) {
3546 dev_err(codec->dev, "Failed to create keyclick file: %d\n",
3547 ret);
3548 }
3549}
3550
3551static void wm8962_free_beep(struct snd_soc_codec *codec)
3552{
3553 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3554
3555 device_remove_file(codec->dev, &dev_attr_beep);
3556 input_unregister_device(wm8962->beep);
3557 cancel_work_sync(&wm8962->beep_work);
3558 wm8962->beep = NULL;
3559
3560 snd_soc_update_bits(codec, WM8962_BEEP_GENERATOR_1, WM8962_BEEP_ENA,0);
3561}
3562#else
3563static void wm8962_init_beep(struct snd_soc_codec *codec)
3564{
3565}
3566
3567static void wm8962_free_beep(struct snd_soc_codec *codec)
3568{
3569}
3570#endif
3571
3572static void wm8962_set_gpio_mode(struct snd_soc_codec *codec, int gpio)
3573{
3574 int mask = 0;
3575 int val = 0;
3576
3577 /* Some of the GPIOs are behind MFP configuration and need to
3578 * be put into GPIO mode. */
3579 switch (gpio) {
3580 case 2:
3581 mask = WM8962_CLKOUT2_SEL_MASK;
3582 val = 1 << WM8962_CLKOUT2_SEL_SHIFT;
3583 break;
3584 case 3:
3585 mask = WM8962_CLKOUT3_SEL_MASK;
3586 val = 1 << WM8962_CLKOUT3_SEL_SHIFT;
3587 break;
3588 default:
3589 break;
3590 }
3591
3592 if (mask)
3593 snd_soc_update_bits(codec, WM8962_ANALOGUE_CLOCKING1,
3594 mask, val);
3595}
3596
3597#ifdef CONFIG_GPIOLIB
3598static inline struct wm8962_priv *gpio_to_wm8962(struct gpio_chip *chip)
3599{
3600 return container_of(chip, struct wm8962_priv, gpio_chip);
3601}
3602
3603static int wm8962_gpio_request(struct gpio_chip *chip, unsigned offset)
3604{
3605 struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
3606 struct snd_soc_codec *codec = wm8962->codec;
3607
3608 /* The WM8962 GPIOs aren't linearly numbered. For simplicity
3609 * we export linear numbers and error out if the unsupported
3610 * ones are requsted.
3611 */
3612 switch (offset + 1) {
3613 case 2:
3614 case 3:
3615 case 5:
3616 case 6:
3617 break;
3618 default:
3619 return -EINVAL;
3620 }
3621
3622 wm8962_set_gpio_mode(codec, offset + 1);
3623
3624 return 0;
3625}
3626
3627static void wm8962_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
3628{
3629 struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
3630 struct snd_soc_codec *codec = wm8962->codec;
3631
3632 snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
3633 WM8962_GP2_LVL, value << WM8962_GP2_LVL_SHIFT);
3634}
3635
3636static int wm8962_gpio_direction_out(struct gpio_chip *chip,
3637 unsigned offset, int value)
3638{
3639 struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
3640 struct snd_soc_codec *codec = wm8962->codec;
3641 int val;
3642
3643 /* Force function 1 (logic output) */
3644 val = (1 << WM8962_GP2_FN_SHIFT) | (value << WM8962_GP2_LVL_SHIFT);
3645
3646 return snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
3647 WM8962_GP2_FN_MASK | WM8962_GP2_LVL, val);
3648}
3649
3650static struct gpio_chip wm8962_template_chip = {
3651 .label = "wm8962",
3652 .owner = THIS_MODULE,
3653 .request = wm8962_gpio_request,
3654 .direction_output = wm8962_gpio_direction_out,
3655 .set = wm8962_gpio_set,
3656 .can_sleep = 1,
3657};
3658
3659static void wm8962_init_gpio(struct snd_soc_codec *codec)
3660{
3661 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3662 struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
3663 int ret;
3664
3665 wm8962->gpio_chip = wm8962_template_chip;
3666 wm8962->gpio_chip.ngpio = WM8962_MAX_GPIO;
3667 wm8962->gpio_chip.dev = codec->dev;
3668
3669 if (pdata && pdata->gpio_base)
3670 wm8962->gpio_chip.base = pdata->gpio_base;
3671 else
3672 wm8962->gpio_chip.base = -1;
3673
3674 ret = gpiochip_add(&wm8962->gpio_chip);
3675 if (ret != 0)
3676 dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
3677}
3678
3679static void wm8962_free_gpio(struct snd_soc_codec *codec)
3680{
3681 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3682 int ret;
3683
3684 ret = gpiochip_remove(&wm8962->gpio_chip);
3685 if (ret != 0)
3686 dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
3687}
3688#else
3689static void wm8962_init_gpio(struct snd_soc_codec *codec)
3690{
3691}
3692
3693static void wm8962_free_gpio(struct snd_soc_codec *codec)
3694{
3695}
3696#endif
3697
3698static int wm8962_probe(struct snd_soc_codec *codec)
3699{
3700 int ret;
3701 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3702 struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
3703 struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
3704 dev);
3705 int i, trigger, irq_pol;
3706
3707 wm8962->codec = codec;
3708 INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
3709
3710 codec->cache_sync = 1;
3711 codec->idle_bias_off = 1;
3712
3713 ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
3714 if (ret != 0) {
3715 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
3716 goto err;
3717 }
3718
3719 for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
3720 wm8962->supplies[i].supply = wm8962_supply_names[i];
3721
3722 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8962->supplies),
3723 wm8962->supplies);
3724 if (ret != 0) {
3725 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
3726 goto err;
3727 }
3728
3729 wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
3730 wm8962->disable_nb[1].notifier_call = wm8962_regulator_event_1;
3731 wm8962->disable_nb[2].notifier_call = wm8962_regulator_event_2;
3732 wm8962->disable_nb[3].notifier_call = wm8962_regulator_event_3;
3733 wm8962->disable_nb[4].notifier_call = wm8962_regulator_event_4;
3734 wm8962->disable_nb[5].notifier_call = wm8962_regulator_event_5;
3735 wm8962->disable_nb[6].notifier_call = wm8962_regulator_event_6;
3736 wm8962->disable_nb[7].notifier_call = wm8962_regulator_event_7;
3737
3738 /* This should really be moved into the regulator core */
3739 for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) {
3740 ret = regulator_register_notifier(wm8962->supplies[i].consumer,
3741 &wm8962->disable_nb[i]);
3742 if (ret != 0) {
3743 dev_err(codec->dev,
3744 "Failed to register regulator notifier: %d\n",
3745 ret);
3746 }
3747 }
3748
3749 ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
3750 wm8962->supplies);
3751 if (ret != 0) {
3752 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
3753 goto err_get;
3754 }
3755
3756 ret = snd_soc_read(codec, WM8962_SOFTWARE_RESET);
3757 if (ret < 0) {
3758 dev_err(codec->dev, "Failed to read ID register\n");
3759 goto err_enable;
3760 }
3761 if (ret != wm8962_reg[WM8962_SOFTWARE_RESET]) {
3762 dev_err(codec->dev, "Device is not a WM8962, ID %x != %x\n",
3763 ret, wm8962_reg[WM8962_SOFTWARE_RESET]);
3764 ret = -EINVAL;
3765 goto err_enable;
3766 }
3767
3768 ret = snd_soc_read(codec, WM8962_RIGHT_INPUT_VOLUME);
3769 if (ret < 0) {
3770 dev_err(codec->dev, "Failed to read device revision: %d\n",
3771 ret);
3772 goto err_enable;
3773 }
3774
3775 dev_info(codec->dev, "customer id %x revision %c\n",
3776 (ret & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
3777 ((ret & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
3778 + 'A');
3779
3780 ret = wm8962_reset(codec);
3781 if (ret < 0) {
3782 dev_err(codec->dev, "Failed to issue reset\n");
3783 goto err_enable;
3784 }
3785
3786 /* SYSCLK defaults to on; make sure it is off so we can safely
3787 * write to registers if the device is declocked.
3788 */
3789 snd_soc_update_bits(codec, WM8962_CLOCKING2, WM8962_SYSCLK_ENA, 0);
3790
3791 regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
3792
3793 if (pdata) {
3794 /* Apply static configuration for GPIOs */
3795 for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++)
3796 if (pdata->gpio_init[i]) {
3797 wm8962_set_gpio_mode(codec, i + 1);
3798 snd_soc_write(codec, 0x200 + i,
3799 pdata->gpio_init[i] & 0xffff);
3800 }
3801
3802 /* Put the speakers into mono mode? */
3803 if (pdata->spk_mono)
3804 wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2]
3805 |= WM8962_SPK_MONO;
3806
3807 /* Micbias setup, detection enable and detection
3808 * threasholds. */
3809 if (pdata->mic_cfg)
3810 snd_soc_update_bits(codec, WM8962_ADDITIONAL_CONTROL_4,
3811 WM8962_MICDET_ENA |
3812 WM8962_MICDET_THR_MASK |
3813 WM8962_MICSHORT_THR_MASK |
3814 WM8962_MICBIAS_LVL,
3815 pdata->mic_cfg);
3816 }
3817
3818 /* Latch volume update bits */
3819 wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
3820 wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
3821 wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
3822 wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
3823 wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
3824 wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
3825 wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
3826 wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
3827 wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
3828 wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
3829
3830 wm8962_add_widgets(codec);
3831
3832 wm8962_init_beep(codec);
3833 wm8962_init_gpio(codec);
3834
3835 if (i2c->irq) {
3836 if (pdata && pdata->irq_active_low) {
3837 trigger = IRQF_TRIGGER_LOW;
3838 irq_pol = WM8962_IRQ_POL;
3839 } else {
3840 trigger = IRQF_TRIGGER_HIGH;
3841 irq_pol = 0;
3842 }
3843
3844 snd_soc_update_bits(codec, WM8962_INTERRUPT_CONTROL,
3845 WM8962_IRQ_POL, irq_pol);
3846
3847 ret = request_threaded_irq(i2c->irq, NULL, wm8962_irq,
3848 trigger | IRQF_ONESHOT,
3849 "wm8962", codec);
3850 if (ret != 0) {
3851 dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
3852 i2c->irq, ret);
3853 /* Non-fatal */
3854 } else {
3855 /* Enable error reporting IRQs by default */
3856 snd_soc_update_bits(codec,
3857 WM8962_INTERRUPT_STATUS_2_MASK,
3858 WM8962_TEMP_SHUT_EINT |
3859 WM8962_FIFOS_ERR_EINT, 0);
3860 }
3861 }
3862
3863 return 0;
3864
3865err_enable:
3866 regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
3867err_get:
3868 regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
3869err:
3870 kfree(wm8962);
3871 return ret;
3872}
3873
3874static int wm8962_remove(struct snd_soc_codec *codec)
3875{
3876 struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
3877 struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
3878 dev);
3879 int i;
3880
3881 if (i2c->irq)
3882 free_irq(i2c->irq, codec);
3883
3884 cancel_delayed_work_sync(&wm8962->mic_work);
3885
3886 wm8962_free_gpio(codec);
3887 wm8962_free_beep(codec);
3888 for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
3889 regulator_unregister_notifier(wm8962->supplies[i].consumer,
3890 &wm8962->disable_nb[i]);
3891 regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
3892
3893 return 0;
3894}
3895
3896static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
3897 .probe = wm8962_probe,
3898 .remove = wm8962_remove,
3899 .resume = wm8962_resume,
3900 .set_bias_level = wm8962_set_bias_level,
3901 .reg_cache_size = WM8962_MAX_REGISTER + 1,
3902 .reg_word_size = sizeof(u16),
3903 .reg_cache_default = wm8962_reg,
3904 .volatile_register = wm8962_volatile_register,
3905 .readable_register = wm8962_readable_register,
3906};
3907
3908#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
3909static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
3910 const struct i2c_device_id *id)
3911{
3912 struct wm8962_priv *wm8962;
3913 int ret;
3914
3915 wm8962 = kzalloc(sizeof(struct wm8962_priv), GFP_KERNEL);
3916 if (wm8962 == NULL)
3917 return -ENOMEM;
3918
3919 i2c_set_clientdata(i2c, wm8962);
3920
3921 ret = snd_soc_register_codec(&i2c->dev,
3922 &soc_codec_dev_wm8962, &wm8962_dai, 1);
3923 if (ret < 0)
3924 kfree(wm8962);
3925
3926 return ret;
3927}
3928
3929static __devexit int wm8962_i2c_remove(struct i2c_client *client)
3930{
3931 snd_soc_unregister_codec(&client->dev);
3932 kfree(i2c_get_clientdata(client));
3933 return 0;
3934}
3935
3936static const struct i2c_device_id wm8962_i2c_id[] = {
3937 { "wm8962", 0 },
3938 { }
3939};
3940MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id);
3941
3942static struct i2c_driver wm8962_i2c_driver = {
3943 .driver = {
3944 .name = "wm8962",
3945 .owner = THIS_MODULE,
3946 },
3947 .probe = wm8962_i2c_probe,
3948 .remove = __devexit_p(wm8962_i2c_remove),
3949 .id_table = wm8962_i2c_id,
3950};
3951#endif
3952
3953static int __init wm8962_modinit(void)
3954{
3955 int ret;
3956#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
3957 ret = i2c_add_driver(&wm8962_i2c_driver);
3958 if (ret != 0) {
3959 printk(KERN_ERR "Failed to register WM8962 I2C driver: %d\n",
3960 ret);
3961 }
3962#endif
3963 return 0;
3964}
3965module_init(wm8962_modinit);
3966
3967static void __exit wm8962_exit(void)
3968{
3969#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
3970 i2c_del_driver(&wm8962_i2c_driver);
3971#endif
3972}
3973module_exit(wm8962_exit);
3974
3975MODULE_DESCRIPTION("ASoC WM8962 driver");
3976MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
3977MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8962.h b/sound/soc/codecs/wm8962.h
new file mode 100644
index 000000000000..a1a5d5294c19
--- /dev/null
+++ b/sound/soc/codecs/wm8962.h
@@ -0,0 +1,3780 @@
1/*
2 * wm8962.h -- WM8962 ASoC driver
3 *
4 * Copyright 2010 Wolfson Microelectronics, plc
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _WM8962_H
14#define _WM8962_H
15
16#include <asm/types.h>
17#include <sound/soc.h>
18
19#define WM8962_SYSCLK_MCLK 1
20#define WM8962_SYSCLK_FLL 2
21#define WM8962_SYSCLK_PLL3 3
22
23#define WM8962_FLL 1
24
25#define WM8962_FLL_MCLK 1
26#define WM8962_FLL_BCLK 2
27#define WM8962_FLL_OSC 3
28#define WM8962_FLL_INT 4
29
30/*
31 * Register values.
32 */
33#define WM8962_LEFT_INPUT_VOLUME 0x00
34#define WM8962_RIGHT_INPUT_VOLUME 0x01
35#define WM8962_HPOUTL_VOLUME 0x02
36#define WM8962_HPOUTR_VOLUME 0x03
37#define WM8962_CLOCKING1 0x04
38#define WM8962_ADC_DAC_CONTROL_1 0x05
39#define WM8962_ADC_DAC_CONTROL_2 0x06
40#define WM8962_AUDIO_INTERFACE_0 0x07
41#define WM8962_CLOCKING2 0x08
42#define WM8962_AUDIO_INTERFACE_1 0x09
43#define WM8962_LEFT_DAC_VOLUME 0x0A
44#define WM8962_RIGHT_DAC_VOLUME 0x0B
45#define WM8962_AUDIO_INTERFACE_2 0x0E
46#define WM8962_SOFTWARE_RESET 0x0F
47#define WM8962_ALC1 0x11
48#define WM8962_ALC2 0x12
49#define WM8962_ALC3 0x13
50#define WM8962_NOISE_GATE 0x14
51#define WM8962_LEFT_ADC_VOLUME 0x15
52#define WM8962_RIGHT_ADC_VOLUME 0x16
53#define WM8962_ADDITIONAL_CONTROL_1 0x17
54#define WM8962_ADDITIONAL_CONTROL_2 0x18
55#define WM8962_PWR_MGMT_1 0x19
56#define WM8962_PWR_MGMT_2 0x1A
57#define WM8962_ADDITIONAL_CONTROL_3 0x1B
58#define WM8962_ANTI_POP 0x1C
59#define WM8962_CLOCKING_3 0x1E
60#define WM8962_INPUT_MIXER_CONTROL_1 0x1F
61#define WM8962_LEFT_INPUT_MIXER_VOLUME 0x20
62#define WM8962_RIGHT_INPUT_MIXER_VOLUME 0x21
63#define WM8962_INPUT_MIXER_CONTROL_2 0x22
64#define WM8962_INPUT_BIAS_CONTROL 0x23
65#define WM8962_LEFT_INPUT_PGA_CONTROL 0x25
66#define WM8962_RIGHT_INPUT_PGA_CONTROL 0x26
67#define WM8962_SPKOUTL_VOLUME 0x28
68#define WM8962_SPKOUTR_VOLUME 0x29
69#define WM8962_THERMAL_SHUTDOWN_STATUS 0x2F
70#define WM8962_ADDITIONAL_CONTROL_4 0x30
71#define WM8962_CLASS_D_CONTROL_1 0x31
72#define WM8962_CLASS_D_CONTROL_2 0x33
73#define WM8962_CLOCKING_4 0x38
74#define WM8962_DAC_DSP_MIXING_1 0x39
75#define WM8962_DAC_DSP_MIXING_2 0x3A
76#define WM8962_DC_SERVO_0 0x3C
77#define WM8962_DC_SERVO_1 0x3D
78#define WM8962_DC_SERVO_4 0x40
79#define WM8962_DC_SERVO_6 0x42
80#define WM8962_ANALOGUE_PGA_BIAS 0x44
81#define WM8962_ANALOGUE_HP_0 0x45
82#define WM8962_ANALOGUE_HP_2 0x47
83#define WM8962_CHARGE_PUMP_1 0x48
84#define WM8962_CHARGE_PUMP_B 0x52
85#define WM8962_WRITE_SEQUENCER_CONTROL_1 0x57
86#define WM8962_WRITE_SEQUENCER_CONTROL_2 0x5A
87#define WM8962_WRITE_SEQUENCER_CONTROL_3 0x5D
88#define WM8962_CONTROL_INTERFACE 0x5E
89#define WM8962_MIXER_ENABLES 0x63
90#define WM8962_HEADPHONE_MIXER_1 0x64
91#define WM8962_HEADPHONE_MIXER_2 0x65
92#define WM8962_HEADPHONE_MIXER_3 0x66
93#define WM8962_HEADPHONE_MIXER_4 0x67
94#define WM8962_SPEAKER_MIXER_1 0x69
95#define WM8962_SPEAKER_MIXER_2 0x6A
96#define WM8962_SPEAKER_MIXER_3 0x6B
97#define WM8962_SPEAKER_MIXER_4 0x6C
98#define WM8962_SPEAKER_MIXER_5 0x6D
99#define WM8962_BEEP_GENERATOR_1 0x6E
100#define WM8962_OSCILLATOR_TRIM_3 0x73
101#define WM8962_OSCILLATOR_TRIM_4 0x74
102#define WM8962_OSCILLATOR_TRIM_7 0x77
103#define WM8962_ANALOGUE_CLOCKING1 0x7C
104#define WM8962_ANALOGUE_CLOCKING2 0x7D
105#define WM8962_ANALOGUE_CLOCKING3 0x7E
106#define WM8962_PLL_SOFTWARE_RESET 0x7F
107#define WM8962_PLL2 0x81
108#define WM8962_PLL_4 0x83
109#define WM8962_PLL_9 0x88
110#define WM8962_PLL_10 0x89
111#define WM8962_PLL_11 0x8A
112#define WM8962_PLL_12 0x8B
113#define WM8962_PLL_13 0x8C
114#define WM8962_PLL_14 0x8D
115#define WM8962_PLL_15 0x8E
116#define WM8962_PLL_16 0x8F
117#define WM8962_FLL_CONTROL_1 0x9B
118#define WM8962_FLL_CONTROL_2 0x9C
119#define WM8962_FLL_CONTROL_3 0x9D
120#define WM8962_FLL_CONTROL_5 0x9F
121#define WM8962_FLL_CONTROL_6 0xA0
122#define WM8962_FLL_CONTROL_7 0xA1
123#define WM8962_FLL_CONTROL_8 0xA2
124#define WM8962_GENERAL_TEST_1 0xFC
125#define WM8962_DF1 0x100
126#define WM8962_DF2 0x101
127#define WM8962_DF3 0x102
128#define WM8962_DF4 0x103
129#define WM8962_DF5 0x104
130#define WM8962_DF6 0x105
131#define WM8962_DF7 0x106
132#define WM8962_LHPF1 0x108
133#define WM8962_LHPF2 0x109
134#define WM8962_THREED1 0x10C
135#define WM8962_THREED2 0x10D
136#define WM8962_THREED3 0x10E
137#define WM8962_THREED4 0x10F
138#define WM8962_DRC_1 0x114
139#define WM8962_DRC_2 0x115
140#define WM8962_DRC_3 0x116
141#define WM8962_DRC_4 0x117
142#define WM8962_DRC_5 0x118
143#define WM8962_TLOOPBACK 0x11D
144#define WM8962_EQ1 0x14F
145#define WM8962_EQ2 0x150
146#define WM8962_EQ3 0x151
147#define WM8962_EQ4 0x152
148#define WM8962_EQ5 0x153
149#define WM8962_EQ6 0x154
150#define WM8962_EQ7 0x155
151#define WM8962_EQ8 0x156
152#define WM8962_EQ9 0x157
153#define WM8962_EQ10 0x158
154#define WM8962_EQ11 0x159
155#define WM8962_EQ12 0x15A
156#define WM8962_EQ13 0x15B
157#define WM8962_EQ14 0x15C
158#define WM8962_EQ15 0x15D
159#define WM8962_EQ16 0x15E
160#define WM8962_EQ17 0x15F
161#define WM8962_EQ18 0x160
162#define WM8962_EQ19 0x161
163#define WM8962_EQ20 0x162
164#define WM8962_EQ21 0x163
165#define WM8962_EQ22 0x164
166#define WM8962_EQ23 0x165
167#define WM8962_EQ24 0x166
168#define WM8962_EQ25 0x167
169#define WM8962_EQ26 0x168
170#define WM8962_EQ27 0x169
171#define WM8962_EQ28 0x16A
172#define WM8962_EQ29 0x16B
173#define WM8962_EQ30 0x16C
174#define WM8962_EQ31 0x16D
175#define WM8962_EQ32 0x16E
176#define WM8962_EQ33 0x16F
177#define WM8962_EQ34 0x170
178#define WM8962_EQ35 0x171
179#define WM8962_EQ36 0x172
180#define WM8962_EQ37 0x173
181#define WM8962_EQ38 0x174
182#define WM8962_EQ39 0x175
183#define WM8962_EQ40 0x176
184#define WM8962_EQ41 0x177
185#define WM8962_GPIO_BASE 0x200
186#define WM8962_GPIO_2 0x201
187#define WM8962_GPIO_3 0x202
188#define WM8962_GPIO_5 0x204
189#define WM8962_GPIO_6 0x205
190#define WM8962_INTERRUPT_STATUS_1 0x230
191#define WM8962_INTERRUPT_STATUS_2 0x231
192#define WM8962_INTERRUPT_STATUS_1_MASK 0x238
193#define WM8962_INTERRUPT_STATUS_2_MASK 0x239
194#define WM8962_INTERRUPT_CONTROL 0x240
195#define WM8962_IRQ_DEBOUNCE 0x248
196#define WM8962_MICINT_SOURCE_POL 0x24A
197#define WM8962_DSP2_POWER_MANAGEMENT 0x300
198#define WM8962_DSP2_EXECCONTROL 0x40D
199#define WM8962_WRITE_SEQUENCER_0 0x1000
200#define WM8962_WRITE_SEQUENCER_1 0x1001
201#define WM8962_WRITE_SEQUENCER_2 0x1002
202#define WM8962_WRITE_SEQUENCER_3 0x1003
203#define WM8962_WRITE_SEQUENCER_4 0x1004
204#define WM8962_WRITE_SEQUENCER_5 0x1005
205#define WM8962_WRITE_SEQUENCER_6 0x1006
206#define WM8962_WRITE_SEQUENCER_7 0x1007
207#define WM8962_WRITE_SEQUENCER_8 0x1008
208#define WM8962_WRITE_SEQUENCER_9 0x1009
209#define WM8962_WRITE_SEQUENCER_10 0x100A
210#define WM8962_WRITE_SEQUENCER_11 0x100B
211#define WM8962_WRITE_SEQUENCER_12 0x100C
212#define WM8962_WRITE_SEQUENCER_13 0x100D
213#define WM8962_WRITE_SEQUENCER_14 0x100E
214#define WM8962_WRITE_SEQUENCER_15 0x100F
215#define WM8962_WRITE_SEQUENCER_16 0x1010
216#define WM8962_WRITE_SEQUENCER_17 0x1011
217#define WM8962_WRITE_SEQUENCER_18 0x1012
218#define WM8962_WRITE_SEQUENCER_19 0x1013
219#define WM8962_WRITE_SEQUENCER_20 0x1014
220#define WM8962_WRITE_SEQUENCER_21 0x1015
221#define WM8962_WRITE_SEQUENCER_22 0x1016
222#define WM8962_WRITE_SEQUENCER_23 0x1017
223#define WM8962_WRITE_SEQUENCER_24 0x1018
224#define WM8962_WRITE_SEQUENCER_25 0x1019
225#define WM8962_WRITE_SEQUENCER_26 0x101A
226#define WM8962_WRITE_SEQUENCER_27 0x101B
227#define WM8962_WRITE_SEQUENCER_28 0x101C
228#define WM8962_WRITE_SEQUENCER_29 0x101D
229#define WM8962_WRITE_SEQUENCER_30 0x101E
230#define WM8962_WRITE_SEQUENCER_31 0x101F
231#define WM8962_WRITE_SEQUENCER_32 0x1020
232#define WM8962_WRITE_SEQUENCER_33 0x1021
233#define WM8962_WRITE_SEQUENCER_34 0x1022
234#define WM8962_WRITE_SEQUENCER_35 0x1023
235#define WM8962_WRITE_SEQUENCER_36 0x1024
236#define WM8962_WRITE_SEQUENCER_37 0x1025
237#define WM8962_WRITE_SEQUENCER_38 0x1026
238#define WM8962_WRITE_SEQUENCER_39 0x1027
239#define WM8962_WRITE_SEQUENCER_40 0x1028
240#define WM8962_WRITE_SEQUENCER_41 0x1029
241#define WM8962_WRITE_SEQUENCER_42 0x102A
242#define WM8962_WRITE_SEQUENCER_43 0x102B
243#define WM8962_WRITE_SEQUENCER_44 0x102C
244#define WM8962_WRITE_SEQUENCER_45 0x102D
245#define WM8962_WRITE_SEQUENCER_46 0x102E
246#define WM8962_WRITE_SEQUENCER_47 0x102F
247#define WM8962_WRITE_SEQUENCER_48 0x1030
248#define WM8962_WRITE_SEQUENCER_49 0x1031
249#define WM8962_WRITE_SEQUENCER_50 0x1032
250#define WM8962_WRITE_SEQUENCER_51 0x1033
251#define WM8962_WRITE_SEQUENCER_52 0x1034
252#define WM8962_WRITE_SEQUENCER_53 0x1035
253#define WM8962_WRITE_SEQUENCER_54 0x1036
254#define WM8962_WRITE_SEQUENCER_55 0x1037
255#define WM8962_WRITE_SEQUENCER_56 0x1038
256#define WM8962_WRITE_SEQUENCER_57 0x1039
257#define WM8962_WRITE_SEQUENCER_58 0x103A
258#define WM8962_WRITE_SEQUENCER_59 0x103B
259#define WM8962_WRITE_SEQUENCER_60 0x103C
260#define WM8962_WRITE_SEQUENCER_61 0x103D
261#define WM8962_WRITE_SEQUENCER_62 0x103E
262#define WM8962_WRITE_SEQUENCER_63 0x103F
263#define WM8962_WRITE_SEQUENCER_64 0x1040
264#define WM8962_WRITE_SEQUENCER_65 0x1041
265#define WM8962_WRITE_SEQUENCER_66 0x1042
266#define WM8962_WRITE_SEQUENCER_67 0x1043
267#define WM8962_WRITE_SEQUENCER_68 0x1044
268#define WM8962_WRITE_SEQUENCER_69 0x1045
269#define WM8962_WRITE_SEQUENCER_70 0x1046
270#define WM8962_WRITE_SEQUENCER_71 0x1047
271#define WM8962_WRITE_SEQUENCER_72 0x1048
272#define WM8962_WRITE_SEQUENCER_73 0x1049
273#define WM8962_WRITE_SEQUENCER_74 0x104A
274#define WM8962_WRITE_SEQUENCER_75 0x104B
275#define WM8962_WRITE_SEQUENCER_76 0x104C
276#define WM8962_WRITE_SEQUENCER_77 0x104D
277#define WM8962_WRITE_SEQUENCER_78 0x104E
278#define WM8962_WRITE_SEQUENCER_79 0x104F
279#define WM8962_WRITE_SEQUENCER_80 0x1050
280#define WM8962_WRITE_SEQUENCER_81 0x1051
281#define WM8962_WRITE_SEQUENCER_82 0x1052
282#define WM8962_WRITE_SEQUENCER_83 0x1053
283#define WM8962_WRITE_SEQUENCER_84 0x1054
284#define WM8962_WRITE_SEQUENCER_85 0x1055
285#define WM8962_WRITE_SEQUENCER_86 0x1056
286#define WM8962_WRITE_SEQUENCER_87 0x1057
287#define WM8962_WRITE_SEQUENCER_88 0x1058
288#define WM8962_WRITE_SEQUENCER_89 0x1059
289#define WM8962_WRITE_SEQUENCER_90 0x105A
290#define WM8962_WRITE_SEQUENCER_91 0x105B
291#define WM8962_WRITE_SEQUENCER_92 0x105C
292#define WM8962_WRITE_SEQUENCER_93 0x105D
293#define WM8962_WRITE_SEQUENCER_94 0x105E
294#define WM8962_WRITE_SEQUENCER_95 0x105F
295#define WM8962_WRITE_SEQUENCER_96 0x1060
296#define WM8962_WRITE_SEQUENCER_97 0x1061
297#define WM8962_WRITE_SEQUENCER_98 0x1062
298#define WM8962_WRITE_SEQUENCER_99 0x1063
299#define WM8962_WRITE_SEQUENCER_100 0x1064
300#define WM8962_WRITE_SEQUENCER_101 0x1065
301#define WM8962_WRITE_SEQUENCER_102 0x1066
302#define WM8962_WRITE_SEQUENCER_103 0x1067
303#define WM8962_WRITE_SEQUENCER_104 0x1068
304#define WM8962_WRITE_SEQUENCER_105 0x1069
305#define WM8962_WRITE_SEQUENCER_106 0x106A
306#define WM8962_WRITE_SEQUENCER_107 0x106B
307#define WM8962_WRITE_SEQUENCER_108 0x106C
308#define WM8962_WRITE_SEQUENCER_109 0x106D
309#define WM8962_WRITE_SEQUENCER_110 0x106E
310#define WM8962_WRITE_SEQUENCER_111 0x106F
311#define WM8962_WRITE_SEQUENCER_112 0x1070
312#define WM8962_WRITE_SEQUENCER_113 0x1071
313#define WM8962_WRITE_SEQUENCER_114 0x1072
314#define WM8962_WRITE_SEQUENCER_115 0x1073
315#define WM8962_WRITE_SEQUENCER_116 0x1074
316#define WM8962_WRITE_SEQUENCER_117 0x1075
317#define WM8962_WRITE_SEQUENCER_118 0x1076
318#define WM8962_WRITE_SEQUENCER_119 0x1077
319#define WM8962_WRITE_SEQUENCER_120 0x1078
320#define WM8962_WRITE_SEQUENCER_121 0x1079
321#define WM8962_WRITE_SEQUENCER_122 0x107A
322#define WM8962_WRITE_SEQUENCER_123 0x107B
323#define WM8962_WRITE_SEQUENCER_124 0x107C
324#define WM8962_WRITE_SEQUENCER_125 0x107D
325#define WM8962_WRITE_SEQUENCER_126 0x107E
326#define WM8962_WRITE_SEQUENCER_127 0x107F
327#define WM8962_WRITE_SEQUENCER_128 0x1080
328#define WM8962_WRITE_SEQUENCER_129 0x1081
329#define WM8962_WRITE_SEQUENCER_130 0x1082
330#define WM8962_WRITE_SEQUENCER_131 0x1083
331#define WM8962_WRITE_SEQUENCER_132 0x1084
332#define WM8962_WRITE_SEQUENCER_133 0x1085
333#define WM8962_WRITE_SEQUENCER_134 0x1086
334#define WM8962_WRITE_SEQUENCER_135 0x1087
335#define WM8962_WRITE_SEQUENCER_136 0x1088
336#define WM8962_WRITE_SEQUENCER_137 0x1089
337#define WM8962_WRITE_SEQUENCER_138 0x108A
338#define WM8962_WRITE_SEQUENCER_139 0x108B
339#define WM8962_WRITE_SEQUENCER_140 0x108C
340#define WM8962_WRITE_SEQUENCER_141 0x108D
341#define WM8962_WRITE_SEQUENCER_142 0x108E
342#define WM8962_WRITE_SEQUENCER_143 0x108F
343#define WM8962_WRITE_SEQUENCER_144 0x1090
344#define WM8962_WRITE_SEQUENCER_145 0x1091
345#define WM8962_WRITE_SEQUENCER_146 0x1092
346#define WM8962_WRITE_SEQUENCER_147 0x1093
347#define WM8962_WRITE_SEQUENCER_148 0x1094
348#define WM8962_WRITE_SEQUENCER_149 0x1095
349#define WM8962_WRITE_SEQUENCER_150 0x1096
350#define WM8962_WRITE_SEQUENCER_151 0x1097
351#define WM8962_WRITE_SEQUENCER_152 0x1098
352#define WM8962_WRITE_SEQUENCER_153 0x1099
353#define WM8962_WRITE_SEQUENCER_154 0x109A
354#define WM8962_WRITE_SEQUENCER_155 0x109B
355#define WM8962_WRITE_SEQUENCER_156 0x109C
356#define WM8962_WRITE_SEQUENCER_157 0x109D
357#define WM8962_WRITE_SEQUENCER_158 0x109E
358#define WM8962_WRITE_SEQUENCER_159 0x109F
359#define WM8962_WRITE_SEQUENCER_160 0x10A0
360#define WM8962_WRITE_SEQUENCER_161 0x10A1
361#define WM8962_WRITE_SEQUENCER_162 0x10A2
362#define WM8962_WRITE_SEQUENCER_163 0x10A3
363#define WM8962_WRITE_SEQUENCER_164 0x10A4
364#define WM8962_WRITE_SEQUENCER_165 0x10A5
365#define WM8962_WRITE_SEQUENCER_166 0x10A6
366#define WM8962_WRITE_SEQUENCER_167 0x10A7
367#define WM8962_WRITE_SEQUENCER_168 0x10A8
368#define WM8962_WRITE_SEQUENCER_169 0x10A9
369#define WM8962_WRITE_SEQUENCER_170 0x10AA
370#define WM8962_WRITE_SEQUENCER_171 0x10AB
371#define WM8962_WRITE_SEQUENCER_172 0x10AC
372#define WM8962_WRITE_SEQUENCER_173 0x10AD
373#define WM8962_WRITE_SEQUENCER_174 0x10AE
374#define WM8962_WRITE_SEQUENCER_175 0x10AF
375#define WM8962_WRITE_SEQUENCER_176 0x10B0
376#define WM8962_WRITE_SEQUENCER_177 0x10B1
377#define WM8962_WRITE_SEQUENCER_178 0x10B2
378#define WM8962_WRITE_SEQUENCER_179 0x10B3
379#define WM8962_WRITE_SEQUENCER_180 0x10B4
380#define WM8962_WRITE_SEQUENCER_181 0x10B5
381#define WM8962_WRITE_SEQUENCER_182 0x10B6
382#define WM8962_WRITE_SEQUENCER_183 0x10B7
383#define WM8962_WRITE_SEQUENCER_184 0x10B8
384#define WM8962_WRITE_SEQUENCER_185 0x10B9
385#define WM8962_WRITE_SEQUENCER_186 0x10BA
386#define WM8962_WRITE_SEQUENCER_187 0x10BB
387#define WM8962_WRITE_SEQUENCER_188 0x10BC
388#define WM8962_WRITE_SEQUENCER_189 0x10BD
389#define WM8962_WRITE_SEQUENCER_190 0x10BE
390#define WM8962_WRITE_SEQUENCER_191 0x10BF
391#define WM8962_WRITE_SEQUENCER_192 0x10C0
392#define WM8962_WRITE_SEQUENCER_193 0x10C1
393#define WM8962_WRITE_SEQUENCER_194 0x10C2
394#define WM8962_WRITE_SEQUENCER_195 0x10C3
395#define WM8962_WRITE_SEQUENCER_196 0x10C4
396#define WM8962_WRITE_SEQUENCER_197 0x10C5
397#define WM8962_WRITE_SEQUENCER_198 0x10C6
398#define WM8962_WRITE_SEQUENCER_199 0x10C7
399#define WM8962_WRITE_SEQUENCER_200 0x10C8
400#define WM8962_WRITE_SEQUENCER_201 0x10C9
401#define WM8962_WRITE_SEQUENCER_202 0x10CA
402#define WM8962_WRITE_SEQUENCER_203 0x10CB
403#define WM8962_WRITE_SEQUENCER_204 0x10CC
404#define WM8962_WRITE_SEQUENCER_205 0x10CD
405#define WM8962_WRITE_SEQUENCER_206 0x10CE
406#define WM8962_WRITE_SEQUENCER_207 0x10CF
407#define WM8962_WRITE_SEQUENCER_208 0x10D0
408#define WM8962_WRITE_SEQUENCER_209 0x10D1
409#define WM8962_WRITE_SEQUENCER_210 0x10D2
410#define WM8962_WRITE_SEQUENCER_211 0x10D3
411#define WM8962_WRITE_SEQUENCER_212 0x10D4
412#define WM8962_WRITE_SEQUENCER_213 0x10D5
413#define WM8962_WRITE_SEQUENCER_214 0x10D6
414#define WM8962_WRITE_SEQUENCER_215 0x10D7
415#define WM8962_WRITE_SEQUENCER_216 0x10D8
416#define WM8962_WRITE_SEQUENCER_217 0x10D9
417#define WM8962_WRITE_SEQUENCER_218 0x10DA
418#define WM8962_WRITE_SEQUENCER_219 0x10DB
419#define WM8962_WRITE_SEQUENCER_220 0x10DC
420#define WM8962_WRITE_SEQUENCER_221 0x10DD
421#define WM8962_WRITE_SEQUENCER_222 0x10DE
422#define WM8962_WRITE_SEQUENCER_223 0x10DF
423#define WM8962_WRITE_SEQUENCER_224 0x10E0
424#define WM8962_WRITE_SEQUENCER_225 0x10E1
425#define WM8962_WRITE_SEQUENCER_226 0x10E2
426#define WM8962_WRITE_SEQUENCER_227 0x10E3
427#define WM8962_WRITE_SEQUENCER_228 0x10E4
428#define WM8962_WRITE_SEQUENCER_229 0x10E5
429#define WM8962_WRITE_SEQUENCER_230 0x10E6
430#define WM8962_WRITE_SEQUENCER_231 0x10E7
431#define WM8962_WRITE_SEQUENCER_232 0x10E8
432#define WM8962_WRITE_SEQUENCER_233 0x10E9
433#define WM8962_WRITE_SEQUENCER_234 0x10EA
434#define WM8962_WRITE_SEQUENCER_235 0x10EB
435#define WM8962_WRITE_SEQUENCER_236 0x10EC
436#define WM8962_WRITE_SEQUENCER_237 0x10ED
437#define WM8962_WRITE_SEQUENCER_238 0x10EE
438#define WM8962_WRITE_SEQUENCER_239 0x10EF
439#define WM8962_WRITE_SEQUENCER_240 0x10F0
440#define WM8962_WRITE_SEQUENCER_241 0x10F1
441#define WM8962_WRITE_SEQUENCER_242 0x10F2
442#define WM8962_WRITE_SEQUENCER_243 0x10F3
443#define WM8962_WRITE_SEQUENCER_244 0x10F4
444#define WM8962_WRITE_SEQUENCER_245 0x10F5
445#define WM8962_WRITE_SEQUENCER_246 0x10F6
446#define WM8962_WRITE_SEQUENCER_247 0x10F7
447#define WM8962_WRITE_SEQUENCER_248 0x10F8
448#define WM8962_WRITE_SEQUENCER_249 0x10F9
449#define WM8962_WRITE_SEQUENCER_250 0x10FA
450#define WM8962_WRITE_SEQUENCER_251 0x10FB
451#define WM8962_WRITE_SEQUENCER_252 0x10FC
452#define WM8962_WRITE_SEQUENCER_253 0x10FD
453#define WM8962_WRITE_SEQUENCER_254 0x10FE
454#define WM8962_WRITE_SEQUENCER_255 0x10FF
455#define WM8962_WRITE_SEQUENCER_256 0x1100
456#define WM8962_WRITE_SEQUENCER_257 0x1101
457#define WM8962_WRITE_SEQUENCER_258 0x1102
458#define WM8962_WRITE_SEQUENCER_259 0x1103
459#define WM8962_WRITE_SEQUENCER_260 0x1104
460#define WM8962_WRITE_SEQUENCER_261 0x1105
461#define WM8962_WRITE_SEQUENCER_262 0x1106
462#define WM8962_WRITE_SEQUENCER_263 0x1107
463#define WM8962_WRITE_SEQUENCER_264 0x1108
464#define WM8962_WRITE_SEQUENCER_265 0x1109
465#define WM8962_WRITE_SEQUENCER_266 0x110A
466#define WM8962_WRITE_SEQUENCER_267 0x110B
467#define WM8962_WRITE_SEQUENCER_268 0x110C
468#define WM8962_WRITE_SEQUENCER_269 0x110D
469#define WM8962_WRITE_SEQUENCER_270 0x110E
470#define WM8962_WRITE_SEQUENCER_271 0x110F
471#define WM8962_WRITE_SEQUENCER_272 0x1110
472#define WM8962_WRITE_SEQUENCER_273 0x1111
473#define WM8962_WRITE_SEQUENCER_274 0x1112
474#define WM8962_WRITE_SEQUENCER_275 0x1113
475#define WM8962_WRITE_SEQUENCER_276 0x1114
476#define WM8962_WRITE_SEQUENCER_277 0x1115
477#define WM8962_WRITE_SEQUENCER_278 0x1116
478#define WM8962_WRITE_SEQUENCER_279 0x1117
479#define WM8962_WRITE_SEQUENCER_280 0x1118
480#define WM8962_WRITE_SEQUENCER_281 0x1119
481#define WM8962_WRITE_SEQUENCER_282 0x111A
482#define WM8962_WRITE_SEQUENCER_283 0x111B
483#define WM8962_WRITE_SEQUENCER_284 0x111C
484#define WM8962_WRITE_SEQUENCER_285 0x111D
485#define WM8962_WRITE_SEQUENCER_286 0x111E
486#define WM8962_WRITE_SEQUENCER_287 0x111F
487#define WM8962_WRITE_SEQUENCER_288 0x1120
488#define WM8962_WRITE_SEQUENCER_289 0x1121
489#define WM8962_WRITE_SEQUENCER_290 0x1122
490#define WM8962_WRITE_SEQUENCER_291 0x1123
491#define WM8962_WRITE_SEQUENCER_292 0x1124
492#define WM8962_WRITE_SEQUENCER_293 0x1125
493#define WM8962_WRITE_SEQUENCER_294 0x1126
494#define WM8962_WRITE_SEQUENCER_295 0x1127
495#define WM8962_WRITE_SEQUENCER_296 0x1128
496#define WM8962_WRITE_SEQUENCER_297 0x1129
497#define WM8962_WRITE_SEQUENCER_298 0x112A
498#define WM8962_WRITE_SEQUENCER_299 0x112B
499#define WM8962_WRITE_SEQUENCER_300 0x112C
500#define WM8962_WRITE_SEQUENCER_301 0x112D
501#define WM8962_WRITE_SEQUENCER_302 0x112E
502#define WM8962_WRITE_SEQUENCER_303 0x112F
503#define WM8962_WRITE_SEQUENCER_304 0x1130
504#define WM8962_WRITE_SEQUENCER_305 0x1131
505#define WM8962_WRITE_SEQUENCER_306 0x1132
506#define WM8962_WRITE_SEQUENCER_307 0x1133
507#define WM8962_WRITE_SEQUENCER_308 0x1134
508#define WM8962_WRITE_SEQUENCER_309 0x1135
509#define WM8962_WRITE_SEQUENCER_310 0x1136
510#define WM8962_WRITE_SEQUENCER_311 0x1137
511#define WM8962_WRITE_SEQUENCER_312 0x1138
512#define WM8962_WRITE_SEQUENCER_313 0x1139
513#define WM8962_WRITE_SEQUENCER_314 0x113A
514#define WM8962_WRITE_SEQUENCER_315 0x113B
515#define WM8962_WRITE_SEQUENCER_316 0x113C
516#define WM8962_WRITE_SEQUENCER_317 0x113D
517#define WM8962_WRITE_SEQUENCER_318 0x113E
518#define WM8962_WRITE_SEQUENCER_319 0x113F
519#define WM8962_WRITE_SEQUENCER_320 0x1140
520#define WM8962_WRITE_SEQUENCER_321 0x1141
521#define WM8962_WRITE_SEQUENCER_322 0x1142
522#define WM8962_WRITE_SEQUENCER_323 0x1143
523#define WM8962_WRITE_SEQUENCER_324 0x1144
524#define WM8962_WRITE_SEQUENCER_325 0x1145
525#define WM8962_WRITE_SEQUENCER_326 0x1146
526#define WM8962_WRITE_SEQUENCER_327 0x1147
527#define WM8962_WRITE_SEQUENCER_328 0x1148
528#define WM8962_WRITE_SEQUENCER_329 0x1149
529#define WM8962_WRITE_SEQUENCER_330 0x114A
530#define WM8962_WRITE_SEQUENCER_331 0x114B
531#define WM8962_WRITE_SEQUENCER_332 0x114C
532#define WM8962_WRITE_SEQUENCER_333 0x114D
533#define WM8962_WRITE_SEQUENCER_334 0x114E
534#define WM8962_WRITE_SEQUENCER_335 0x114F
535#define WM8962_WRITE_SEQUENCER_336 0x1150
536#define WM8962_WRITE_SEQUENCER_337 0x1151
537#define WM8962_WRITE_SEQUENCER_338 0x1152
538#define WM8962_WRITE_SEQUENCER_339 0x1153
539#define WM8962_WRITE_SEQUENCER_340 0x1154
540#define WM8962_WRITE_SEQUENCER_341 0x1155
541#define WM8962_WRITE_SEQUENCER_342 0x1156
542#define WM8962_WRITE_SEQUENCER_343 0x1157
543#define WM8962_WRITE_SEQUENCER_344 0x1158
544#define WM8962_WRITE_SEQUENCER_345 0x1159
545#define WM8962_WRITE_SEQUENCER_346 0x115A
546#define WM8962_WRITE_SEQUENCER_347 0x115B
547#define WM8962_WRITE_SEQUENCER_348 0x115C
548#define WM8962_WRITE_SEQUENCER_349 0x115D
549#define WM8962_WRITE_SEQUENCER_350 0x115E
550#define WM8962_WRITE_SEQUENCER_351 0x115F
551#define WM8962_WRITE_SEQUENCER_352 0x1160
552#define WM8962_WRITE_SEQUENCER_353 0x1161
553#define WM8962_WRITE_SEQUENCER_354 0x1162
554#define WM8962_WRITE_SEQUENCER_355 0x1163
555#define WM8962_WRITE_SEQUENCER_356 0x1164
556#define WM8962_WRITE_SEQUENCER_357 0x1165
557#define WM8962_WRITE_SEQUENCER_358 0x1166
558#define WM8962_WRITE_SEQUENCER_359 0x1167
559#define WM8962_WRITE_SEQUENCER_360 0x1168
560#define WM8962_WRITE_SEQUENCER_361 0x1169
561#define WM8962_WRITE_SEQUENCER_362 0x116A
562#define WM8962_WRITE_SEQUENCER_363 0x116B
563#define WM8962_WRITE_SEQUENCER_364 0x116C
564#define WM8962_WRITE_SEQUENCER_365 0x116D
565#define WM8962_WRITE_SEQUENCER_366 0x116E
566#define WM8962_WRITE_SEQUENCER_367 0x116F
567#define WM8962_WRITE_SEQUENCER_368 0x1170
568#define WM8962_WRITE_SEQUENCER_369 0x1171
569#define WM8962_WRITE_SEQUENCER_370 0x1172
570#define WM8962_WRITE_SEQUENCER_371 0x1173
571#define WM8962_WRITE_SEQUENCER_372 0x1174
572#define WM8962_WRITE_SEQUENCER_373 0x1175
573#define WM8962_WRITE_SEQUENCER_374 0x1176
574#define WM8962_WRITE_SEQUENCER_375 0x1177
575#define WM8962_WRITE_SEQUENCER_376 0x1178
576#define WM8962_WRITE_SEQUENCER_377 0x1179
577#define WM8962_WRITE_SEQUENCER_378 0x117A
578#define WM8962_WRITE_SEQUENCER_379 0x117B
579#define WM8962_WRITE_SEQUENCER_380 0x117C
580#define WM8962_WRITE_SEQUENCER_381 0x117D
581#define WM8962_WRITE_SEQUENCER_382 0x117E
582#define WM8962_WRITE_SEQUENCER_383 0x117F
583#define WM8962_WRITE_SEQUENCER_384 0x1180
584#define WM8962_WRITE_SEQUENCER_385 0x1181
585#define WM8962_WRITE_SEQUENCER_386 0x1182
586#define WM8962_WRITE_SEQUENCER_387 0x1183
587#define WM8962_WRITE_SEQUENCER_388 0x1184
588#define WM8962_WRITE_SEQUENCER_389 0x1185
589#define WM8962_WRITE_SEQUENCER_390 0x1186
590#define WM8962_WRITE_SEQUENCER_391 0x1187
591#define WM8962_WRITE_SEQUENCER_392 0x1188
592#define WM8962_WRITE_SEQUENCER_393 0x1189
593#define WM8962_WRITE_SEQUENCER_394 0x118A
594#define WM8962_WRITE_SEQUENCER_395 0x118B
595#define WM8962_WRITE_SEQUENCER_396 0x118C
596#define WM8962_WRITE_SEQUENCER_397 0x118D
597#define WM8962_WRITE_SEQUENCER_398 0x118E
598#define WM8962_WRITE_SEQUENCER_399 0x118F
599#define WM8962_WRITE_SEQUENCER_400 0x1190
600#define WM8962_WRITE_SEQUENCER_401 0x1191
601#define WM8962_WRITE_SEQUENCER_402 0x1192
602#define WM8962_WRITE_SEQUENCER_403 0x1193
603#define WM8962_WRITE_SEQUENCER_404 0x1194
604#define WM8962_WRITE_SEQUENCER_405 0x1195
605#define WM8962_WRITE_SEQUENCER_406 0x1196
606#define WM8962_WRITE_SEQUENCER_407 0x1197
607#define WM8962_WRITE_SEQUENCER_408 0x1198
608#define WM8962_WRITE_SEQUENCER_409 0x1199
609#define WM8962_WRITE_SEQUENCER_410 0x119A
610#define WM8962_WRITE_SEQUENCER_411 0x119B
611#define WM8962_WRITE_SEQUENCER_412 0x119C
612#define WM8962_WRITE_SEQUENCER_413 0x119D
613#define WM8962_WRITE_SEQUENCER_414 0x119E
614#define WM8962_WRITE_SEQUENCER_415 0x119F
615#define WM8962_WRITE_SEQUENCER_416 0x11A0
616#define WM8962_WRITE_SEQUENCER_417 0x11A1
617#define WM8962_WRITE_SEQUENCER_418 0x11A2
618#define WM8962_WRITE_SEQUENCER_419 0x11A3
619#define WM8962_WRITE_SEQUENCER_420 0x11A4
620#define WM8962_WRITE_SEQUENCER_421 0x11A5
621#define WM8962_WRITE_SEQUENCER_422 0x11A6
622#define WM8962_WRITE_SEQUENCER_423 0x11A7
623#define WM8962_WRITE_SEQUENCER_424 0x11A8
624#define WM8962_WRITE_SEQUENCER_425 0x11A9
625#define WM8962_WRITE_SEQUENCER_426 0x11AA
626#define WM8962_WRITE_SEQUENCER_427 0x11AB
627#define WM8962_WRITE_SEQUENCER_428 0x11AC
628#define WM8962_WRITE_SEQUENCER_429 0x11AD
629#define WM8962_WRITE_SEQUENCER_430 0x11AE
630#define WM8962_WRITE_SEQUENCER_431 0x11AF
631#define WM8962_WRITE_SEQUENCER_432 0x11B0
632#define WM8962_WRITE_SEQUENCER_433 0x11B1
633#define WM8962_WRITE_SEQUENCER_434 0x11B2
634#define WM8962_WRITE_SEQUENCER_435 0x11B3
635#define WM8962_WRITE_SEQUENCER_436 0x11B4
636#define WM8962_WRITE_SEQUENCER_437 0x11B5
637#define WM8962_WRITE_SEQUENCER_438 0x11B6
638#define WM8962_WRITE_SEQUENCER_439 0x11B7
639#define WM8962_WRITE_SEQUENCER_440 0x11B8
640#define WM8962_WRITE_SEQUENCER_441 0x11B9
641#define WM8962_WRITE_SEQUENCER_442 0x11BA
642#define WM8962_WRITE_SEQUENCER_443 0x11BB
643#define WM8962_WRITE_SEQUENCER_444 0x11BC
644#define WM8962_WRITE_SEQUENCER_445 0x11BD
645#define WM8962_WRITE_SEQUENCER_446 0x11BE
646#define WM8962_WRITE_SEQUENCER_447 0x11BF
647#define WM8962_WRITE_SEQUENCER_448 0x11C0
648#define WM8962_WRITE_SEQUENCER_449 0x11C1
649#define WM8962_WRITE_SEQUENCER_450 0x11C2
650#define WM8962_WRITE_SEQUENCER_451 0x11C3
651#define WM8962_WRITE_SEQUENCER_452 0x11C4
652#define WM8962_WRITE_SEQUENCER_453 0x11C5
653#define WM8962_WRITE_SEQUENCER_454 0x11C6
654#define WM8962_WRITE_SEQUENCER_455 0x11C7
655#define WM8962_WRITE_SEQUENCER_456 0x11C8
656#define WM8962_WRITE_SEQUENCER_457 0x11C9
657#define WM8962_WRITE_SEQUENCER_458 0x11CA
658#define WM8962_WRITE_SEQUENCER_459 0x11CB
659#define WM8962_WRITE_SEQUENCER_460 0x11CC
660#define WM8962_WRITE_SEQUENCER_461 0x11CD
661#define WM8962_WRITE_SEQUENCER_462 0x11CE
662#define WM8962_WRITE_SEQUENCER_463 0x11CF
663#define WM8962_WRITE_SEQUENCER_464 0x11D0
664#define WM8962_WRITE_SEQUENCER_465 0x11D1
665#define WM8962_WRITE_SEQUENCER_466 0x11D2
666#define WM8962_WRITE_SEQUENCER_467 0x11D3
667#define WM8962_WRITE_SEQUENCER_468 0x11D4
668#define WM8962_WRITE_SEQUENCER_469 0x11D5
669#define WM8962_WRITE_SEQUENCER_470 0x11D6
670#define WM8962_WRITE_SEQUENCER_471 0x11D7
671#define WM8962_WRITE_SEQUENCER_472 0x11D8
672#define WM8962_WRITE_SEQUENCER_473 0x11D9
673#define WM8962_WRITE_SEQUENCER_474 0x11DA
674#define WM8962_WRITE_SEQUENCER_475 0x11DB
675#define WM8962_WRITE_SEQUENCER_476 0x11DC
676#define WM8962_WRITE_SEQUENCER_477 0x11DD
677#define WM8962_WRITE_SEQUENCER_478 0x11DE
678#define WM8962_WRITE_SEQUENCER_479 0x11DF
679#define WM8962_WRITE_SEQUENCER_480 0x11E0
680#define WM8962_WRITE_SEQUENCER_481 0x11E1
681#define WM8962_WRITE_SEQUENCER_482 0x11E2
682#define WM8962_WRITE_SEQUENCER_483 0x11E3
683#define WM8962_WRITE_SEQUENCER_484 0x11E4
684#define WM8962_WRITE_SEQUENCER_485 0x11E5
685#define WM8962_WRITE_SEQUENCER_486 0x11E6
686#define WM8962_WRITE_SEQUENCER_487 0x11E7
687#define WM8962_WRITE_SEQUENCER_488 0x11E8
688#define WM8962_WRITE_SEQUENCER_489 0x11E9
689#define WM8962_WRITE_SEQUENCER_490 0x11EA
690#define WM8962_WRITE_SEQUENCER_491 0x11EB
691#define WM8962_WRITE_SEQUENCER_492 0x11EC
692#define WM8962_WRITE_SEQUENCER_493 0x11ED
693#define WM8962_WRITE_SEQUENCER_494 0x11EE
694#define WM8962_WRITE_SEQUENCER_495 0x11EF
695#define WM8962_WRITE_SEQUENCER_496 0x11F0
696#define WM8962_WRITE_SEQUENCER_497 0x11F1
697#define WM8962_WRITE_SEQUENCER_498 0x11F2
698#define WM8962_WRITE_SEQUENCER_499 0x11F3
699#define WM8962_WRITE_SEQUENCER_500 0x11F4
700#define WM8962_WRITE_SEQUENCER_501 0x11F5
701#define WM8962_WRITE_SEQUENCER_502 0x11F6
702#define WM8962_WRITE_SEQUENCER_503 0x11F7
703#define WM8962_WRITE_SEQUENCER_504 0x11F8
704#define WM8962_WRITE_SEQUENCER_505 0x11F9
705#define WM8962_WRITE_SEQUENCER_506 0x11FA
706#define WM8962_WRITE_SEQUENCER_507 0x11FB
707#define WM8962_WRITE_SEQUENCER_508 0x11FC
708#define WM8962_WRITE_SEQUENCER_509 0x11FD
709#define WM8962_WRITE_SEQUENCER_510 0x11FE
710#define WM8962_WRITE_SEQUENCER_511 0x11FF
711#define WM8962_DSP2_INSTRUCTION_RAM_0 0x2000
712#define WM8962_DSP2_ADDRESS_RAM_2 0x2400
713#define WM8962_DSP2_ADDRESS_RAM_1 0x2401
714#define WM8962_DSP2_ADDRESS_RAM_0 0x2402
715#define WM8962_DSP2_DATA1_RAM_1 0x3000
716#define WM8962_DSP2_DATA1_RAM_0 0x3001
717#define WM8962_DSP2_DATA2_RAM_1 0x3400
718#define WM8962_DSP2_DATA2_RAM_0 0x3401
719#define WM8962_DSP2_DATA3_RAM_1 0x3800
720#define WM8962_DSP2_DATA3_RAM_0 0x3801
721#define WM8962_DSP2_COEFF_RAM_0 0x3C00
722#define WM8962_RETUNEADC_SHARED_COEFF_1 0x4000
723#define WM8962_RETUNEADC_SHARED_COEFF_0 0x4001
724#define WM8962_RETUNEDAC_SHARED_COEFF_1 0x4002
725#define WM8962_RETUNEDAC_SHARED_COEFF_0 0x4003
726#define WM8962_SOUNDSTAGE_ENABLES_1 0x4004
727#define WM8962_SOUNDSTAGE_ENABLES_0 0x4005
728#define WM8962_HDBASS_AI_1 0x4200
729#define WM8962_HDBASS_AI_0 0x4201
730#define WM8962_HDBASS_AR_1 0x4202
731#define WM8962_HDBASS_AR_0 0x4203
732#define WM8962_HDBASS_B_1 0x4204
733#define WM8962_HDBASS_B_0 0x4205
734#define WM8962_HDBASS_K_1 0x4206
735#define WM8962_HDBASS_K_0 0x4207
736#define WM8962_HDBASS_N1_1 0x4208
737#define WM8962_HDBASS_N1_0 0x4209
738#define WM8962_HDBASS_N2_1 0x420A
739#define WM8962_HDBASS_N2_0 0x420B
740#define WM8962_HDBASS_N3_1 0x420C
741#define WM8962_HDBASS_N3_0 0x420D
742#define WM8962_HDBASS_N4_1 0x420E
743#define WM8962_HDBASS_N4_0 0x420F
744#define WM8962_HDBASS_N5_1 0x4210
745#define WM8962_HDBASS_N5_0 0x4211
746#define WM8962_HDBASS_X1_1 0x4212
747#define WM8962_HDBASS_X1_0 0x4213
748#define WM8962_HDBASS_X2_1 0x4214
749#define WM8962_HDBASS_X2_0 0x4215
750#define WM8962_HDBASS_X3_1 0x4216
751#define WM8962_HDBASS_X3_0 0x4217
752#define WM8962_HDBASS_ATK_1 0x4218
753#define WM8962_HDBASS_ATK_0 0x4219
754#define WM8962_HDBASS_DCY_1 0x421A
755#define WM8962_HDBASS_DCY_0 0x421B
756#define WM8962_HDBASS_PG_1 0x421C
757#define WM8962_HDBASS_PG_0 0x421D
758#define WM8962_HPF_C_1 0x4400
759#define WM8962_HPF_C_0 0x4401
760#define WM8962_ADCL_RETUNE_C1_1 0x4600
761#define WM8962_ADCL_RETUNE_C1_0 0x4601
762#define WM8962_ADCL_RETUNE_C2_1 0x4602
763#define WM8962_ADCL_RETUNE_C2_0 0x4603
764#define WM8962_ADCL_RETUNE_C3_1 0x4604
765#define WM8962_ADCL_RETUNE_C3_0 0x4605
766#define WM8962_ADCL_RETUNE_C4_1 0x4606
767#define WM8962_ADCL_RETUNE_C4_0 0x4607
768#define WM8962_ADCL_RETUNE_C5_1 0x4608
769#define WM8962_ADCL_RETUNE_C5_0 0x4609
770#define WM8962_ADCL_RETUNE_C6_1 0x460A
771#define WM8962_ADCL_RETUNE_C6_0 0x460B
772#define WM8962_ADCL_RETUNE_C7_1 0x460C
773#define WM8962_ADCL_RETUNE_C7_0 0x460D
774#define WM8962_ADCL_RETUNE_C8_1 0x460E
775#define WM8962_ADCL_RETUNE_C8_0 0x460F
776#define WM8962_ADCL_RETUNE_C9_1 0x4610
777#define WM8962_ADCL_RETUNE_C9_0 0x4611
778#define WM8962_ADCL_RETUNE_C10_1 0x4612
779#define WM8962_ADCL_RETUNE_C10_0 0x4613
780#define WM8962_ADCL_RETUNE_C11_1 0x4614
781#define WM8962_ADCL_RETUNE_C11_0 0x4615
782#define WM8962_ADCL_RETUNE_C12_1 0x4616
783#define WM8962_ADCL_RETUNE_C12_0 0x4617
784#define WM8962_ADCL_RETUNE_C13_1 0x4618
785#define WM8962_ADCL_RETUNE_C13_0 0x4619
786#define WM8962_ADCL_RETUNE_C14_1 0x461A
787#define WM8962_ADCL_RETUNE_C14_0 0x461B
788#define WM8962_ADCL_RETUNE_C15_1 0x461C
789#define WM8962_ADCL_RETUNE_C15_0 0x461D
790#define WM8962_ADCL_RETUNE_C16_1 0x461E
791#define WM8962_ADCL_RETUNE_C16_0 0x461F
792#define WM8962_ADCL_RETUNE_C17_1 0x4620
793#define WM8962_ADCL_RETUNE_C17_0 0x4621
794#define WM8962_ADCL_RETUNE_C18_1 0x4622
795#define WM8962_ADCL_RETUNE_C18_0 0x4623
796#define WM8962_ADCL_RETUNE_C19_1 0x4624
797#define WM8962_ADCL_RETUNE_C19_0 0x4625
798#define WM8962_ADCL_RETUNE_C20_1 0x4626
799#define WM8962_ADCL_RETUNE_C20_0 0x4627
800#define WM8962_ADCL_RETUNE_C21_1 0x4628
801#define WM8962_ADCL_RETUNE_C21_0 0x4629
802#define WM8962_ADCL_RETUNE_C22_1 0x462A
803#define WM8962_ADCL_RETUNE_C22_0 0x462B
804#define WM8962_ADCL_RETUNE_C23_1 0x462C
805#define WM8962_ADCL_RETUNE_C23_0 0x462D
806#define WM8962_ADCL_RETUNE_C24_1 0x462E
807#define WM8962_ADCL_RETUNE_C24_0 0x462F
808#define WM8962_ADCL_RETUNE_C25_1 0x4630
809#define WM8962_ADCL_RETUNE_C25_0 0x4631
810#define WM8962_ADCL_RETUNE_C26_1 0x4632
811#define WM8962_ADCL_RETUNE_C26_0 0x4633
812#define WM8962_ADCL_RETUNE_C27_1 0x4634
813#define WM8962_ADCL_RETUNE_C27_0 0x4635
814#define WM8962_ADCL_RETUNE_C28_1 0x4636
815#define WM8962_ADCL_RETUNE_C28_0 0x4637
816#define WM8962_ADCL_RETUNE_C29_1 0x4638
817#define WM8962_ADCL_RETUNE_C29_0 0x4639
818#define WM8962_ADCL_RETUNE_C30_1 0x463A
819#define WM8962_ADCL_RETUNE_C30_0 0x463B
820#define WM8962_ADCL_RETUNE_C31_1 0x463C
821#define WM8962_ADCL_RETUNE_C31_0 0x463D
822#define WM8962_ADCL_RETUNE_C32_1 0x463E
823#define WM8962_ADCL_RETUNE_C32_0 0x463F
824#define WM8962_RETUNEADC_PG2_1 0x4800
825#define WM8962_RETUNEADC_PG2_0 0x4801
826#define WM8962_RETUNEADC_PG_1 0x4802
827#define WM8962_RETUNEADC_PG_0 0x4803
828#define WM8962_ADCR_RETUNE_C1_1 0x4A00
829#define WM8962_ADCR_RETUNE_C1_0 0x4A01
830#define WM8962_ADCR_RETUNE_C2_1 0x4A02
831#define WM8962_ADCR_RETUNE_C2_0 0x4A03
832#define WM8962_ADCR_RETUNE_C3_1 0x4A04
833#define WM8962_ADCR_RETUNE_C3_0 0x4A05
834#define WM8962_ADCR_RETUNE_C4_1 0x4A06
835#define WM8962_ADCR_RETUNE_C4_0 0x4A07
836#define WM8962_ADCR_RETUNE_C5_1 0x4A08
837#define WM8962_ADCR_RETUNE_C5_0 0x4A09
838#define WM8962_ADCR_RETUNE_C6_1 0x4A0A
839#define WM8962_ADCR_RETUNE_C6_0 0x4A0B
840#define WM8962_ADCR_RETUNE_C7_1 0x4A0C
841#define WM8962_ADCR_RETUNE_C7_0 0x4A0D
842#define WM8962_ADCR_RETUNE_C8_1 0x4A0E
843#define WM8962_ADCR_RETUNE_C8_0 0x4A0F
844#define WM8962_ADCR_RETUNE_C9_1 0x4A10
845#define WM8962_ADCR_RETUNE_C9_0 0x4A11
846#define WM8962_ADCR_RETUNE_C10_1 0x4A12
847#define WM8962_ADCR_RETUNE_C10_0 0x4A13
848#define WM8962_ADCR_RETUNE_C11_1 0x4A14
849#define WM8962_ADCR_RETUNE_C11_0 0x4A15
850#define WM8962_ADCR_RETUNE_C12_1 0x4A16
851#define WM8962_ADCR_RETUNE_C12_0 0x4A17
852#define WM8962_ADCR_RETUNE_C13_1 0x4A18
853#define WM8962_ADCR_RETUNE_C13_0 0x4A19
854#define WM8962_ADCR_RETUNE_C14_1 0x4A1A
855#define WM8962_ADCR_RETUNE_C14_0 0x4A1B
856#define WM8962_ADCR_RETUNE_C15_1 0x4A1C
857#define WM8962_ADCR_RETUNE_C15_0 0x4A1D
858#define WM8962_ADCR_RETUNE_C16_1 0x4A1E
859#define WM8962_ADCR_RETUNE_C16_0 0x4A1F
860#define WM8962_ADCR_RETUNE_C17_1 0x4A20
861#define WM8962_ADCR_RETUNE_C17_0 0x4A21
862#define WM8962_ADCR_RETUNE_C18_1 0x4A22
863#define WM8962_ADCR_RETUNE_C18_0 0x4A23
864#define WM8962_ADCR_RETUNE_C19_1 0x4A24
865#define WM8962_ADCR_RETUNE_C19_0 0x4A25
866#define WM8962_ADCR_RETUNE_C20_1 0x4A26
867#define WM8962_ADCR_RETUNE_C20_0 0x4A27
868#define WM8962_ADCR_RETUNE_C21_1 0x4A28
869#define WM8962_ADCR_RETUNE_C21_0 0x4A29
870#define WM8962_ADCR_RETUNE_C22_1 0x4A2A
871#define WM8962_ADCR_RETUNE_C22_0 0x4A2B
872#define WM8962_ADCR_RETUNE_C23_1 0x4A2C
873#define WM8962_ADCR_RETUNE_C23_0 0x4A2D
874#define WM8962_ADCR_RETUNE_C24_1 0x4A2E
875#define WM8962_ADCR_RETUNE_C24_0 0x4A2F
876#define WM8962_ADCR_RETUNE_C25_1 0x4A30
877#define WM8962_ADCR_RETUNE_C25_0 0x4A31
878#define WM8962_ADCR_RETUNE_C26_1 0x4A32
879#define WM8962_ADCR_RETUNE_C26_0 0x4A33
880#define WM8962_ADCR_RETUNE_C27_1 0x4A34
881#define WM8962_ADCR_RETUNE_C27_0 0x4A35
882#define WM8962_ADCR_RETUNE_C28_1 0x4A36
883#define WM8962_ADCR_RETUNE_C28_0 0x4A37
884#define WM8962_ADCR_RETUNE_C29_1 0x4A38
885#define WM8962_ADCR_RETUNE_C29_0 0x4A39
886#define WM8962_ADCR_RETUNE_C30_1 0x4A3A
887#define WM8962_ADCR_RETUNE_C30_0 0x4A3B
888#define WM8962_ADCR_RETUNE_C31_1 0x4A3C
889#define WM8962_ADCR_RETUNE_C31_0 0x4A3D
890#define WM8962_ADCR_RETUNE_C32_1 0x4A3E
891#define WM8962_ADCR_RETUNE_C32_0 0x4A3F
892#define WM8962_DACL_RETUNE_C1_1 0x4C00
893#define WM8962_DACL_RETUNE_C1_0 0x4C01
894#define WM8962_DACL_RETUNE_C2_1 0x4C02
895#define WM8962_DACL_RETUNE_C2_0 0x4C03
896#define WM8962_DACL_RETUNE_C3_1 0x4C04
897#define WM8962_DACL_RETUNE_C3_0 0x4C05
898#define WM8962_DACL_RETUNE_C4_1 0x4C06
899#define WM8962_DACL_RETUNE_C4_0 0x4C07
900#define WM8962_DACL_RETUNE_C5_1 0x4C08
901#define WM8962_DACL_RETUNE_C5_0 0x4C09
902#define WM8962_DACL_RETUNE_C6_1 0x4C0A
903#define WM8962_DACL_RETUNE_C6_0 0x4C0B
904#define WM8962_DACL_RETUNE_C7_1 0x4C0C
905#define WM8962_DACL_RETUNE_C7_0 0x4C0D
906#define WM8962_DACL_RETUNE_C8_1 0x4C0E
907#define WM8962_DACL_RETUNE_C8_0 0x4C0F
908#define WM8962_DACL_RETUNE_C9_1 0x4C10
909#define WM8962_DACL_RETUNE_C9_0 0x4C11
910#define WM8962_DACL_RETUNE_C10_1 0x4C12
911#define WM8962_DACL_RETUNE_C10_0 0x4C13
912#define WM8962_DACL_RETUNE_C11_1 0x4C14
913#define WM8962_DACL_RETUNE_C11_0 0x4C15
914#define WM8962_DACL_RETUNE_C12_1 0x4C16
915#define WM8962_DACL_RETUNE_C12_0 0x4C17
916#define WM8962_DACL_RETUNE_C13_1 0x4C18
917#define WM8962_DACL_RETUNE_C13_0 0x4C19
918#define WM8962_DACL_RETUNE_C14_1 0x4C1A
919#define WM8962_DACL_RETUNE_C14_0 0x4C1B
920#define WM8962_DACL_RETUNE_C15_1 0x4C1C
921#define WM8962_DACL_RETUNE_C15_0 0x4C1D
922#define WM8962_DACL_RETUNE_C16_1 0x4C1E
923#define WM8962_DACL_RETUNE_C16_0 0x4C1F
924#define WM8962_DACL_RETUNE_C17_1 0x4C20
925#define WM8962_DACL_RETUNE_C17_0 0x4C21
926#define WM8962_DACL_RETUNE_C18_1 0x4C22
927#define WM8962_DACL_RETUNE_C18_0 0x4C23
928#define WM8962_DACL_RETUNE_C19_1 0x4C24
929#define WM8962_DACL_RETUNE_C19_0 0x4C25
930#define WM8962_DACL_RETUNE_C20_1 0x4C26
931#define WM8962_DACL_RETUNE_C20_0 0x4C27
932#define WM8962_DACL_RETUNE_C21_1 0x4C28
933#define WM8962_DACL_RETUNE_C21_0 0x4C29
934#define WM8962_DACL_RETUNE_C22_1 0x4C2A
935#define WM8962_DACL_RETUNE_C22_0 0x4C2B
936#define WM8962_DACL_RETUNE_C23_1 0x4C2C
937#define WM8962_DACL_RETUNE_C23_0 0x4C2D
938#define WM8962_DACL_RETUNE_C24_1 0x4C2E
939#define WM8962_DACL_RETUNE_C24_0 0x4C2F
940#define WM8962_DACL_RETUNE_C25_1 0x4C30
941#define WM8962_DACL_RETUNE_C25_0 0x4C31
942#define WM8962_DACL_RETUNE_C26_1 0x4C32
943#define WM8962_DACL_RETUNE_C26_0 0x4C33
944#define WM8962_DACL_RETUNE_C27_1 0x4C34
945#define WM8962_DACL_RETUNE_C27_0 0x4C35
946#define WM8962_DACL_RETUNE_C28_1 0x4C36
947#define WM8962_DACL_RETUNE_C28_0 0x4C37
948#define WM8962_DACL_RETUNE_C29_1 0x4C38
949#define WM8962_DACL_RETUNE_C29_0 0x4C39
950#define WM8962_DACL_RETUNE_C30_1 0x4C3A
951#define WM8962_DACL_RETUNE_C30_0 0x4C3B
952#define WM8962_DACL_RETUNE_C31_1 0x4C3C
953#define WM8962_DACL_RETUNE_C31_0 0x4C3D
954#define WM8962_DACL_RETUNE_C32_1 0x4C3E
955#define WM8962_DACL_RETUNE_C32_0 0x4C3F
956#define WM8962_RETUNEDAC_PG2_1 0x4E00
957#define WM8962_RETUNEDAC_PG2_0 0x4E01
958#define WM8962_RETUNEDAC_PG_1 0x4E02
959#define WM8962_RETUNEDAC_PG_0 0x4E03
960#define WM8962_DACR_RETUNE_C1_1 0x5000
961#define WM8962_DACR_RETUNE_C1_0 0x5001
962#define WM8962_DACR_RETUNE_C2_1 0x5002
963#define WM8962_DACR_RETUNE_C2_0 0x5003
964#define WM8962_DACR_RETUNE_C3_1 0x5004
965#define WM8962_DACR_RETUNE_C3_0 0x5005
966#define WM8962_DACR_RETUNE_C4_1 0x5006
967#define WM8962_DACR_RETUNE_C4_0 0x5007
968#define WM8962_DACR_RETUNE_C5_1 0x5008
969#define WM8962_DACR_RETUNE_C5_0 0x5009
970#define WM8962_DACR_RETUNE_C6_1 0x500A
971#define WM8962_DACR_RETUNE_C6_0 0x500B
972#define WM8962_DACR_RETUNE_C7_1 0x500C
973#define WM8962_DACR_RETUNE_C7_0 0x500D
974#define WM8962_DACR_RETUNE_C8_1 0x500E
975#define WM8962_DACR_RETUNE_C8_0 0x500F
976#define WM8962_DACR_RETUNE_C9_1 0x5010
977#define WM8962_DACR_RETUNE_C9_0 0x5011
978#define WM8962_DACR_RETUNE_C10_1 0x5012
979#define WM8962_DACR_RETUNE_C10_0 0x5013
980#define WM8962_DACR_RETUNE_C11_1 0x5014
981#define WM8962_DACR_RETUNE_C11_0 0x5015
982#define WM8962_DACR_RETUNE_C12_1 0x5016
983#define WM8962_DACR_RETUNE_C12_0 0x5017
984#define WM8962_DACR_RETUNE_C13_1 0x5018
985#define WM8962_DACR_RETUNE_C13_0 0x5019
986#define WM8962_DACR_RETUNE_C14_1 0x501A
987#define WM8962_DACR_RETUNE_C14_0 0x501B
988#define WM8962_DACR_RETUNE_C15_1 0x501C
989#define WM8962_DACR_RETUNE_C15_0 0x501D
990#define WM8962_DACR_RETUNE_C16_1 0x501E
991#define WM8962_DACR_RETUNE_C16_0 0x501F
992#define WM8962_DACR_RETUNE_C17_1 0x5020
993#define WM8962_DACR_RETUNE_C17_0 0x5021
994#define WM8962_DACR_RETUNE_C18_1 0x5022
995#define WM8962_DACR_RETUNE_C18_0 0x5023
996#define WM8962_DACR_RETUNE_C19_1 0x5024
997#define WM8962_DACR_RETUNE_C19_0 0x5025
998#define WM8962_DACR_RETUNE_C20_1 0x5026
999#define WM8962_DACR_RETUNE_C20_0 0x5027
1000#define WM8962_DACR_RETUNE_C21_1 0x5028
1001#define WM8962_DACR_RETUNE_C21_0 0x5029
1002#define WM8962_DACR_RETUNE_C22_1 0x502A
1003#define WM8962_DACR_RETUNE_C22_0 0x502B
1004#define WM8962_DACR_RETUNE_C23_1 0x502C
1005#define WM8962_DACR_RETUNE_C23_0 0x502D
1006#define WM8962_DACR_RETUNE_C24_1 0x502E
1007#define WM8962_DACR_RETUNE_C24_0 0x502F
1008#define WM8962_DACR_RETUNE_C25_1 0x5030
1009#define WM8962_DACR_RETUNE_C25_0 0x5031
1010#define WM8962_DACR_RETUNE_C26_1 0x5032
1011#define WM8962_DACR_RETUNE_C26_0 0x5033
1012#define WM8962_DACR_RETUNE_C27_1 0x5034
1013#define WM8962_DACR_RETUNE_C27_0 0x5035
1014#define WM8962_DACR_RETUNE_C28_1 0x5036
1015#define WM8962_DACR_RETUNE_C28_0 0x5037
1016#define WM8962_DACR_RETUNE_C29_1 0x5038
1017#define WM8962_DACR_RETUNE_C29_0 0x5039
1018#define WM8962_DACR_RETUNE_C30_1 0x503A
1019#define WM8962_DACR_RETUNE_C30_0 0x503B
1020#define WM8962_DACR_RETUNE_C31_1 0x503C
1021#define WM8962_DACR_RETUNE_C31_0 0x503D
1022#define WM8962_DACR_RETUNE_C32_1 0x503E
1023#define WM8962_DACR_RETUNE_C32_0 0x503F
1024#define WM8962_VSS_XHD2_1 0x5200
1025#define WM8962_VSS_XHD2_0 0x5201
1026#define WM8962_VSS_XHD3_1 0x5202
1027#define WM8962_VSS_XHD3_0 0x5203
1028#define WM8962_VSS_XHN1_1 0x5204
1029#define WM8962_VSS_XHN1_0 0x5205
1030#define WM8962_VSS_XHN2_1 0x5206
1031#define WM8962_VSS_XHN2_0 0x5207
1032#define WM8962_VSS_XHN3_1 0x5208
1033#define WM8962_VSS_XHN3_0 0x5209
1034#define WM8962_VSS_XLA_1 0x520A
1035#define WM8962_VSS_XLA_0 0x520B
1036#define WM8962_VSS_XLB_1 0x520C
1037#define WM8962_VSS_XLB_0 0x520D
1038#define WM8962_VSS_XLG_1 0x520E
1039#define WM8962_VSS_XLG_0 0x520F
1040#define WM8962_VSS_PG2_1 0x5210
1041#define WM8962_VSS_PG2_0 0x5211
1042#define WM8962_VSS_PG_1 0x5212
1043#define WM8962_VSS_PG_0 0x5213
1044#define WM8962_VSS_XTD1_1 0x5214
1045#define WM8962_VSS_XTD1_0 0x5215
1046#define WM8962_VSS_XTD2_1 0x5216
1047#define WM8962_VSS_XTD2_0 0x5217
1048#define WM8962_VSS_XTD3_1 0x5218
1049#define WM8962_VSS_XTD3_0 0x5219
1050#define WM8962_VSS_XTD4_1 0x521A
1051#define WM8962_VSS_XTD4_0 0x521B
1052#define WM8962_VSS_XTD5_1 0x521C
1053#define WM8962_VSS_XTD5_0 0x521D
1054#define WM8962_VSS_XTD6_1 0x521E
1055#define WM8962_VSS_XTD6_0 0x521F
1056#define WM8962_VSS_XTD7_1 0x5220
1057#define WM8962_VSS_XTD7_0 0x5221
1058#define WM8962_VSS_XTD8_1 0x5222
1059#define WM8962_VSS_XTD8_0 0x5223
1060#define WM8962_VSS_XTD9_1 0x5224
1061#define WM8962_VSS_XTD9_0 0x5225
1062#define WM8962_VSS_XTD10_1 0x5226
1063#define WM8962_VSS_XTD10_0 0x5227
1064#define WM8962_VSS_XTD11_1 0x5228
1065#define WM8962_VSS_XTD11_0 0x5229
1066#define WM8962_VSS_XTD12_1 0x522A
1067#define WM8962_VSS_XTD12_0 0x522B
1068#define WM8962_VSS_XTD13_1 0x522C
1069#define WM8962_VSS_XTD13_0 0x522D
1070#define WM8962_VSS_XTD14_1 0x522E
1071#define WM8962_VSS_XTD14_0 0x522F
1072#define WM8962_VSS_XTD15_1 0x5230
1073#define WM8962_VSS_XTD15_0 0x5231
1074#define WM8962_VSS_XTD16_1 0x5232
1075#define WM8962_VSS_XTD16_0 0x5233
1076#define WM8962_VSS_XTD17_1 0x5234
1077#define WM8962_VSS_XTD17_0 0x5235
1078#define WM8962_VSS_XTD18_1 0x5236
1079#define WM8962_VSS_XTD18_0 0x5237
1080#define WM8962_VSS_XTD19_1 0x5238
1081#define WM8962_VSS_XTD19_0 0x5239
1082#define WM8962_VSS_XTD20_1 0x523A
1083#define WM8962_VSS_XTD20_0 0x523B
1084#define WM8962_VSS_XTD21_1 0x523C
1085#define WM8962_VSS_XTD21_0 0x523D
1086#define WM8962_VSS_XTD22_1 0x523E
1087#define WM8962_VSS_XTD22_0 0x523F
1088#define WM8962_VSS_XTD23_1 0x5240
1089#define WM8962_VSS_XTD23_0 0x5241
1090#define WM8962_VSS_XTD24_1 0x5242
1091#define WM8962_VSS_XTD24_0 0x5243
1092#define WM8962_VSS_XTD25_1 0x5244
1093#define WM8962_VSS_XTD25_0 0x5245
1094#define WM8962_VSS_XTD26_1 0x5246
1095#define WM8962_VSS_XTD26_0 0x5247
1096#define WM8962_VSS_XTD27_1 0x5248
1097#define WM8962_VSS_XTD27_0 0x5249
1098#define WM8962_VSS_XTD28_1 0x524A
1099#define WM8962_VSS_XTD28_0 0x524B
1100#define WM8962_VSS_XTD29_1 0x524C
1101#define WM8962_VSS_XTD29_0 0x524D
1102#define WM8962_VSS_XTD30_1 0x524E
1103#define WM8962_VSS_XTD30_0 0x524F
1104#define WM8962_VSS_XTD31_1 0x5250
1105#define WM8962_VSS_XTD31_0 0x5251
1106#define WM8962_VSS_XTD32_1 0x5252
1107#define WM8962_VSS_XTD32_0 0x5253
1108#define WM8962_VSS_XTS1_1 0x5254
1109#define WM8962_VSS_XTS1_0 0x5255
1110#define WM8962_VSS_XTS2_1 0x5256
1111#define WM8962_VSS_XTS2_0 0x5257
1112#define WM8962_VSS_XTS3_1 0x5258
1113#define WM8962_VSS_XTS3_0 0x5259
1114#define WM8962_VSS_XTS4_1 0x525A
1115#define WM8962_VSS_XTS4_0 0x525B
1116#define WM8962_VSS_XTS5_1 0x525C
1117#define WM8962_VSS_XTS5_0 0x525D
1118#define WM8962_VSS_XTS6_1 0x525E
1119#define WM8962_VSS_XTS6_0 0x525F
1120#define WM8962_VSS_XTS7_1 0x5260
1121#define WM8962_VSS_XTS7_0 0x5261
1122#define WM8962_VSS_XTS8_1 0x5262
1123#define WM8962_VSS_XTS8_0 0x5263
1124#define WM8962_VSS_XTS9_1 0x5264
1125#define WM8962_VSS_XTS9_0 0x5265
1126#define WM8962_VSS_XTS10_1 0x5266
1127#define WM8962_VSS_XTS10_0 0x5267
1128#define WM8962_VSS_XTS11_1 0x5268
1129#define WM8962_VSS_XTS11_0 0x5269
1130#define WM8962_VSS_XTS12_1 0x526A
1131#define WM8962_VSS_XTS12_0 0x526B
1132#define WM8962_VSS_XTS13_1 0x526C
1133#define WM8962_VSS_XTS13_0 0x526D
1134#define WM8962_VSS_XTS14_1 0x526E
1135#define WM8962_VSS_XTS14_0 0x526F
1136#define WM8962_VSS_XTS15_1 0x5270
1137#define WM8962_VSS_XTS15_0 0x5271
1138#define WM8962_VSS_XTS16_1 0x5272
1139#define WM8962_VSS_XTS16_0 0x5273
1140#define WM8962_VSS_XTS17_1 0x5274
1141#define WM8962_VSS_XTS17_0 0x5275
1142#define WM8962_VSS_XTS18_1 0x5276
1143#define WM8962_VSS_XTS18_0 0x5277
1144#define WM8962_VSS_XTS19_1 0x5278
1145#define WM8962_VSS_XTS19_0 0x5279
1146#define WM8962_VSS_XTS20_1 0x527A
1147#define WM8962_VSS_XTS20_0 0x527B
1148#define WM8962_VSS_XTS21_1 0x527C
1149#define WM8962_VSS_XTS21_0 0x527D
1150#define WM8962_VSS_XTS22_1 0x527E
1151#define WM8962_VSS_XTS22_0 0x527F
1152#define WM8962_VSS_XTS23_1 0x5280
1153#define WM8962_VSS_XTS23_0 0x5281
1154#define WM8962_VSS_XTS24_1 0x5282
1155#define WM8962_VSS_XTS24_0 0x5283
1156#define WM8962_VSS_XTS25_1 0x5284
1157#define WM8962_VSS_XTS25_0 0x5285
1158#define WM8962_VSS_XTS26_1 0x5286
1159#define WM8962_VSS_XTS26_0 0x5287
1160#define WM8962_VSS_XTS27_1 0x5288
1161#define WM8962_VSS_XTS27_0 0x5289
1162#define WM8962_VSS_XTS28_1 0x528A
1163#define WM8962_VSS_XTS28_0 0x528B
1164#define WM8962_VSS_XTS29_1 0x528C
1165#define WM8962_VSS_XTS29_0 0x528D
1166#define WM8962_VSS_XTS30_1 0x528E
1167#define WM8962_VSS_XTS30_0 0x528F
1168#define WM8962_VSS_XTS31_1 0x5290
1169#define WM8962_VSS_XTS31_0 0x5291
1170#define WM8962_VSS_XTS32_1 0x5292
1171#define WM8962_VSS_XTS32_0 0x5293
1172
1173#define WM8962_REGISTER_COUNT 1138
1174#define WM8962_MAX_REGISTER 0x5293
1175
1176/*
1177 * Field Definitions.
1178 */
1179
1180/*
1181 * R0 (0x00) - Left Input volume
1182 */
1183#define WM8962_IN_VU 0x0100 /* IN_VU */
1184#define WM8962_IN_VU_MASK 0x0100 /* IN_VU */
1185#define WM8962_IN_VU_SHIFT 8 /* IN_VU */
1186#define WM8962_IN_VU_WIDTH 1 /* IN_VU */
1187#define WM8962_INPGAL_MUTE 0x0080 /* INPGAL_MUTE */
1188#define WM8962_INPGAL_MUTE_MASK 0x0080 /* INPGAL_MUTE */
1189#define WM8962_INPGAL_MUTE_SHIFT 7 /* INPGAL_MUTE */
1190#define WM8962_INPGAL_MUTE_WIDTH 1 /* INPGAL_MUTE */
1191#define WM8962_INL_ZC 0x0040 /* INL_ZC */
1192#define WM8962_INL_ZC_MASK 0x0040 /* INL_ZC */
1193#define WM8962_INL_ZC_SHIFT 6 /* INL_ZC */
1194#define WM8962_INL_ZC_WIDTH 1 /* INL_ZC */
1195#define WM8962_INL_VOL_MASK 0x003F /* INL_VOL - [5:0] */
1196#define WM8962_INL_VOL_SHIFT 0 /* INL_VOL - [5:0] */
1197#define WM8962_INL_VOL_WIDTH 6 /* INL_VOL - [5:0] */
1198
1199/*
1200 * R1 (0x01) - Right Input volume
1201 */
1202#define WM8962_CUST_ID_MASK 0xF000 /* CUST_ID - [15:12] */
1203#define WM8962_CUST_ID_SHIFT 12 /* CUST_ID - [15:12] */
1204#define WM8962_CUST_ID_WIDTH 4 /* CUST_ID - [15:12] */
1205#define WM8962_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */
1206#define WM8962_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */
1207#define WM8962_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */
1208#define WM8962_IN_VU 0x0100 /* IN_VU */
1209#define WM8962_IN_VU_MASK 0x0100 /* IN_VU */
1210#define WM8962_IN_VU_SHIFT 8 /* IN_VU */
1211#define WM8962_IN_VU_WIDTH 1 /* IN_VU */
1212#define WM8962_INPGAR_MUTE 0x0080 /* INPGAR_MUTE */
1213#define WM8962_INPGAR_MUTE_MASK 0x0080 /* INPGAR_MUTE */
1214#define WM8962_INPGAR_MUTE_SHIFT 7 /* INPGAR_MUTE */
1215#define WM8962_INPGAR_MUTE_WIDTH 1 /* INPGAR_MUTE */
1216#define WM8962_INR_ZC 0x0040 /* INR_ZC */
1217#define WM8962_INR_ZC_MASK 0x0040 /* INR_ZC */
1218#define WM8962_INR_ZC_SHIFT 6 /* INR_ZC */
1219#define WM8962_INR_ZC_WIDTH 1 /* INR_ZC */
1220#define WM8962_INR_VOL_MASK 0x003F /* INR_VOL - [5:0] */
1221#define WM8962_INR_VOL_SHIFT 0 /* INR_VOL - [5:0] */
1222#define WM8962_INR_VOL_WIDTH 6 /* INR_VOL - [5:0] */
1223
1224/*
1225 * R2 (0x02) - HPOUTL volume
1226 */
1227#define WM8962_HPOUT_VU 0x0100 /* HPOUT_VU */
1228#define WM8962_HPOUT_VU_MASK 0x0100 /* HPOUT_VU */
1229#define WM8962_HPOUT_VU_SHIFT 8 /* HPOUT_VU */
1230#define WM8962_HPOUT_VU_WIDTH 1 /* HPOUT_VU */
1231#define WM8962_HPOUTL_ZC 0x0080 /* HPOUTL_ZC */
1232#define WM8962_HPOUTL_ZC_MASK 0x0080 /* HPOUTL_ZC */
1233#define WM8962_HPOUTL_ZC_SHIFT 7 /* HPOUTL_ZC */
1234#define WM8962_HPOUTL_ZC_WIDTH 1 /* HPOUTL_ZC */
1235#define WM8962_HPOUTL_VOL_MASK 0x007F /* HPOUTL_VOL - [6:0] */
1236#define WM8962_HPOUTL_VOL_SHIFT 0 /* HPOUTL_VOL - [6:0] */
1237#define WM8962_HPOUTL_VOL_WIDTH 7 /* HPOUTL_VOL - [6:0] */
1238
1239/*
1240 * R3 (0x03) - HPOUTR volume
1241 */
1242#define WM8962_HPOUT_VU 0x0100 /* HPOUT_VU */
1243#define WM8962_HPOUT_VU_MASK 0x0100 /* HPOUT_VU */
1244#define WM8962_HPOUT_VU_SHIFT 8 /* HPOUT_VU */
1245#define WM8962_HPOUT_VU_WIDTH 1 /* HPOUT_VU */
1246#define WM8962_HPOUTR_ZC 0x0080 /* HPOUTR_ZC */
1247#define WM8962_HPOUTR_ZC_MASK 0x0080 /* HPOUTR_ZC */
1248#define WM8962_HPOUTR_ZC_SHIFT 7 /* HPOUTR_ZC */
1249#define WM8962_HPOUTR_ZC_WIDTH 1 /* HPOUTR_ZC */
1250#define WM8962_HPOUTR_VOL_MASK 0x007F /* HPOUTR_VOL - [6:0] */
1251#define WM8962_HPOUTR_VOL_SHIFT 0 /* HPOUTR_VOL - [6:0] */
1252#define WM8962_HPOUTR_VOL_WIDTH 7 /* HPOUTR_VOL - [6:0] */
1253
1254/*
1255 * R4 (0x04) - Clocking1
1256 */
1257#define WM8962_DSPCLK_DIV_MASK 0x0600 /* DSPCLK_DIV - [10:9] */
1258#define WM8962_DSPCLK_DIV_SHIFT 9 /* DSPCLK_DIV - [10:9] */
1259#define WM8962_DSPCLK_DIV_WIDTH 2 /* DSPCLK_DIV - [10:9] */
1260#define WM8962_ADCSYS_CLK_DIV_MASK 0x01C0 /* ADCSYS_CLK_DIV - [8:6] */
1261#define WM8962_ADCSYS_CLK_DIV_SHIFT 6 /* ADCSYS_CLK_DIV - [8:6] */
1262#define WM8962_ADCSYS_CLK_DIV_WIDTH 3 /* ADCSYS_CLK_DIV - [8:6] */
1263#define WM8962_DACSYS_CLK_DIV_MASK 0x0038 /* DACSYS_CLK_DIV - [5:3] */
1264#define WM8962_DACSYS_CLK_DIV_SHIFT 3 /* DACSYS_CLK_DIV - [5:3] */
1265#define WM8962_DACSYS_CLK_DIV_WIDTH 3 /* DACSYS_CLK_DIV - [5:3] */
1266#define WM8962_MCLKDIV_MASK 0x0006 /* MCLKDIV - [2:1] */
1267#define WM8962_MCLKDIV_SHIFT 1 /* MCLKDIV - [2:1] */
1268#define WM8962_MCLKDIV_WIDTH 2 /* MCLKDIV - [2:1] */
1269
1270/*
1271 * R5 (0x05) - ADC & DAC Control 1
1272 */
1273#define WM8962_ADCR_DAT_INV 0x0040 /* ADCR_DAT_INV */
1274#define WM8962_ADCR_DAT_INV_MASK 0x0040 /* ADCR_DAT_INV */
1275#define WM8962_ADCR_DAT_INV_SHIFT 6 /* ADCR_DAT_INV */
1276#define WM8962_ADCR_DAT_INV_WIDTH 1 /* ADCR_DAT_INV */
1277#define WM8962_ADCL_DAT_INV 0x0020 /* ADCL_DAT_INV */
1278#define WM8962_ADCL_DAT_INV_MASK 0x0020 /* ADCL_DAT_INV */
1279#define WM8962_ADCL_DAT_INV_SHIFT 5 /* ADCL_DAT_INV */
1280#define WM8962_ADCL_DAT_INV_WIDTH 1 /* ADCL_DAT_INV */
1281#define WM8962_DAC_MUTE_RAMP 0x0010 /* DAC_MUTE_RAMP */
1282#define WM8962_DAC_MUTE_RAMP_MASK 0x0010 /* DAC_MUTE_RAMP */
1283#define WM8962_DAC_MUTE_RAMP_SHIFT 4 /* DAC_MUTE_RAMP */
1284#define WM8962_DAC_MUTE_RAMP_WIDTH 1 /* DAC_MUTE_RAMP */
1285#define WM8962_DAC_MUTE 0x0008 /* DAC_MUTE */
1286#define WM8962_DAC_MUTE_MASK 0x0008 /* DAC_MUTE */
1287#define WM8962_DAC_MUTE_SHIFT 3 /* DAC_MUTE */
1288#define WM8962_DAC_MUTE_WIDTH 1 /* DAC_MUTE */
1289#define WM8962_DAC_DEEMP_MASK 0x0006 /* DAC_DEEMP - [2:1] */
1290#define WM8962_DAC_DEEMP_SHIFT 1 /* DAC_DEEMP - [2:1] */
1291#define WM8962_DAC_DEEMP_WIDTH 2 /* DAC_DEEMP - [2:1] */
1292#define WM8962_ADC_HPF_DIS 0x0001 /* ADC_HPF_DIS */
1293#define WM8962_ADC_HPF_DIS_MASK 0x0001 /* ADC_HPF_DIS */
1294#define WM8962_ADC_HPF_DIS_SHIFT 0 /* ADC_HPF_DIS */
1295#define WM8962_ADC_HPF_DIS_WIDTH 1 /* ADC_HPF_DIS */
1296
1297/*
1298 * R6 (0x06) - ADC & DAC Control 2
1299 */
1300#define WM8962_ADC_HPF_SR_MASK 0x3000 /* ADC_HPF_SR - [13:12] */
1301#define WM8962_ADC_HPF_SR_SHIFT 12 /* ADC_HPF_SR - [13:12] */
1302#define WM8962_ADC_HPF_SR_WIDTH 2 /* ADC_HPF_SR - [13:12] */
1303#define WM8962_ADC_HPF_MODE 0x0400 /* ADC_HPF_MODE */
1304#define WM8962_ADC_HPF_MODE_MASK 0x0400 /* ADC_HPF_MODE */
1305#define WM8962_ADC_HPF_MODE_SHIFT 10 /* ADC_HPF_MODE */
1306#define WM8962_ADC_HPF_MODE_WIDTH 1 /* ADC_HPF_MODE */
1307#define WM8962_ADC_HPF_CUT_MASK 0x0380 /* ADC_HPF_CUT - [9:7] */
1308#define WM8962_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [9:7] */
1309#define WM8962_ADC_HPF_CUT_WIDTH 3 /* ADC_HPF_CUT - [9:7] */
1310#define WM8962_DACR_DAT_INV 0x0040 /* DACR_DAT_INV */
1311#define WM8962_DACR_DAT_INV_MASK 0x0040 /* DACR_DAT_INV */
1312#define WM8962_DACR_DAT_INV_SHIFT 6 /* DACR_DAT_INV */
1313#define WM8962_DACR_DAT_INV_WIDTH 1 /* DACR_DAT_INV */
1314#define WM8962_DACL_DAT_INV 0x0020 /* DACL_DAT_INV */
1315#define WM8962_DACL_DAT_INV_MASK 0x0020 /* DACL_DAT_INV */
1316#define WM8962_DACL_DAT_INV_SHIFT 5 /* DACL_DAT_INV */
1317#define WM8962_DACL_DAT_INV_WIDTH 1 /* DACL_DAT_INV */
1318#define WM8962_DAC_UNMUTE_RAMP 0x0008 /* DAC_UNMUTE_RAMP */
1319#define WM8962_DAC_UNMUTE_RAMP_MASK 0x0008 /* DAC_UNMUTE_RAMP */
1320#define WM8962_DAC_UNMUTE_RAMP_SHIFT 3 /* DAC_UNMUTE_RAMP */
1321#define WM8962_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */
1322#define WM8962_DAC_MUTERATE 0x0004 /* DAC_MUTERATE */
1323#define WM8962_DAC_MUTERATE_MASK 0x0004 /* DAC_MUTERATE */
1324#define WM8962_DAC_MUTERATE_SHIFT 2 /* DAC_MUTERATE */
1325#define WM8962_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
1326#define WM8962_DAC_HP 0x0001 /* DAC_HP */
1327#define WM8962_DAC_HP_MASK 0x0001 /* DAC_HP */
1328#define WM8962_DAC_HP_SHIFT 0 /* DAC_HP */
1329#define WM8962_DAC_HP_WIDTH 1 /* DAC_HP */
1330
1331/*
1332 * R7 (0x07) - Audio Interface 0
1333 */
1334#define WM8962_AIFDAC_TDM_MODE 0x1000 /* AIFDAC_TDM_MODE */
1335#define WM8962_AIFDAC_TDM_MODE_MASK 0x1000 /* AIFDAC_TDM_MODE */
1336#define WM8962_AIFDAC_TDM_MODE_SHIFT 12 /* AIFDAC_TDM_MODE */
1337#define WM8962_AIFDAC_TDM_MODE_WIDTH 1 /* AIFDAC_TDM_MODE */
1338#define WM8962_AIFDAC_TDM_SLOT 0x0800 /* AIFDAC_TDM_SLOT */
1339#define WM8962_AIFDAC_TDM_SLOT_MASK 0x0800 /* AIFDAC_TDM_SLOT */
1340#define WM8962_AIFDAC_TDM_SLOT_SHIFT 11 /* AIFDAC_TDM_SLOT */
1341#define WM8962_AIFDAC_TDM_SLOT_WIDTH 1 /* AIFDAC_TDM_SLOT */
1342#define WM8962_AIFADC_TDM_MODE 0x0400 /* AIFADC_TDM_MODE */
1343#define WM8962_AIFADC_TDM_MODE_MASK 0x0400 /* AIFADC_TDM_MODE */
1344#define WM8962_AIFADC_TDM_MODE_SHIFT 10 /* AIFADC_TDM_MODE */
1345#define WM8962_AIFADC_TDM_MODE_WIDTH 1 /* AIFADC_TDM_MODE */
1346#define WM8962_AIFADC_TDM_SLOT 0x0200 /* AIFADC_TDM_SLOT */
1347#define WM8962_AIFADC_TDM_SLOT_MASK 0x0200 /* AIFADC_TDM_SLOT */
1348#define WM8962_AIFADC_TDM_SLOT_SHIFT 9 /* AIFADC_TDM_SLOT */
1349#define WM8962_AIFADC_TDM_SLOT_WIDTH 1 /* AIFADC_TDM_SLOT */
1350#define WM8962_ADC_LRSWAP 0x0100 /* ADC_LRSWAP */
1351#define WM8962_ADC_LRSWAP_MASK 0x0100 /* ADC_LRSWAP */
1352#define WM8962_ADC_LRSWAP_SHIFT 8 /* ADC_LRSWAP */
1353#define WM8962_ADC_LRSWAP_WIDTH 1 /* ADC_LRSWAP */
1354#define WM8962_BCLK_INV 0x0080 /* BCLK_INV */
1355#define WM8962_BCLK_INV_MASK 0x0080 /* BCLK_INV */
1356#define WM8962_BCLK_INV_SHIFT 7 /* BCLK_INV */
1357#define WM8962_BCLK_INV_WIDTH 1 /* BCLK_INV */
1358#define WM8962_MSTR 0x0040 /* MSTR */
1359#define WM8962_MSTR_MASK 0x0040 /* MSTR */
1360#define WM8962_MSTR_SHIFT 6 /* MSTR */
1361#define WM8962_MSTR_WIDTH 1 /* MSTR */
1362#define WM8962_DAC_LRSWAP 0x0020 /* DAC_LRSWAP */
1363#define WM8962_DAC_LRSWAP_MASK 0x0020 /* DAC_LRSWAP */
1364#define WM8962_DAC_LRSWAP_SHIFT 5 /* DAC_LRSWAP */
1365#define WM8962_DAC_LRSWAP_WIDTH 1 /* DAC_LRSWAP */
1366#define WM8962_LRCLK_INV 0x0010 /* LRCLK_INV */
1367#define WM8962_LRCLK_INV_MASK 0x0010 /* LRCLK_INV */
1368#define WM8962_LRCLK_INV_SHIFT 4 /* LRCLK_INV */
1369#define WM8962_LRCLK_INV_WIDTH 1 /* LRCLK_INV */
1370#define WM8962_WL_MASK 0x000C /* WL - [3:2] */
1371#define WM8962_WL_SHIFT 2 /* WL - [3:2] */
1372#define WM8962_WL_WIDTH 2 /* WL - [3:2] */
1373#define WM8962_FMT_MASK 0x0003 /* FMT - [1:0] */
1374#define WM8962_FMT_SHIFT 0 /* FMT - [1:0] */
1375#define WM8962_FMT_WIDTH 2 /* FMT - [1:0] */
1376
1377/*
1378 * R8 (0x08) - Clocking2
1379 */
1380#define WM8962_CLKREG_OVD 0x0800 /* CLKREG_OVD */
1381#define WM8962_CLKREG_OVD_MASK 0x0800 /* CLKREG_OVD */
1382#define WM8962_CLKREG_OVD_SHIFT 11 /* CLKREG_OVD */
1383#define WM8962_CLKREG_OVD_WIDTH 1 /* CLKREG_OVD */
1384#define WM8962_SYSCLK_SRC_MASK 0x0600 /* SYSCLK_SRC - [10:9] */
1385#define WM8962_SYSCLK_SRC_SHIFT 9 /* SYSCLK_SRC - [10:9] */
1386#define WM8962_SYSCLK_SRC_WIDTH 2 /* SYSCLK_SRC - [10:9] */
1387#define WM8962_CLASSD_CLK_DIV_MASK 0x01C0 /* CLASSD_CLK_DIV - [8:6] */
1388#define WM8962_CLASSD_CLK_DIV_SHIFT 6 /* CLASSD_CLK_DIV - [8:6] */
1389#define WM8962_CLASSD_CLK_DIV_WIDTH 3 /* CLASSD_CLK_DIV - [8:6] */
1390#define WM8962_SYSCLK_ENA 0x0020 /* SYSCLK_ENA */
1391#define WM8962_SYSCLK_ENA_MASK 0x0020 /* SYSCLK_ENA */
1392#define WM8962_SYSCLK_ENA_SHIFT 5 /* SYSCLK_ENA */
1393#define WM8962_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */
1394#define WM8962_BCLK_DIV_MASK 0x000F /* BCLK_DIV - [3:0] */
1395#define WM8962_BCLK_DIV_SHIFT 0 /* BCLK_DIV - [3:0] */
1396#define WM8962_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [3:0] */
1397
1398/*
1399 * R9 (0x09) - Audio Interface 1
1400 */
1401#define WM8962_AUTOMUTE_STS 0x0800 /* AUTOMUTE_STS */
1402#define WM8962_AUTOMUTE_STS_MASK 0x0800 /* AUTOMUTE_STS */
1403#define WM8962_AUTOMUTE_STS_SHIFT 11 /* AUTOMUTE_STS */
1404#define WM8962_AUTOMUTE_STS_WIDTH 1 /* AUTOMUTE_STS */
1405#define WM8962_DAC_AUTOMUTE_SAMPLES_MASK 0x0300 /* DAC_AUTOMUTE_SAMPLES - [9:8] */
1406#define WM8962_DAC_AUTOMUTE_SAMPLES_SHIFT 8 /* DAC_AUTOMUTE_SAMPLES - [9:8] */
1407#define WM8962_DAC_AUTOMUTE_SAMPLES_WIDTH 2 /* DAC_AUTOMUTE_SAMPLES - [9:8] */
1408#define WM8962_DAC_AUTOMUTE 0x0080 /* DAC_AUTOMUTE */
1409#define WM8962_DAC_AUTOMUTE_MASK 0x0080 /* DAC_AUTOMUTE */
1410#define WM8962_DAC_AUTOMUTE_SHIFT 7 /* DAC_AUTOMUTE */
1411#define WM8962_DAC_AUTOMUTE_WIDTH 1 /* DAC_AUTOMUTE */
1412#define WM8962_DAC_COMP 0x0010 /* DAC_COMP */
1413#define WM8962_DAC_COMP_MASK 0x0010 /* DAC_COMP */
1414#define WM8962_DAC_COMP_SHIFT 4 /* DAC_COMP */
1415#define WM8962_DAC_COMP_WIDTH 1 /* DAC_COMP */
1416#define WM8962_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */
1417#define WM8962_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */
1418#define WM8962_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */
1419#define WM8962_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */
1420#define WM8962_ADC_COMP 0x0004 /* ADC_COMP */
1421#define WM8962_ADC_COMP_MASK 0x0004 /* ADC_COMP */
1422#define WM8962_ADC_COMP_SHIFT 2 /* ADC_COMP */
1423#define WM8962_ADC_COMP_WIDTH 1 /* ADC_COMP */
1424#define WM8962_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */
1425#define WM8962_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */
1426#define WM8962_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */
1427#define WM8962_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */
1428#define WM8962_LOOPBACK 0x0001 /* LOOPBACK */
1429#define WM8962_LOOPBACK_MASK 0x0001 /* LOOPBACK */
1430#define WM8962_LOOPBACK_SHIFT 0 /* LOOPBACK */
1431#define WM8962_LOOPBACK_WIDTH 1 /* LOOPBACK */
1432
1433/*
1434 * R10 (0x0A) - Left DAC volume
1435 */
1436#define WM8962_DAC_VU 0x0100 /* DAC_VU */
1437#define WM8962_DAC_VU_MASK 0x0100 /* DAC_VU */
1438#define WM8962_DAC_VU_SHIFT 8 /* DAC_VU */
1439#define WM8962_DAC_VU_WIDTH 1 /* DAC_VU */
1440#define WM8962_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */
1441#define WM8962_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */
1442#define WM8962_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */
1443
1444/*
1445 * R11 (0x0B) - Right DAC volume
1446 */
1447#define WM8962_DAC_VU 0x0100 /* DAC_VU */
1448#define WM8962_DAC_VU_MASK 0x0100 /* DAC_VU */
1449#define WM8962_DAC_VU_SHIFT 8 /* DAC_VU */
1450#define WM8962_DAC_VU_WIDTH 1 /* DAC_VU */
1451#define WM8962_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */
1452#define WM8962_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */
1453#define WM8962_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */
1454
1455/*
1456 * R14 (0x0E) - Audio Interface 2
1457 */
1458#define WM8962_AIF_RATE_MASK 0x07FF /* AIF_RATE - [10:0] */
1459#define WM8962_AIF_RATE_SHIFT 0 /* AIF_RATE - [10:0] */
1460#define WM8962_AIF_RATE_WIDTH 11 /* AIF_RATE - [10:0] */
1461
1462/*
1463 * R15 (0x0F) - Software Reset
1464 */
1465#define WM8962_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */
1466#define WM8962_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */
1467#define WM8962_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */
1468
1469/*
1470 * R17 (0x11) - ALC1
1471 */
1472#define WM8962_ALC_INACTIVE_ENA 0x0400 /* ALC_INACTIVE_ENA */
1473#define WM8962_ALC_INACTIVE_ENA_MASK 0x0400 /* ALC_INACTIVE_ENA */
1474#define WM8962_ALC_INACTIVE_ENA_SHIFT 10 /* ALC_INACTIVE_ENA */
1475#define WM8962_ALC_INACTIVE_ENA_WIDTH 1 /* ALC_INACTIVE_ENA */
1476#define WM8962_ALC_LVL_MODE 0x0200 /* ALC_LVL_MODE */
1477#define WM8962_ALC_LVL_MODE_MASK 0x0200 /* ALC_LVL_MODE */
1478#define WM8962_ALC_LVL_MODE_SHIFT 9 /* ALC_LVL_MODE */
1479#define WM8962_ALC_LVL_MODE_WIDTH 1 /* ALC_LVL_MODE */
1480#define WM8962_ALCL_ENA 0x0100 /* ALCL_ENA */
1481#define WM8962_ALCL_ENA_MASK 0x0100 /* ALCL_ENA */
1482#define WM8962_ALCL_ENA_SHIFT 8 /* ALCL_ENA */
1483#define WM8962_ALCL_ENA_WIDTH 1 /* ALCL_ENA */
1484#define WM8962_ALCR_ENA 0x0080 /* ALCR_ENA */
1485#define WM8962_ALCR_ENA_MASK 0x0080 /* ALCR_ENA */
1486#define WM8962_ALCR_ENA_SHIFT 7 /* ALCR_ENA */
1487#define WM8962_ALCR_ENA_WIDTH 1 /* ALCR_ENA */
1488#define WM8962_ALC_MAXGAIN_MASK 0x0070 /* ALC_MAXGAIN - [6:4] */
1489#define WM8962_ALC_MAXGAIN_SHIFT 4 /* ALC_MAXGAIN - [6:4] */
1490#define WM8962_ALC_MAXGAIN_WIDTH 3 /* ALC_MAXGAIN - [6:4] */
1491#define WM8962_ALC_LVL_MASK 0x000F /* ALC_LVL - [3:0] */
1492#define WM8962_ALC_LVL_SHIFT 0 /* ALC_LVL - [3:0] */
1493#define WM8962_ALC_LVL_WIDTH 4 /* ALC_LVL - [3:0] */
1494
1495/*
1496 * R18 (0x12) - ALC2
1497 */
1498#define WM8962_ALC_LOCK_STS 0x8000 /* ALC_LOCK_STS */
1499#define WM8962_ALC_LOCK_STS_MASK 0x8000 /* ALC_LOCK_STS */
1500#define WM8962_ALC_LOCK_STS_SHIFT 15 /* ALC_LOCK_STS */
1501#define WM8962_ALC_LOCK_STS_WIDTH 1 /* ALC_LOCK_STS */
1502#define WM8962_ALC_THRESH_STS 0x4000 /* ALC_THRESH_STS */
1503#define WM8962_ALC_THRESH_STS_MASK 0x4000 /* ALC_THRESH_STS */
1504#define WM8962_ALC_THRESH_STS_SHIFT 14 /* ALC_THRESH_STS */
1505#define WM8962_ALC_THRESH_STS_WIDTH 1 /* ALC_THRESH_STS */
1506#define WM8962_ALC_SAT_STS 0x2000 /* ALC_SAT_STS */
1507#define WM8962_ALC_SAT_STS_MASK 0x2000 /* ALC_SAT_STS */
1508#define WM8962_ALC_SAT_STS_SHIFT 13 /* ALC_SAT_STS */
1509#define WM8962_ALC_SAT_STS_WIDTH 1 /* ALC_SAT_STS */
1510#define WM8962_ALC_PKOVR_STS 0x1000 /* ALC_PKOVR_STS */
1511#define WM8962_ALC_PKOVR_STS_MASK 0x1000 /* ALC_PKOVR_STS */
1512#define WM8962_ALC_PKOVR_STS_SHIFT 12 /* ALC_PKOVR_STS */
1513#define WM8962_ALC_PKOVR_STS_WIDTH 1 /* ALC_PKOVR_STS */
1514#define WM8962_ALC_NGATE_STS 0x0800 /* ALC_NGATE_STS */
1515#define WM8962_ALC_NGATE_STS_MASK 0x0800 /* ALC_NGATE_STS */
1516#define WM8962_ALC_NGATE_STS_SHIFT 11 /* ALC_NGATE_STS */
1517#define WM8962_ALC_NGATE_STS_WIDTH 1 /* ALC_NGATE_STS */
1518#define WM8962_ALC_ZC 0x0080 /* ALC_ZC */
1519#define WM8962_ALC_ZC_MASK 0x0080 /* ALC_ZC */
1520#define WM8962_ALC_ZC_SHIFT 7 /* ALC_ZC */
1521#define WM8962_ALC_ZC_WIDTH 1 /* ALC_ZC */
1522#define WM8962_ALC_MINGAIN_MASK 0x0070 /* ALC_MINGAIN - [6:4] */
1523#define WM8962_ALC_MINGAIN_SHIFT 4 /* ALC_MINGAIN - [6:4] */
1524#define WM8962_ALC_MINGAIN_WIDTH 3 /* ALC_MINGAIN - [6:4] */
1525#define WM8962_ALC_HLD_MASK 0x000F /* ALC_HLD - [3:0] */
1526#define WM8962_ALC_HLD_SHIFT 0 /* ALC_HLD - [3:0] */
1527#define WM8962_ALC_HLD_WIDTH 4 /* ALC_HLD - [3:0] */
1528
1529/*
1530 * R19 (0x13) - ALC3
1531 */
1532#define WM8962_ALC_NGATE_GAIN_MASK 0x1C00 /* ALC_NGATE_GAIN - [12:10] */
1533#define WM8962_ALC_NGATE_GAIN_SHIFT 10 /* ALC_NGATE_GAIN - [12:10] */
1534#define WM8962_ALC_NGATE_GAIN_WIDTH 3 /* ALC_NGATE_GAIN - [12:10] */
1535#define WM8962_ALC_MODE 0x0100 /* ALC_MODE */
1536#define WM8962_ALC_MODE_MASK 0x0100 /* ALC_MODE */
1537#define WM8962_ALC_MODE_SHIFT 8 /* ALC_MODE */
1538#define WM8962_ALC_MODE_WIDTH 1 /* ALC_MODE */
1539#define WM8962_ALC_DCY_MASK 0x00F0 /* ALC_DCY - [7:4] */
1540#define WM8962_ALC_DCY_SHIFT 4 /* ALC_DCY - [7:4] */
1541#define WM8962_ALC_DCY_WIDTH 4 /* ALC_DCY - [7:4] */
1542#define WM8962_ALC_ATK_MASK 0x000F /* ALC_ATK - [3:0] */
1543#define WM8962_ALC_ATK_SHIFT 0 /* ALC_ATK - [3:0] */
1544#define WM8962_ALC_ATK_WIDTH 4 /* ALC_ATK - [3:0] */
1545
1546/*
1547 * R20 (0x14) - Noise Gate
1548 */
1549#define WM8962_ALC_NGATE_DCY_MASK 0xF000 /* ALC_NGATE_DCY - [15:12] */
1550#define WM8962_ALC_NGATE_DCY_SHIFT 12 /* ALC_NGATE_DCY - [15:12] */
1551#define WM8962_ALC_NGATE_DCY_WIDTH 4 /* ALC_NGATE_DCY - [15:12] */
1552#define WM8962_ALC_NGATE_ATK_MASK 0x0F00 /* ALC_NGATE_ATK - [11:8] */
1553#define WM8962_ALC_NGATE_ATK_SHIFT 8 /* ALC_NGATE_ATK - [11:8] */
1554#define WM8962_ALC_NGATE_ATK_WIDTH 4 /* ALC_NGATE_ATK - [11:8] */
1555#define WM8962_ALC_NGATE_THR_MASK 0x00F8 /* ALC_NGATE_THR - [7:3] */
1556#define WM8962_ALC_NGATE_THR_SHIFT 3 /* ALC_NGATE_THR - [7:3] */
1557#define WM8962_ALC_NGATE_THR_WIDTH 5 /* ALC_NGATE_THR - [7:3] */
1558#define WM8962_ALC_NGATE_MODE_MASK 0x0006 /* ALC_NGATE_MODE - [2:1] */
1559#define WM8962_ALC_NGATE_MODE_SHIFT 1 /* ALC_NGATE_MODE - [2:1] */
1560#define WM8962_ALC_NGATE_MODE_WIDTH 2 /* ALC_NGATE_MODE - [2:1] */
1561#define WM8962_ALC_NGATE_ENA 0x0001 /* ALC_NGATE_ENA */
1562#define WM8962_ALC_NGATE_ENA_MASK 0x0001 /* ALC_NGATE_ENA */
1563#define WM8962_ALC_NGATE_ENA_SHIFT 0 /* ALC_NGATE_ENA */
1564#define WM8962_ALC_NGATE_ENA_WIDTH 1 /* ALC_NGATE_ENA */
1565
1566/*
1567 * R21 (0x15) - Left ADC volume
1568 */
1569#define WM8962_ADC_VU 0x0100 /* ADC_VU */
1570#define WM8962_ADC_VU_MASK 0x0100 /* ADC_VU */
1571#define WM8962_ADC_VU_SHIFT 8 /* ADC_VU */
1572#define WM8962_ADC_VU_WIDTH 1 /* ADC_VU */
1573#define WM8962_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */
1574#define WM8962_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */
1575#define WM8962_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */
1576
1577/*
1578 * R22 (0x16) - Right ADC volume
1579 */
1580#define WM8962_ADC_VU 0x0100 /* ADC_VU */
1581#define WM8962_ADC_VU_MASK 0x0100 /* ADC_VU */
1582#define WM8962_ADC_VU_SHIFT 8 /* ADC_VU */
1583#define WM8962_ADC_VU_WIDTH 1 /* ADC_VU */
1584#define WM8962_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */
1585#define WM8962_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */
1586#define WM8962_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */
1587
1588/*
1589 * R23 (0x17) - Additional control(1)
1590 */
1591#define WM8962_THERR_ACT 0x0100 /* THERR_ACT */
1592#define WM8962_THERR_ACT_MASK 0x0100 /* THERR_ACT */
1593#define WM8962_THERR_ACT_SHIFT 8 /* THERR_ACT */
1594#define WM8962_THERR_ACT_WIDTH 1 /* THERR_ACT */
1595#define WM8962_ADC_BIAS 0x0040 /* ADC_BIAS */
1596#define WM8962_ADC_BIAS_MASK 0x0040 /* ADC_BIAS */
1597#define WM8962_ADC_BIAS_SHIFT 6 /* ADC_BIAS */
1598#define WM8962_ADC_BIAS_WIDTH 1 /* ADC_BIAS */
1599#define WM8962_ADC_HP 0x0020 /* ADC_HP */
1600#define WM8962_ADC_HP_MASK 0x0020 /* ADC_HP */
1601#define WM8962_ADC_HP_SHIFT 5 /* ADC_HP */
1602#define WM8962_ADC_HP_WIDTH 1 /* ADC_HP */
1603#define WM8962_TOCLK_ENA 0x0001 /* TOCLK_ENA */
1604#define WM8962_TOCLK_ENA_MASK 0x0001 /* TOCLK_ENA */
1605#define WM8962_TOCLK_ENA_SHIFT 0 /* TOCLK_ENA */
1606#define WM8962_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */
1607
1608/*
1609 * R24 (0x18) - Additional control(2)
1610 */
1611#define WM8962_AIF_TRI 0x0008 /* AIF_TRI */
1612#define WM8962_AIF_TRI_MASK 0x0008 /* AIF_TRI */
1613#define WM8962_AIF_TRI_SHIFT 3 /* AIF_TRI */
1614#define WM8962_AIF_TRI_WIDTH 1 /* AIF_TRI */
1615
1616/*
1617 * R25 (0x19) - Pwr Mgmt (1)
1618 */
1619#define WM8962_DMIC_ENA 0x0400 /* DMIC_ENA */
1620#define WM8962_DMIC_ENA_MASK 0x0400 /* DMIC_ENA */
1621#define WM8962_DMIC_ENA_SHIFT 10 /* DMIC_ENA */
1622#define WM8962_DMIC_ENA_WIDTH 1 /* DMIC_ENA */
1623#define WM8962_OPCLK_ENA 0x0200 /* OPCLK_ENA */
1624#define WM8962_OPCLK_ENA_MASK 0x0200 /* OPCLK_ENA */
1625#define WM8962_OPCLK_ENA_SHIFT 9 /* OPCLK_ENA */
1626#define WM8962_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */
1627#define WM8962_VMID_SEL_MASK 0x0180 /* VMID_SEL - [8:7] */
1628#define WM8962_VMID_SEL_SHIFT 7 /* VMID_SEL - [8:7] */
1629#define WM8962_VMID_SEL_WIDTH 2 /* VMID_SEL - [8:7] */
1630#define WM8962_BIAS_ENA 0x0040 /* BIAS_ENA */
1631#define WM8962_BIAS_ENA_MASK 0x0040 /* BIAS_ENA */
1632#define WM8962_BIAS_ENA_SHIFT 6 /* BIAS_ENA */
1633#define WM8962_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
1634#define WM8962_INL_ENA 0x0020 /* INL_ENA */
1635#define WM8962_INL_ENA_MASK 0x0020 /* INL_ENA */
1636#define WM8962_INL_ENA_SHIFT 5 /* INL_ENA */
1637#define WM8962_INL_ENA_WIDTH 1 /* INL_ENA */
1638#define WM8962_INR_ENA 0x0010 /* INR_ENA */
1639#define WM8962_INR_ENA_MASK 0x0010 /* INR_ENA */
1640#define WM8962_INR_ENA_SHIFT 4 /* INR_ENA */
1641#define WM8962_INR_ENA_WIDTH 1 /* INR_ENA */
1642#define WM8962_ADCL_ENA 0x0008 /* ADCL_ENA */
1643#define WM8962_ADCL_ENA_MASK 0x0008 /* ADCL_ENA */
1644#define WM8962_ADCL_ENA_SHIFT 3 /* ADCL_ENA */
1645#define WM8962_ADCL_ENA_WIDTH 1 /* ADCL_ENA */
1646#define WM8962_ADCR_ENA 0x0004 /* ADCR_ENA */
1647#define WM8962_ADCR_ENA_MASK 0x0004 /* ADCR_ENA */
1648#define WM8962_ADCR_ENA_SHIFT 2 /* ADCR_ENA */
1649#define WM8962_ADCR_ENA_WIDTH 1 /* ADCR_ENA */
1650#define WM8962_MICBIAS_ENA 0x0002 /* MICBIAS_ENA */
1651#define WM8962_MICBIAS_ENA_MASK 0x0002 /* MICBIAS_ENA */
1652#define WM8962_MICBIAS_ENA_SHIFT 1 /* MICBIAS_ENA */
1653#define WM8962_MICBIAS_ENA_WIDTH 1 /* MICBIAS_ENA */
1654
1655/*
1656 * R26 (0x1A) - Pwr Mgmt (2)
1657 */
1658#define WM8962_DACL_ENA 0x0100 /* DACL_ENA */
1659#define WM8962_DACL_ENA_MASK 0x0100 /* DACL_ENA */
1660#define WM8962_DACL_ENA_SHIFT 8 /* DACL_ENA */
1661#define WM8962_DACL_ENA_WIDTH 1 /* DACL_ENA */
1662#define WM8962_DACR_ENA 0x0080 /* DACR_ENA */
1663#define WM8962_DACR_ENA_MASK 0x0080 /* DACR_ENA */
1664#define WM8962_DACR_ENA_SHIFT 7 /* DACR_ENA */
1665#define WM8962_DACR_ENA_WIDTH 1 /* DACR_ENA */
1666#define WM8962_HPOUTL_PGA_ENA 0x0040 /* HPOUTL_PGA_ENA */
1667#define WM8962_HPOUTL_PGA_ENA_MASK 0x0040 /* HPOUTL_PGA_ENA */
1668#define WM8962_HPOUTL_PGA_ENA_SHIFT 6 /* HPOUTL_PGA_ENA */
1669#define WM8962_HPOUTL_PGA_ENA_WIDTH 1 /* HPOUTL_PGA_ENA */
1670#define WM8962_HPOUTR_PGA_ENA 0x0020 /* HPOUTR_PGA_ENA */
1671#define WM8962_HPOUTR_PGA_ENA_MASK 0x0020 /* HPOUTR_PGA_ENA */
1672#define WM8962_HPOUTR_PGA_ENA_SHIFT 5 /* HPOUTR_PGA_ENA */
1673#define WM8962_HPOUTR_PGA_ENA_WIDTH 1 /* HPOUTR_PGA_ENA */
1674#define WM8962_SPKOUTL_PGA_ENA 0x0010 /* SPKOUTL_PGA_ENA */
1675#define WM8962_SPKOUTL_PGA_ENA_MASK 0x0010 /* SPKOUTL_PGA_ENA */
1676#define WM8962_SPKOUTL_PGA_ENA_SHIFT 4 /* SPKOUTL_PGA_ENA */
1677#define WM8962_SPKOUTL_PGA_ENA_WIDTH 1 /* SPKOUTL_PGA_ENA */
1678#define WM8962_SPKOUTR_PGA_ENA 0x0008 /* SPKOUTR_PGA_ENA */
1679#define WM8962_SPKOUTR_PGA_ENA_MASK 0x0008 /* SPKOUTR_PGA_ENA */
1680#define WM8962_SPKOUTR_PGA_ENA_SHIFT 3 /* SPKOUTR_PGA_ENA */
1681#define WM8962_SPKOUTR_PGA_ENA_WIDTH 1 /* SPKOUTR_PGA_ENA */
1682#define WM8962_HPOUTL_PGA_MUTE 0x0002 /* HPOUTL_PGA_MUTE */
1683#define WM8962_HPOUTL_PGA_MUTE_MASK 0x0002 /* HPOUTL_PGA_MUTE */
1684#define WM8962_HPOUTL_PGA_MUTE_SHIFT 1 /* HPOUTL_PGA_MUTE */
1685#define WM8962_HPOUTL_PGA_MUTE_WIDTH 1 /* HPOUTL_PGA_MUTE */
1686#define WM8962_HPOUTR_PGA_MUTE 0x0001 /* HPOUTR_PGA_MUTE */
1687#define WM8962_HPOUTR_PGA_MUTE_MASK 0x0001 /* HPOUTR_PGA_MUTE */
1688#define WM8962_HPOUTR_PGA_MUTE_SHIFT 0 /* HPOUTR_PGA_MUTE */
1689#define WM8962_HPOUTR_PGA_MUTE_WIDTH 1 /* HPOUTR_PGA_MUTE */
1690
1691/*
1692 * R27 (0x1B) - Additional Control (3)
1693 */
1694#define WM8962_SAMPLE_RATE_INT_MODE 0x0010 /* SAMPLE_RATE_INT_MODE */
1695#define WM8962_SAMPLE_RATE_INT_MODE_MASK 0x0010 /* SAMPLE_RATE_INT_MODE */
1696#define WM8962_SAMPLE_RATE_INT_MODE_SHIFT 4 /* SAMPLE_RATE_INT_MODE */
1697#define WM8962_SAMPLE_RATE_INT_MODE_WIDTH 1 /* SAMPLE_RATE_INT_MODE */
1698#define WM8962_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */
1699#define WM8962_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */
1700#define WM8962_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */
1701
1702/*
1703 * R28 (0x1C) - Anti-pop
1704 */
1705#define WM8962_STARTUP_BIAS_ENA 0x0010 /* STARTUP_BIAS_ENA */
1706#define WM8962_STARTUP_BIAS_ENA_MASK 0x0010 /* STARTUP_BIAS_ENA */
1707#define WM8962_STARTUP_BIAS_ENA_SHIFT 4 /* STARTUP_BIAS_ENA */
1708#define WM8962_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
1709#define WM8962_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */
1710#define WM8962_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */
1711#define WM8962_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */
1712#define WM8962_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
1713#define WM8962_VMID_RAMP 0x0004 /* VMID_RAMP */
1714#define WM8962_VMID_RAMP_MASK 0x0004 /* VMID_RAMP */
1715#define WM8962_VMID_RAMP_SHIFT 2 /* VMID_RAMP */
1716#define WM8962_VMID_RAMP_WIDTH 1 /* VMID_RAMP */
1717
1718/*
1719 * R30 (0x1E) - Clocking 3
1720 */
1721#define WM8962_DBCLK_DIV_MASK 0xE000 /* DBCLK_DIV - [15:13] */
1722#define WM8962_DBCLK_DIV_SHIFT 13 /* DBCLK_DIV - [15:13] */
1723#define WM8962_DBCLK_DIV_WIDTH 3 /* DBCLK_DIV - [15:13] */
1724#define WM8962_OPCLK_DIV_MASK 0x1C00 /* OPCLK_DIV - [12:10] */
1725#define WM8962_OPCLK_DIV_SHIFT 10 /* OPCLK_DIV - [12:10] */
1726#define WM8962_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [12:10] */
1727#define WM8962_TOCLK_DIV_MASK 0x0380 /* TOCLK_DIV - [9:7] */
1728#define WM8962_TOCLK_DIV_SHIFT 7 /* TOCLK_DIV - [9:7] */
1729#define WM8962_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [9:7] */
1730#define WM8962_F256KCLK_DIV_MASK 0x007E /* F256KCLK_DIV - [6:1] */
1731#define WM8962_F256KCLK_DIV_SHIFT 1 /* F256KCLK_DIV - [6:1] */
1732#define WM8962_F256KCLK_DIV_WIDTH 6 /* F256KCLK_DIV - [6:1] */
1733
1734/*
1735 * R31 (0x1F) - Input mixer control (1)
1736 */
1737#define WM8962_MIXINL_MUTE 0x0008 /* MIXINL_MUTE */
1738#define WM8962_MIXINL_MUTE_MASK 0x0008 /* MIXINL_MUTE */
1739#define WM8962_MIXINL_MUTE_SHIFT 3 /* MIXINL_MUTE */
1740#define WM8962_MIXINL_MUTE_WIDTH 1 /* MIXINL_MUTE */
1741#define WM8962_MIXINR_MUTE 0x0004 /* MIXINR_MUTE */
1742#define WM8962_MIXINR_MUTE_MASK 0x0004 /* MIXINR_MUTE */
1743#define WM8962_MIXINR_MUTE_SHIFT 2 /* MIXINR_MUTE */
1744#define WM8962_MIXINR_MUTE_WIDTH 1 /* MIXINR_MUTE */
1745#define WM8962_MIXINL_ENA 0x0002 /* MIXINL_ENA */
1746#define WM8962_MIXINL_ENA_MASK 0x0002 /* MIXINL_ENA */
1747#define WM8962_MIXINL_ENA_SHIFT 1 /* MIXINL_ENA */
1748#define WM8962_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */
1749#define WM8962_MIXINR_ENA 0x0001 /* MIXINR_ENA */
1750#define WM8962_MIXINR_ENA_MASK 0x0001 /* MIXINR_ENA */
1751#define WM8962_MIXINR_ENA_SHIFT 0 /* MIXINR_ENA */
1752#define WM8962_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */
1753
1754/*
1755 * R32 (0x20) - Left input mixer volume
1756 */
1757#define WM8962_IN2L_MIXINL_VOL_MASK 0x01C0 /* IN2L_MIXINL_VOL - [8:6] */
1758#define WM8962_IN2L_MIXINL_VOL_SHIFT 6 /* IN2L_MIXINL_VOL - [8:6] */
1759#define WM8962_IN2L_MIXINL_VOL_WIDTH 3 /* IN2L_MIXINL_VOL - [8:6] */
1760#define WM8962_INPGAL_MIXINL_VOL_MASK 0x0038 /* INPGAL_MIXINL_VOL - [5:3] */
1761#define WM8962_INPGAL_MIXINL_VOL_SHIFT 3 /* INPGAL_MIXINL_VOL - [5:3] */
1762#define WM8962_INPGAL_MIXINL_VOL_WIDTH 3 /* INPGAL_MIXINL_VOL - [5:3] */
1763#define WM8962_IN3L_MIXINL_VOL_MASK 0x0007 /* IN3L_MIXINL_VOL - [2:0] */
1764#define WM8962_IN3L_MIXINL_VOL_SHIFT 0 /* IN3L_MIXINL_VOL - [2:0] */
1765#define WM8962_IN3L_MIXINL_VOL_WIDTH 3 /* IN3L_MIXINL_VOL - [2:0] */
1766
1767/*
1768 * R33 (0x21) - Right input mixer volume
1769 */
1770#define WM8962_IN2R_MIXINR_VOL_MASK 0x01C0 /* IN2R_MIXINR_VOL - [8:6] */
1771#define WM8962_IN2R_MIXINR_VOL_SHIFT 6 /* IN2R_MIXINR_VOL - [8:6] */
1772#define WM8962_IN2R_MIXINR_VOL_WIDTH 3 /* IN2R_MIXINR_VOL - [8:6] */
1773#define WM8962_INPGAR_MIXINR_VOL_MASK 0x0038 /* INPGAR_MIXINR_VOL - [5:3] */
1774#define WM8962_INPGAR_MIXINR_VOL_SHIFT 3 /* INPGAR_MIXINR_VOL - [5:3] */
1775#define WM8962_INPGAR_MIXINR_VOL_WIDTH 3 /* INPGAR_MIXINR_VOL - [5:3] */
1776#define WM8962_IN3R_MIXINR_VOL_MASK 0x0007 /* IN3R_MIXINR_VOL - [2:0] */
1777#define WM8962_IN3R_MIXINR_VOL_SHIFT 0 /* IN3R_MIXINR_VOL - [2:0] */
1778#define WM8962_IN3R_MIXINR_VOL_WIDTH 3 /* IN3R_MIXINR_VOL - [2:0] */
1779
1780/*
1781 * R34 (0x22) - Input mixer control (2)
1782 */
1783#define WM8962_IN2L_TO_MIXINL 0x0020 /* IN2L_TO_MIXINL */
1784#define WM8962_IN2L_TO_MIXINL_MASK 0x0020 /* IN2L_TO_MIXINL */
1785#define WM8962_IN2L_TO_MIXINL_SHIFT 5 /* IN2L_TO_MIXINL */
1786#define WM8962_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */
1787#define WM8962_IN3L_TO_MIXINL 0x0010 /* IN3L_TO_MIXINL */
1788#define WM8962_IN3L_TO_MIXINL_MASK 0x0010 /* IN3L_TO_MIXINL */
1789#define WM8962_IN3L_TO_MIXINL_SHIFT 4 /* IN3L_TO_MIXINL */
1790#define WM8962_IN3L_TO_MIXINL_WIDTH 1 /* IN3L_TO_MIXINL */
1791#define WM8962_INPGAL_TO_MIXINL 0x0008 /* INPGAL_TO_MIXINL */
1792#define WM8962_INPGAL_TO_MIXINL_MASK 0x0008 /* INPGAL_TO_MIXINL */
1793#define WM8962_INPGAL_TO_MIXINL_SHIFT 3 /* INPGAL_TO_MIXINL */
1794#define WM8962_INPGAL_TO_MIXINL_WIDTH 1 /* INPGAL_TO_MIXINL */
1795#define WM8962_IN2R_TO_MIXINR 0x0004 /* IN2R_TO_MIXINR */
1796#define WM8962_IN2R_TO_MIXINR_MASK 0x0004 /* IN2R_TO_MIXINR */
1797#define WM8962_IN2R_TO_MIXINR_SHIFT 2 /* IN2R_TO_MIXINR */
1798#define WM8962_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */
1799#define WM8962_IN3R_TO_MIXINR 0x0002 /* IN3R_TO_MIXINR */
1800#define WM8962_IN3R_TO_MIXINR_MASK 0x0002 /* IN3R_TO_MIXINR */
1801#define WM8962_IN3R_TO_MIXINR_SHIFT 1 /* IN3R_TO_MIXINR */
1802#define WM8962_IN3R_TO_MIXINR_WIDTH 1 /* IN3R_TO_MIXINR */
1803#define WM8962_INPGAR_TO_MIXINR 0x0001 /* INPGAR_TO_MIXINR */
1804#define WM8962_INPGAR_TO_MIXINR_MASK 0x0001 /* INPGAR_TO_MIXINR */
1805#define WM8962_INPGAR_TO_MIXINR_SHIFT 0 /* INPGAR_TO_MIXINR */
1806#define WM8962_INPGAR_TO_MIXINR_WIDTH 1 /* INPGAR_TO_MIXINR */
1807
1808/*
1809 * R35 (0x23) - Input bias control
1810 */
1811#define WM8962_MIXIN_BIAS_MASK 0x0038 /* MIXIN_BIAS - [5:3] */
1812#define WM8962_MIXIN_BIAS_SHIFT 3 /* MIXIN_BIAS - [5:3] */
1813#define WM8962_MIXIN_BIAS_WIDTH 3 /* MIXIN_BIAS - [5:3] */
1814#define WM8962_INPGA_BIAS_MASK 0x0007 /* INPGA_BIAS - [2:0] */
1815#define WM8962_INPGA_BIAS_SHIFT 0 /* INPGA_BIAS - [2:0] */
1816#define WM8962_INPGA_BIAS_WIDTH 3 /* INPGA_BIAS - [2:0] */
1817
1818/*
1819 * R37 (0x25) - Left input PGA control
1820 */
1821#define WM8962_INPGAL_ENA 0x0010 /* INPGAL_ENA */
1822#define WM8962_INPGAL_ENA_MASK 0x0010 /* INPGAL_ENA */
1823#define WM8962_INPGAL_ENA_SHIFT 4 /* INPGAL_ENA */
1824#define WM8962_INPGAL_ENA_WIDTH 1 /* INPGAL_ENA */
1825#define WM8962_IN1L_TO_INPGAL 0x0008 /* IN1L_TO_INPGAL */
1826#define WM8962_IN1L_TO_INPGAL_MASK 0x0008 /* IN1L_TO_INPGAL */
1827#define WM8962_IN1L_TO_INPGAL_SHIFT 3 /* IN1L_TO_INPGAL */
1828#define WM8962_IN1L_TO_INPGAL_WIDTH 1 /* IN1L_TO_INPGAL */
1829#define WM8962_IN2L_TO_INPGAL 0x0004 /* IN2L_TO_INPGAL */
1830#define WM8962_IN2L_TO_INPGAL_MASK 0x0004 /* IN2L_TO_INPGAL */
1831#define WM8962_IN2L_TO_INPGAL_SHIFT 2 /* IN2L_TO_INPGAL */
1832#define WM8962_IN2L_TO_INPGAL_WIDTH 1 /* IN2L_TO_INPGAL */
1833#define WM8962_IN3L_TO_INPGAL 0x0002 /* IN3L_TO_INPGAL */
1834#define WM8962_IN3L_TO_INPGAL_MASK 0x0002 /* IN3L_TO_INPGAL */
1835#define WM8962_IN3L_TO_INPGAL_SHIFT 1 /* IN3L_TO_INPGAL */
1836#define WM8962_IN3L_TO_INPGAL_WIDTH 1 /* IN3L_TO_INPGAL */
1837#define WM8962_IN4L_TO_INPGAL 0x0001 /* IN4L_TO_INPGAL */
1838#define WM8962_IN4L_TO_INPGAL_MASK 0x0001 /* IN4L_TO_INPGAL */
1839#define WM8962_IN4L_TO_INPGAL_SHIFT 0 /* IN4L_TO_INPGAL */
1840#define WM8962_IN4L_TO_INPGAL_WIDTH 1 /* IN4L_TO_INPGAL */
1841
1842/*
1843 * R38 (0x26) - Right input PGA control
1844 */
1845#define WM8962_INPGAR_ENA 0x0010 /* INPGAR_ENA */
1846#define WM8962_INPGAR_ENA_MASK 0x0010 /* INPGAR_ENA */
1847#define WM8962_INPGAR_ENA_SHIFT 4 /* INPGAR_ENA */
1848#define WM8962_INPGAR_ENA_WIDTH 1 /* INPGAR_ENA */
1849#define WM8962_IN1R_TO_INPGAR 0x0008 /* IN1R_TO_INPGAR */
1850#define WM8962_IN1R_TO_INPGAR_MASK 0x0008 /* IN1R_TO_INPGAR */
1851#define WM8962_IN1R_TO_INPGAR_SHIFT 3 /* IN1R_TO_INPGAR */
1852#define WM8962_IN1R_TO_INPGAR_WIDTH 1 /* IN1R_TO_INPGAR */
1853#define WM8962_IN2R_TO_INPGAR 0x0004 /* IN2R_TO_INPGAR */
1854#define WM8962_IN2R_TO_INPGAR_MASK 0x0004 /* IN2R_TO_INPGAR */
1855#define WM8962_IN2R_TO_INPGAR_SHIFT 2 /* IN2R_TO_INPGAR */
1856#define WM8962_IN2R_TO_INPGAR_WIDTH 1 /* IN2R_TO_INPGAR */
1857#define WM8962_IN3R_TO_INPGAR 0x0002 /* IN3R_TO_INPGAR */
1858#define WM8962_IN3R_TO_INPGAR_MASK 0x0002 /* IN3R_TO_INPGAR */
1859#define WM8962_IN3R_TO_INPGAR_SHIFT 1 /* IN3R_TO_INPGAR */
1860#define WM8962_IN3R_TO_INPGAR_WIDTH 1 /* IN3R_TO_INPGAR */
1861#define WM8962_IN4R_TO_INPGAR 0x0001 /* IN4R_TO_INPGAR */
1862#define WM8962_IN4R_TO_INPGAR_MASK 0x0001 /* IN4R_TO_INPGAR */
1863#define WM8962_IN4R_TO_INPGAR_SHIFT 0 /* IN4R_TO_INPGAR */
1864#define WM8962_IN4R_TO_INPGAR_WIDTH 1 /* IN4R_TO_INPGAR */
1865
1866/*
1867 * R40 (0x28) - SPKOUTL volume
1868 */
1869#define WM8962_SPKOUT_VU 0x0100 /* SPKOUT_VU */
1870#define WM8962_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
1871#define WM8962_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
1872#define WM8962_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
1873#define WM8962_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */
1874#define WM8962_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */
1875#define WM8962_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */
1876#define WM8962_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */
1877#define WM8962_SPKOUTL_VOL_MASK 0x007F /* SPKOUTL_VOL - [6:0] */
1878#define WM8962_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [6:0] */
1879#define WM8962_SPKOUTL_VOL_WIDTH 7 /* SPKOUTL_VOL - [6:0] */
1880
1881/*
1882 * R41 (0x29) - SPKOUTR volume
1883 */
1884#define WM8962_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */
1885#define WM8962_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */
1886#define WM8962_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */
1887#define WM8962_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */
1888#define WM8962_SPKOUTR_VOL_MASK 0x007F /* SPKOUTR_VOL - [6:0] */
1889#define WM8962_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [6:0] */
1890#define WM8962_SPKOUTR_VOL_WIDTH 7 /* SPKOUTR_VOL - [6:0] */
1891
1892/*
1893 * R47 (0x2F) - Thermal Shutdown Status
1894 */
1895#define WM8962_TEMP_ERR_HP 0x0008 /* TEMP_ERR_HP */
1896#define WM8962_TEMP_ERR_HP_MASK 0x0008 /* TEMP_ERR_HP */
1897#define WM8962_TEMP_ERR_HP_SHIFT 3 /* TEMP_ERR_HP */
1898#define WM8962_TEMP_ERR_HP_WIDTH 1 /* TEMP_ERR_HP */
1899#define WM8962_TEMP_WARN_HP 0x0004 /* TEMP_WARN_HP */
1900#define WM8962_TEMP_WARN_HP_MASK 0x0004 /* TEMP_WARN_HP */
1901#define WM8962_TEMP_WARN_HP_SHIFT 2 /* TEMP_WARN_HP */
1902#define WM8962_TEMP_WARN_HP_WIDTH 1 /* TEMP_WARN_HP */
1903#define WM8962_TEMP_ERR_SPK 0x0002 /* TEMP_ERR_SPK */
1904#define WM8962_TEMP_ERR_SPK_MASK 0x0002 /* TEMP_ERR_SPK */
1905#define WM8962_TEMP_ERR_SPK_SHIFT 1 /* TEMP_ERR_SPK */
1906#define WM8962_TEMP_ERR_SPK_WIDTH 1 /* TEMP_ERR_SPK */
1907#define WM8962_TEMP_WARN_SPK 0x0001 /* TEMP_WARN_SPK */
1908#define WM8962_TEMP_WARN_SPK_MASK 0x0001 /* TEMP_WARN_SPK */
1909#define WM8962_TEMP_WARN_SPK_SHIFT 0 /* TEMP_WARN_SPK */
1910#define WM8962_TEMP_WARN_SPK_WIDTH 1 /* TEMP_WARN_SPK */
1911
1912/*
1913 * R48 (0x30) - Additional Control (4)
1914 */
1915#define WM8962_MICDET_THR_MASK 0x7000 /* MICDET_THR - [14:12] */
1916#define WM8962_MICDET_THR_SHIFT 12 /* MICDET_THR - [14:12] */
1917#define WM8962_MICDET_THR_WIDTH 3 /* MICDET_THR - [14:12] */
1918#define WM8962_MICSHORT_THR_MASK 0x0C00 /* MICSHORT_THR - [11:10] */
1919#define WM8962_MICSHORT_THR_SHIFT 10 /* MICSHORT_THR - [11:10] */
1920#define WM8962_MICSHORT_THR_WIDTH 2 /* MICSHORT_THR - [11:10] */
1921#define WM8962_MICDET_ENA 0x0200 /* MICDET_ENA */
1922#define WM8962_MICDET_ENA_MASK 0x0200 /* MICDET_ENA */
1923#define WM8962_MICDET_ENA_SHIFT 9 /* MICDET_ENA */
1924#define WM8962_MICDET_ENA_WIDTH 1 /* MICDET_ENA */
1925#define WM8962_MICDET_STS 0x0080 /* MICDET_STS */
1926#define WM8962_MICDET_STS_MASK 0x0080 /* MICDET_STS */
1927#define WM8962_MICDET_STS_SHIFT 7 /* MICDET_STS */
1928#define WM8962_MICDET_STS_WIDTH 1 /* MICDET_STS */
1929#define WM8962_MICSHORT_STS 0x0040 /* MICSHORT_STS */
1930#define WM8962_MICSHORT_STS_MASK 0x0040 /* MICSHORT_STS */
1931#define WM8962_MICSHORT_STS_SHIFT 6 /* MICSHORT_STS */
1932#define WM8962_MICSHORT_STS_WIDTH 1 /* MICSHORT_STS */
1933#define WM8962_TEMP_ENA_HP 0x0004 /* TEMP_ENA_HP */
1934#define WM8962_TEMP_ENA_HP_MASK 0x0004 /* TEMP_ENA_HP */
1935#define WM8962_TEMP_ENA_HP_SHIFT 2 /* TEMP_ENA_HP */
1936#define WM8962_TEMP_ENA_HP_WIDTH 1 /* TEMP_ENA_HP */
1937#define WM8962_TEMP_ENA_SPK 0x0002 /* TEMP_ENA_SPK */
1938#define WM8962_TEMP_ENA_SPK_MASK 0x0002 /* TEMP_ENA_SPK */
1939#define WM8962_TEMP_ENA_SPK_SHIFT 1 /* TEMP_ENA_SPK */
1940#define WM8962_TEMP_ENA_SPK_WIDTH 1 /* TEMP_ENA_SPK */
1941#define WM8962_MICBIAS_LVL 0x0001 /* MICBIAS_LVL */
1942#define WM8962_MICBIAS_LVL_MASK 0x0001 /* MICBIAS_LVL */
1943#define WM8962_MICBIAS_LVL_SHIFT 0 /* MICBIAS_LVL */
1944#define WM8962_MICBIAS_LVL_WIDTH 1 /* MICBIAS_LVL */
1945
1946/*
1947 * R49 (0x31) - Class D Control 1
1948 */
1949#define WM8962_SPKOUTR_ENA 0x0080 /* SPKOUTR_ENA */
1950#define WM8962_SPKOUTR_ENA_MASK 0x0080 /* SPKOUTR_ENA */
1951#define WM8962_SPKOUTR_ENA_SHIFT 7 /* SPKOUTR_ENA */
1952#define WM8962_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */
1953#define WM8962_SPKOUTL_ENA 0x0040 /* SPKOUTL_ENA */
1954#define WM8962_SPKOUTL_ENA_MASK 0x0040 /* SPKOUTL_ENA */
1955#define WM8962_SPKOUTL_ENA_SHIFT 6 /* SPKOUTL_ENA */
1956#define WM8962_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */
1957#define WM8962_SPKOUTL_PGA_MUTE 0x0002 /* SPKOUTL_PGA_MUTE */
1958#define WM8962_SPKOUTL_PGA_MUTE_MASK 0x0002 /* SPKOUTL_PGA_MUTE */
1959#define WM8962_SPKOUTL_PGA_MUTE_SHIFT 1 /* SPKOUTL_PGA_MUTE */
1960#define WM8962_SPKOUTL_PGA_MUTE_WIDTH 1 /* SPKOUTL_PGA_MUTE */
1961#define WM8962_SPKOUTR_PGA_MUTE 0x0001 /* SPKOUTR_PGA_MUTE */
1962#define WM8962_SPKOUTR_PGA_MUTE_MASK 0x0001 /* SPKOUTR_PGA_MUTE */
1963#define WM8962_SPKOUTR_PGA_MUTE_SHIFT 0 /* SPKOUTR_PGA_MUTE */
1964#define WM8962_SPKOUTR_PGA_MUTE_WIDTH 1 /* SPKOUTR_PGA_MUTE */
1965
1966/*
1967 * R51 (0x33) - Class D Control 2
1968 */
1969#define WM8962_SPK_MONO 0x0040 /* SPK_MONO */
1970#define WM8962_SPK_MONO_MASK 0x0040 /* SPK_MONO */
1971#define WM8962_SPK_MONO_SHIFT 6 /* SPK_MONO */
1972#define WM8962_SPK_MONO_WIDTH 1 /* SPK_MONO */
1973#define WM8962_CLASSD_VOL_MASK 0x0007 /* CLASSD_VOL - [2:0] */
1974#define WM8962_CLASSD_VOL_SHIFT 0 /* CLASSD_VOL - [2:0] */
1975#define WM8962_CLASSD_VOL_WIDTH 3 /* CLASSD_VOL - [2:0] */
1976
1977/*
1978 * R56 (0x38) - Clocking 4
1979 */
1980#define WM8962_SYSCLK_RATE_MASK 0x001E /* SYSCLK_RATE - [4:1] */
1981#define WM8962_SYSCLK_RATE_SHIFT 1 /* SYSCLK_RATE - [4:1] */
1982#define WM8962_SYSCLK_RATE_WIDTH 4 /* SYSCLK_RATE - [4:1] */
1983
1984/*
1985 * R57 (0x39) - DAC DSP Mixing (1)
1986 */
1987#define WM8962_DAC_MONOMIX 0x0200 /* DAC_MONOMIX */
1988#define WM8962_DAC_MONOMIX_MASK 0x0200 /* DAC_MONOMIX */
1989#define WM8962_DAC_MONOMIX_SHIFT 9 /* DAC_MONOMIX */
1990#define WM8962_DAC_MONOMIX_WIDTH 1 /* DAC_MONOMIX */
1991#define WM8962_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */
1992#define WM8962_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */
1993#define WM8962_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */
1994#define WM8962_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */
1995#define WM8962_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */
1996#define WM8962_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */
1997
1998/*
1999 * R58 (0x3A) - DAC DSP Mixing (2)
2000 */
2001#define WM8962_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */
2002#define WM8962_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */
2003#define WM8962_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */
2004#define WM8962_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */
2005#define WM8962_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */
2006#define WM8962_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */
2007
2008/*
2009 * R60 (0x3C) - DC Servo 0
2010 */
2011#define WM8962_INL_DCS_ENA 0x0080 /* INL_DCS_ENA */
2012#define WM8962_INL_DCS_ENA_MASK 0x0080 /* INL_DCS_ENA */
2013#define WM8962_INL_DCS_ENA_SHIFT 7 /* INL_DCS_ENA */
2014#define WM8962_INL_DCS_ENA_WIDTH 1 /* INL_DCS_ENA */
2015#define WM8962_INL_DCS_STARTUP 0x0040 /* INL_DCS_STARTUP */
2016#define WM8962_INL_DCS_STARTUP_MASK 0x0040 /* INL_DCS_STARTUP */
2017#define WM8962_INL_DCS_STARTUP_SHIFT 6 /* INL_DCS_STARTUP */
2018#define WM8962_INL_DCS_STARTUP_WIDTH 1 /* INL_DCS_STARTUP */
2019#define WM8962_INR_DCS_ENA 0x0008 /* INR_DCS_ENA */
2020#define WM8962_INR_DCS_ENA_MASK 0x0008 /* INR_DCS_ENA */
2021#define WM8962_INR_DCS_ENA_SHIFT 3 /* INR_DCS_ENA */
2022#define WM8962_INR_DCS_ENA_WIDTH 1 /* INR_DCS_ENA */
2023#define WM8962_INR_DCS_STARTUP 0x0004 /* INR_DCS_STARTUP */
2024#define WM8962_INR_DCS_STARTUP_MASK 0x0004 /* INR_DCS_STARTUP */
2025#define WM8962_INR_DCS_STARTUP_SHIFT 2 /* INR_DCS_STARTUP */
2026#define WM8962_INR_DCS_STARTUP_WIDTH 1 /* INR_DCS_STARTUP */
2027
2028/*
2029 * R61 (0x3D) - DC Servo 1
2030 */
2031#define WM8962_HP1L_DCS_ENA 0x0080 /* HP1L_DCS_ENA */
2032#define WM8962_HP1L_DCS_ENA_MASK 0x0080 /* HP1L_DCS_ENA */
2033#define WM8962_HP1L_DCS_ENA_SHIFT 7 /* HP1L_DCS_ENA */
2034#define WM8962_HP1L_DCS_ENA_WIDTH 1 /* HP1L_DCS_ENA */
2035#define WM8962_HP1L_DCS_STARTUP 0x0040 /* HP1L_DCS_STARTUP */
2036#define WM8962_HP1L_DCS_STARTUP_MASK 0x0040 /* HP1L_DCS_STARTUP */
2037#define WM8962_HP1L_DCS_STARTUP_SHIFT 6 /* HP1L_DCS_STARTUP */
2038#define WM8962_HP1L_DCS_STARTUP_WIDTH 1 /* HP1L_DCS_STARTUP */
2039#define WM8962_HP1L_DCS_SYNC 0x0010 /* HP1L_DCS_SYNC */
2040#define WM8962_HP1L_DCS_SYNC_MASK 0x0010 /* HP1L_DCS_SYNC */
2041#define WM8962_HP1L_DCS_SYNC_SHIFT 4 /* HP1L_DCS_SYNC */
2042#define WM8962_HP1L_DCS_SYNC_WIDTH 1 /* HP1L_DCS_SYNC */
2043#define WM8962_HP1R_DCS_ENA 0x0008 /* HP1R_DCS_ENA */
2044#define WM8962_HP1R_DCS_ENA_MASK 0x0008 /* HP1R_DCS_ENA */
2045#define WM8962_HP1R_DCS_ENA_SHIFT 3 /* HP1R_DCS_ENA */
2046#define WM8962_HP1R_DCS_ENA_WIDTH 1 /* HP1R_DCS_ENA */
2047#define WM8962_HP1R_DCS_STARTUP 0x0004 /* HP1R_DCS_STARTUP */
2048#define WM8962_HP1R_DCS_STARTUP_MASK 0x0004 /* HP1R_DCS_STARTUP */
2049#define WM8962_HP1R_DCS_STARTUP_SHIFT 2 /* HP1R_DCS_STARTUP */
2050#define WM8962_HP1R_DCS_STARTUP_WIDTH 1 /* HP1R_DCS_STARTUP */
2051#define WM8962_HP1R_DCS_SYNC 0x0001 /* HP1R_DCS_SYNC */
2052#define WM8962_HP1R_DCS_SYNC_MASK 0x0001 /* HP1R_DCS_SYNC */
2053#define WM8962_HP1R_DCS_SYNC_SHIFT 0 /* HP1R_DCS_SYNC */
2054#define WM8962_HP1R_DCS_SYNC_WIDTH 1 /* HP1R_DCS_SYNC */
2055
2056/*
2057 * R64 (0x40) - DC Servo 4
2058 */
2059#define WM8962_HP1_DCS_SYNC_STEPS_MASK 0x3F80 /* HP1_DCS_SYNC_STEPS - [13:7] */
2060#define WM8962_HP1_DCS_SYNC_STEPS_SHIFT 7 /* HP1_DCS_SYNC_STEPS - [13:7] */
2061#define WM8962_HP1_DCS_SYNC_STEPS_WIDTH 7 /* HP1_DCS_SYNC_STEPS - [13:7] */
2062
2063/*
2064 * R66 (0x42) - DC Servo 6
2065 */
2066#define WM8962_DCS_STARTUP_DONE_INL 0x0400 /* DCS_STARTUP_DONE_INL */
2067#define WM8962_DCS_STARTUP_DONE_INL_MASK 0x0400 /* DCS_STARTUP_DONE_INL */
2068#define WM8962_DCS_STARTUP_DONE_INL_SHIFT 10 /* DCS_STARTUP_DONE_INL */
2069#define WM8962_DCS_STARTUP_DONE_INL_WIDTH 1 /* DCS_STARTUP_DONE_INL */
2070#define WM8962_DCS_STARTUP_DONE_INR 0x0200 /* DCS_STARTUP_DONE_INR */
2071#define WM8962_DCS_STARTUP_DONE_INR_MASK 0x0200 /* DCS_STARTUP_DONE_INR */
2072#define WM8962_DCS_STARTUP_DONE_INR_SHIFT 9 /* DCS_STARTUP_DONE_INR */
2073#define WM8962_DCS_STARTUP_DONE_INR_WIDTH 1 /* DCS_STARTUP_DONE_INR */
2074#define WM8962_DCS_STARTUP_DONE_HP1L 0x0100 /* DCS_STARTUP_DONE_HP1L */
2075#define WM8962_DCS_STARTUP_DONE_HP1L_MASK 0x0100 /* DCS_STARTUP_DONE_HP1L */
2076#define WM8962_DCS_STARTUP_DONE_HP1L_SHIFT 8 /* DCS_STARTUP_DONE_HP1L */
2077#define WM8962_DCS_STARTUP_DONE_HP1L_WIDTH 1 /* DCS_STARTUP_DONE_HP1L */
2078#define WM8962_DCS_STARTUP_DONE_HP1R 0x0080 /* DCS_STARTUP_DONE_HP1R */
2079#define WM8962_DCS_STARTUP_DONE_HP1R_MASK 0x0080 /* DCS_STARTUP_DONE_HP1R */
2080#define WM8962_DCS_STARTUP_DONE_HP1R_SHIFT 7 /* DCS_STARTUP_DONE_HP1R */
2081#define WM8962_DCS_STARTUP_DONE_HP1R_WIDTH 1 /* DCS_STARTUP_DONE_HP1R */
2082
2083/*
2084 * R68 (0x44) - Analogue PGA Bias
2085 */
2086#define WM8962_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */
2087#define WM8962_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */
2088#define WM8962_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */
2089
2090/*
2091 * R69 (0x45) - Analogue HP 0
2092 */
2093#define WM8962_HP1L_RMV_SHORT 0x0080 /* HP1L_RMV_SHORT */
2094#define WM8962_HP1L_RMV_SHORT_MASK 0x0080 /* HP1L_RMV_SHORT */
2095#define WM8962_HP1L_RMV_SHORT_SHIFT 7 /* HP1L_RMV_SHORT */
2096#define WM8962_HP1L_RMV_SHORT_WIDTH 1 /* HP1L_RMV_SHORT */
2097#define WM8962_HP1L_ENA_OUTP 0x0040 /* HP1L_ENA_OUTP */
2098#define WM8962_HP1L_ENA_OUTP_MASK 0x0040 /* HP1L_ENA_OUTP */
2099#define WM8962_HP1L_ENA_OUTP_SHIFT 6 /* HP1L_ENA_OUTP */
2100#define WM8962_HP1L_ENA_OUTP_WIDTH 1 /* HP1L_ENA_OUTP */
2101#define WM8962_HP1L_ENA_DLY 0x0020 /* HP1L_ENA_DLY */
2102#define WM8962_HP1L_ENA_DLY_MASK 0x0020 /* HP1L_ENA_DLY */
2103#define WM8962_HP1L_ENA_DLY_SHIFT 5 /* HP1L_ENA_DLY */
2104#define WM8962_HP1L_ENA_DLY_WIDTH 1 /* HP1L_ENA_DLY */
2105#define WM8962_HP1L_ENA 0x0010 /* HP1L_ENA */
2106#define WM8962_HP1L_ENA_MASK 0x0010 /* HP1L_ENA */
2107#define WM8962_HP1L_ENA_SHIFT 4 /* HP1L_ENA */
2108#define WM8962_HP1L_ENA_WIDTH 1 /* HP1L_ENA */
2109#define WM8962_HP1R_RMV_SHORT 0x0008 /* HP1R_RMV_SHORT */
2110#define WM8962_HP1R_RMV_SHORT_MASK 0x0008 /* HP1R_RMV_SHORT */
2111#define WM8962_HP1R_RMV_SHORT_SHIFT 3 /* HP1R_RMV_SHORT */
2112#define WM8962_HP1R_RMV_SHORT_WIDTH 1 /* HP1R_RMV_SHORT */
2113#define WM8962_HP1R_ENA_OUTP 0x0004 /* HP1R_ENA_OUTP */
2114#define WM8962_HP1R_ENA_OUTP_MASK 0x0004 /* HP1R_ENA_OUTP */
2115#define WM8962_HP1R_ENA_OUTP_SHIFT 2 /* HP1R_ENA_OUTP */
2116#define WM8962_HP1R_ENA_OUTP_WIDTH 1 /* HP1R_ENA_OUTP */
2117#define WM8962_HP1R_ENA_DLY 0x0002 /* HP1R_ENA_DLY */
2118#define WM8962_HP1R_ENA_DLY_MASK 0x0002 /* HP1R_ENA_DLY */
2119#define WM8962_HP1R_ENA_DLY_SHIFT 1 /* HP1R_ENA_DLY */
2120#define WM8962_HP1R_ENA_DLY_WIDTH 1 /* HP1R_ENA_DLY */
2121#define WM8962_HP1R_ENA 0x0001 /* HP1R_ENA */
2122#define WM8962_HP1R_ENA_MASK 0x0001 /* HP1R_ENA */
2123#define WM8962_HP1R_ENA_SHIFT 0 /* HP1R_ENA */
2124#define WM8962_HP1R_ENA_WIDTH 1 /* HP1R_ENA */
2125
2126/*
2127 * R71 (0x47) - Analogue HP 2
2128 */
2129#define WM8962_HP1L_VOL_MASK 0x01C0 /* HP1L_VOL - [8:6] */
2130#define WM8962_HP1L_VOL_SHIFT 6 /* HP1L_VOL - [8:6] */
2131#define WM8962_HP1L_VOL_WIDTH 3 /* HP1L_VOL - [8:6] */
2132#define WM8962_HP1R_VOL_MASK 0x0038 /* HP1R_VOL - [5:3] */
2133#define WM8962_HP1R_VOL_SHIFT 3 /* HP1R_VOL - [5:3] */
2134#define WM8962_HP1R_VOL_WIDTH 3 /* HP1R_VOL - [5:3] */
2135#define WM8962_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */
2136#define WM8962_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */
2137#define WM8962_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */
2138
2139/*
2140 * R72 (0x48) - Charge Pump 1
2141 */
2142#define WM8962_CP_ENA 0x0001 /* CP_ENA */
2143#define WM8962_CP_ENA_MASK 0x0001 /* CP_ENA */
2144#define WM8962_CP_ENA_SHIFT 0 /* CP_ENA */
2145#define WM8962_CP_ENA_WIDTH 1 /* CP_ENA */
2146
2147/*
2148 * R82 (0x52) - Charge Pump B
2149 */
2150#define WM8962_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */
2151#define WM8962_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */
2152#define WM8962_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */
2153#define WM8962_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */
2154
2155/*
2156 * R87 (0x57) - Write Sequencer Control 1
2157 */
2158#define WM8962_WSEQ_AUTOSEQ_ENA 0x0080 /* WSEQ_AUTOSEQ_ENA */
2159#define WM8962_WSEQ_AUTOSEQ_ENA_MASK 0x0080 /* WSEQ_AUTOSEQ_ENA */
2160#define WM8962_WSEQ_AUTOSEQ_ENA_SHIFT 7 /* WSEQ_AUTOSEQ_ENA */
2161#define WM8962_WSEQ_AUTOSEQ_ENA_WIDTH 1 /* WSEQ_AUTOSEQ_ENA */
2162#define WM8962_WSEQ_ENA 0x0020 /* WSEQ_ENA */
2163#define WM8962_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */
2164#define WM8962_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */
2165#define WM8962_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
2166
2167/*
2168 * R90 (0x5A) - Write Sequencer Control 2
2169 */
2170#define WM8962_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */
2171#define WM8962_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */
2172#define WM8962_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */
2173#define WM8962_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
2174#define WM8962_WSEQ_START 0x0080 /* WSEQ_START */
2175#define WM8962_WSEQ_START_MASK 0x0080 /* WSEQ_START */
2176#define WM8962_WSEQ_START_SHIFT 7 /* WSEQ_START */
2177#define WM8962_WSEQ_START_WIDTH 1 /* WSEQ_START */
2178#define WM8962_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */
2179#define WM8962_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */
2180#define WM8962_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */
2181
2182/*
2183 * R93 (0x5D) - Write Sequencer Control 3
2184 */
2185#define WM8962_WSEQ_CURRENT_INDEX_MASK 0x03F8 /* WSEQ_CURRENT_INDEX - [9:3] */
2186#define WM8962_WSEQ_CURRENT_INDEX_SHIFT 3 /* WSEQ_CURRENT_INDEX - [9:3] */
2187#define WM8962_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [9:3] */
2188#define WM8962_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */
2189#define WM8962_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */
2190#define WM8962_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */
2191#define WM8962_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
2192
2193/*
2194 * R94 (0x5E) - Control Interface
2195 */
2196#define WM8962_SPI_CONTRD 0x0040 /* SPI_CONTRD */
2197#define WM8962_SPI_CONTRD_MASK 0x0040 /* SPI_CONTRD */
2198#define WM8962_SPI_CONTRD_SHIFT 6 /* SPI_CONTRD */
2199#define WM8962_SPI_CONTRD_WIDTH 1 /* SPI_CONTRD */
2200#define WM8962_SPI_4WIRE 0x0020 /* SPI_4WIRE */
2201#define WM8962_SPI_4WIRE_MASK 0x0020 /* SPI_4WIRE */
2202#define WM8962_SPI_4WIRE_SHIFT 5 /* SPI_4WIRE */
2203#define WM8962_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */
2204#define WM8962_SPI_CFG 0x0010 /* SPI_CFG */
2205#define WM8962_SPI_CFG_MASK 0x0010 /* SPI_CFG */
2206#define WM8962_SPI_CFG_SHIFT 4 /* SPI_CFG */
2207#define WM8962_SPI_CFG_WIDTH 1 /* SPI_CFG */
2208
2209/*
2210 * R99 (0x63) - Mixer Enables
2211 */
2212#define WM8962_HPMIXL_ENA 0x0008 /* HPMIXL_ENA */
2213#define WM8962_HPMIXL_ENA_MASK 0x0008 /* HPMIXL_ENA */
2214#define WM8962_HPMIXL_ENA_SHIFT 3 /* HPMIXL_ENA */
2215#define WM8962_HPMIXL_ENA_WIDTH 1 /* HPMIXL_ENA */
2216#define WM8962_HPMIXR_ENA 0x0004 /* HPMIXR_ENA */
2217#define WM8962_HPMIXR_ENA_MASK 0x0004 /* HPMIXR_ENA */
2218#define WM8962_HPMIXR_ENA_SHIFT 2 /* HPMIXR_ENA */
2219#define WM8962_HPMIXR_ENA_WIDTH 1 /* HPMIXR_ENA */
2220#define WM8962_SPKMIXL_ENA 0x0002 /* SPKMIXL_ENA */
2221#define WM8962_SPKMIXL_ENA_MASK 0x0002 /* SPKMIXL_ENA */
2222#define WM8962_SPKMIXL_ENA_SHIFT 1 /* SPKMIXL_ENA */
2223#define WM8962_SPKMIXL_ENA_WIDTH 1 /* SPKMIXL_ENA */
2224#define WM8962_SPKMIXR_ENA 0x0001 /* SPKMIXR_ENA */
2225#define WM8962_SPKMIXR_ENA_MASK 0x0001 /* SPKMIXR_ENA */
2226#define WM8962_SPKMIXR_ENA_SHIFT 0 /* SPKMIXR_ENA */
2227#define WM8962_SPKMIXR_ENA_WIDTH 1 /* SPKMIXR_ENA */
2228
2229/*
2230 * R100 (0x64) - Headphone Mixer (1)
2231 */
2232#define WM8962_HPMIXL_TO_HPOUTL_PGA 0x0080 /* HPMIXL_TO_HPOUTL_PGA */
2233#define WM8962_HPMIXL_TO_HPOUTL_PGA_MASK 0x0080 /* HPMIXL_TO_HPOUTL_PGA */
2234#define WM8962_HPMIXL_TO_HPOUTL_PGA_SHIFT 7 /* HPMIXL_TO_HPOUTL_PGA */
2235#define WM8962_HPMIXL_TO_HPOUTL_PGA_WIDTH 1 /* HPMIXL_TO_HPOUTL_PGA */
2236#define WM8962_DACL_TO_HPMIXL 0x0020 /* DACL_TO_HPMIXL */
2237#define WM8962_DACL_TO_HPMIXL_MASK 0x0020 /* DACL_TO_HPMIXL */
2238#define WM8962_DACL_TO_HPMIXL_SHIFT 5 /* DACL_TO_HPMIXL */
2239#define WM8962_DACL_TO_HPMIXL_WIDTH 1 /* DACL_TO_HPMIXL */
2240#define WM8962_DACR_TO_HPMIXL 0x0010 /* DACR_TO_HPMIXL */
2241#define WM8962_DACR_TO_HPMIXL_MASK 0x0010 /* DACR_TO_HPMIXL */
2242#define WM8962_DACR_TO_HPMIXL_SHIFT 4 /* DACR_TO_HPMIXL */
2243#define WM8962_DACR_TO_HPMIXL_WIDTH 1 /* DACR_TO_HPMIXL */
2244#define WM8962_MIXINL_TO_HPMIXL 0x0008 /* MIXINL_TO_HPMIXL */
2245#define WM8962_MIXINL_TO_HPMIXL_MASK 0x0008 /* MIXINL_TO_HPMIXL */
2246#define WM8962_MIXINL_TO_HPMIXL_SHIFT 3 /* MIXINL_TO_HPMIXL */
2247#define WM8962_MIXINL_TO_HPMIXL_WIDTH 1 /* MIXINL_TO_HPMIXL */
2248#define WM8962_MIXINR_TO_HPMIXL 0x0004 /* MIXINR_TO_HPMIXL */
2249#define WM8962_MIXINR_TO_HPMIXL_MASK 0x0004 /* MIXINR_TO_HPMIXL */
2250#define WM8962_MIXINR_TO_HPMIXL_SHIFT 2 /* MIXINR_TO_HPMIXL */
2251#define WM8962_MIXINR_TO_HPMIXL_WIDTH 1 /* MIXINR_TO_HPMIXL */
2252#define WM8962_IN4L_TO_HPMIXL 0x0002 /* IN4L_TO_HPMIXL */
2253#define WM8962_IN4L_TO_HPMIXL_MASK 0x0002 /* IN4L_TO_HPMIXL */
2254#define WM8962_IN4L_TO_HPMIXL_SHIFT 1 /* IN4L_TO_HPMIXL */
2255#define WM8962_IN4L_TO_HPMIXL_WIDTH 1 /* IN4L_TO_HPMIXL */
2256#define WM8962_IN4R_TO_HPMIXL 0x0001 /* IN4R_TO_HPMIXL */
2257#define WM8962_IN4R_TO_HPMIXL_MASK 0x0001 /* IN4R_TO_HPMIXL */
2258#define WM8962_IN4R_TO_HPMIXL_SHIFT 0 /* IN4R_TO_HPMIXL */
2259#define WM8962_IN4R_TO_HPMIXL_WIDTH 1 /* IN4R_TO_HPMIXL */
2260
2261/*
2262 * R101 (0x65) - Headphone Mixer (2)
2263 */
2264#define WM8962_HPMIXR_TO_HPOUTR_PGA 0x0080 /* HPMIXR_TO_HPOUTR_PGA */
2265#define WM8962_HPMIXR_TO_HPOUTR_PGA_MASK 0x0080 /* HPMIXR_TO_HPOUTR_PGA */
2266#define WM8962_HPMIXR_TO_HPOUTR_PGA_SHIFT 7 /* HPMIXR_TO_HPOUTR_PGA */
2267#define WM8962_HPMIXR_TO_HPOUTR_PGA_WIDTH 1 /* HPMIXR_TO_HPOUTR_PGA */
2268#define WM8962_DACL_TO_HPMIXR 0x0020 /* DACL_TO_HPMIXR */
2269#define WM8962_DACL_TO_HPMIXR_MASK 0x0020 /* DACL_TO_HPMIXR */
2270#define WM8962_DACL_TO_HPMIXR_SHIFT 5 /* DACL_TO_HPMIXR */
2271#define WM8962_DACL_TO_HPMIXR_WIDTH 1 /* DACL_TO_HPMIXR */
2272#define WM8962_DACR_TO_HPMIXR 0x0010 /* DACR_TO_HPMIXR */
2273#define WM8962_DACR_TO_HPMIXR_MASK 0x0010 /* DACR_TO_HPMIXR */
2274#define WM8962_DACR_TO_HPMIXR_SHIFT 4 /* DACR_TO_HPMIXR */
2275#define WM8962_DACR_TO_HPMIXR_WIDTH 1 /* DACR_TO_HPMIXR */
2276#define WM8962_MIXINL_TO_HPMIXR 0x0008 /* MIXINL_TO_HPMIXR */
2277#define WM8962_MIXINL_TO_HPMIXR_MASK 0x0008 /* MIXINL_TO_HPMIXR */
2278#define WM8962_MIXINL_TO_HPMIXR_SHIFT 3 /* MIXINL_TO_HPMIXR */
2279#define WM8962_MIXINL_TO_HPMIXR_WIDTH 1 /* MIXINL_TO_HPMIXR */
2280#define WM8962_MIXINR_TO_HPMIXR 0x0004 /* MIXINR_TO_HPMIXR */
2281#define WM8962_MIXINR_TO_HPMIXR_MASK 0x0004 /* MIXINR_TO_HPMIXR */
2282#define WM8962_MIXINR_TO_HPMIXR_SHIFT 2 /* MIXINR_TO_HPMIXR */
2283#define WM8962_MIXINR_TO_HPMIXR_WIDTH 1 /* MIXINR_TO_HPMIXR */
2284#define WM8962_IN4L_TO_HPMIXR 0x0002 /* IN4L_TO_HPMIXR */
2285#define WM8962_IN4L_TO_HPMIXR_MASK 0x0002 /* IN4L_TO_HPMIXR */
2286#define WM8962_IN4L_TO_HPMIXR_SHIFT 1 /* IN4L_TO_HPMIXR */
2287#define WM8962_IN4L_TO_HPMIXR_WIDTH 1 /* IN4L_TO_HPMIXR */
2288#define WM8962_IN4R_TO_HPMIXR 0x0001 /* IN4R_TO_HPMIXR */
2289#define WM8962_IN4R_TO_HPMIXR_MASK 0x0001 /* IN4R_TO_HPMIXR */
2290#define WM8962_IN4R_TO_HPMIXR_SHIFT 0 /* IN4R_TO_HPMIXR */
2291#define WM8962_IN4R_TO_HPMIXR_WIDTH 1 /* IN4R_TO_HPMIXR */
2292
2293/*
2294 * R102 (0x66) - Headphone Mixer (3)
2295 */
2296#define WM8962_HPMIXL_MUTE 0x0100 /* HPMIXL_MUTE */
2297#define WM8962_HPMIXL_MUTE_MASK 0x0100 /* HPMIXL_MUTE */
2298#define WM8962_HPMIXL_MUTE_SHIFT 8 /* HPMIXL_MUTE */
2299#define WM8962_HPMIXL_MUTE_WIDTH 1 /* HPMIXL_MUTE */
2300#define WM8962_MIXINL_HPMIXL_VOL 0x0080 /* MIXINL_HPMIXL_VOL */
2301#define WM8962_MIXINL_HPMIXL_VOL_MASK 0x0080 /* MIXINL_HPMIXL_VOL */
2302#define WM8962_MIXINL_HPMIXL_VOL_SHIFT 7 /* MIXINL_HPMIXL_VOL */
2303#define WM8962_MIXINL_HPMIXL_VOL_WIDTH 1 /* MIXINL_HPMIXL_VOL */
2304#define WM8962_MIXINR_HPMIXL_VOL 0x0040 /* MIXINR_HPMIXL_VOL */
2305#define WM8962_MIXINR_HPMIXL_VOL_MASK 0x0040 /* MIXINR_HPMIXL_VOL */
2306#define WM8962_MIXINR_HPMIXL_VOL_SHIFT 6 /* MIXINR_HPMIXL_VOL */
2307#define WM8962_MIXINR_HPMIXL_VOL_WIDTH 1 /* MIXINR_HPMIXL_VOL */
2308#define WM8962_IN4L_HPMIXL_VOL_MASK 0x0038 /* IN4L_HPMIXL_VOL - [5:3] */
2309#define WM8962_IN4L_HPMIXL_VOL_SHIFT 3 /* IN4L_HPMIXL_VOL - [5:3] */
2310#define WM8962_IN4L_HPMIXL_VOL_WIDTH 3 /* IN4L_HPMIXL_VOL - [5:3] */
2311#define WM8962_IN4R_HPMIXL_VOL_MASK 0x0007 /* IN4R_HPMIXL_VOL - [2:0] */
2312#define WM8962_IN4R_HPMIXL_VOL_SHIFT 0 /* IN4R_HPMIXL_VOL - [2:0] */
2313#define WM8962_IN4R_HPMIXL_VOL_WIDTH 3 /* IN4R_HPMIXL_VOL - [2:0] */
2314
2315/*
2316 * R103 (0x67) - Headphone Mixer (4)
2317 */
2318#define WM8962_HPMIXR_MUTE 0x0100 /* HPMIXR_MUTE */
2319#define WM8962_HPMIXR_MUTE_MASK 0x0100 /* HPMIXR_MUTE */
2320#define WM8962_HPMIXR_MUTE_SHIFT 8 /* HPMIXR_MUTE */
2321#define WM8962_HPMIXR_MUTE_WIDTH 1 /* HPMIXR_MUTE */
2322#define WM8962_MIXINL_HPMIXR_VOL 0x0080 /* MIXINL_HPMIXR_VOL */
2323#define WM8962_MIXINL_HPMIXR_VOL_MASK 0x0080 /* MIXINL_HPMIXR_VOL */
2324#define WM8962_MIXINL_HPMIXR_VOL_SHIFT 7 /* MIXINL_HPMIXR_VOL */
2325#define WM8962_MIXINL_HPMIXR_VOL_WIDTH 1 /* MIXINL_HPMIXR_VOL */
2326#define WM8962_MIXINR_HPMIXR_VOL 0x0040 /* MIXINR_HPMIXR_VOL */
2327#define WM8962_MIXINR_HPMIXR_VOL_MASK 0x0040 /* MIXINR_HPMIXR_VOL */
2328#define WM8962_MIXINR_HPMIXR_VOL_SHIFT 6 /* MIXINR_HPMIXR_VOL */
2329#define WM8962_MIXINR_HPMIXR_VOL_WIDTH 1 /* MIXINR_HPMIXR_VOL */
2330#define WM8962_IN4L_HPMIXR_VOL_MASK 0x0038 /* IN4L_HPMIXR_VOL - [5:3] */
2331#define WM8962_IN4L_HPMIXR_VOL_SHIFT 3 /* IN4L_HPMIXR_VOL - [5:3] */
2332#define WM8962_IN4L_HPMIXR_VOL_WIDTH 3 /* IN4L_HPMIXR_VOL - [5:3] */
2333#define WM8962_IN4R_HPMIXR_VOL_MASK 0x0007 /* IN4R_HPMIXR_VOL - [2:0] */
2334#define WM8962_IN4R_HPMIXR_VOL_SHIFT 0 /* IN4R_HPMIXR_VOL - [2:0] */
2335#define WM8962_IN4R_HPMIXR_VOL_WIDTH 3 /* IN4R_HPMIXR_VOL - [2:0] */
2336
2337/*
2338 * R105 (0x69) - Speaker Mixer (1)
2339 */
2340#define WM8962_SPKMIXL_TO_SPKOUTL_PGA 0x0080 /* SPKMIXL_TO_SPKOUTL_PGA */
2341#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_MASK 0x0080 /* SPKMIXL_TO_SPKOUTL_PGA */
2342#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_SHIFT 7 /* SPKMIXL_TO_SPKOUTL_PGA */
2343#define WM8962_SPKMIXL_TO_SPKOUTL_PGA_WIDTH 1 /* SPKMIXL_TO_SPKOUTL_PGA */
2344#define WM8962_DACL_TO_SPKMIXL 0x0020 /* DACL_TO_SPKMIXL */
2345#define WM8962_DACL_TO_SPKMIXL_MASK 0x0020 /* DACL_TO_SPKMIXL */
2346#define WM8962_DACL_TO_SPKMIXL_SHIFT 5 /* DACL_TO_SPKMIXL */
2347#define WM8962_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */
2348#define WM8962_DACR_TO_SPKMIXL 0x0010 /* DACR_TO_SPKMIXL */
2349#define WM8962_DACR_TO_SPKMIXL_MASK 0x0010 /* DACR_TO_SPKMIXL */
2350#define WM8962_DACR_TO_SPKMIXL_SHIFT 4 /* DACR_TO_SPKMIXL */
2351#define WM8962_DACR_TO_SPKMIXL_WIDTH 1 /* DACR_TO_SPKMIXL */
2352#define WM8962_MIXINL_TO_SPKMIXL 0x0008 /* MIXINL_TO_SPKMIXL */
2353#define WM8962_MIXINL_TO_SPKMIXL_MASK 0x0008 /* MIXINL_TO_SPKMIXL */
2354#define WM8962_MIXINL_TO_SPKMIXL_SHIFT 3 /* MIXINL_TO_SPKMIXL */
2355#define WM8962_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */
2356#define WM8962_MIXINR_TO_SPKMIXL 0x0004 /* MIXINR_TO_SPKMIXL */
2357#define WM8962_MIXINR_TO_SPKMIXL_MASK 0x0004 /* MIXINR_TO_SPKMIXL */
2358#define WM8962_MIXINR_TO_SPKMIXL_SHIFT 2 /* MIXINR_TO_SPKMIXL */
2359#define WM8962_MIXINR_TO_SPKMIXL_WIDTH 1 /* MIXINR_TO_SPKMIXL */
2360#define WM8962_IN4L_TO_SPKMIXL 0x0002 /* IN4L_TO_SPKMIXL */
2361#define WM8962_IN4L_TO_SPKMIXL_MASK 0x0002 /* IN4L_TO_SPKMIXL */
2362#define WM8962_IN4L_TO_SPKMIXL_SHIFT 1 /* IN4L_TO_SPKMIXL */
2363#define WM8962_IN4L_TO_SPKMIXL_WIDTH 1 /* IN4L_TO_SPKMIXL */
2364#define WM8962_IN4R_TO_SPKMIXL 0x0001 /* IN4R_TO_SPKMIXL */
2365#define WM8962_IN4R_TO_SPKMIXL_MASK 0x0001 /* IN4R_TO_SPKMIXL */
2366#define WM8962_IN4R_TO_SPKMIXL_SHIFT 0 /* IN4R_TO_SPKMIXL */
2367#define WM8962_IN4R_TO_SPKMIXL_WIDTH 1 /* IN4R_TO_SPKMIXL */
2368
2369/*
2370 * R106 (0x6A) - Speaker Mixer (2)
2371 */
2372#define WM8962_SPKMIXR_TO_SPKOUTR_PGA 0x0080 /* SPKMIXR_TO_SPKOUTR_PGA */
2373#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_MASK 0x0080 /* SPKMIXR_TO_SPKOUTR_PGA */
2374#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_SHIFT 7 /* SPKMIXR_TO_SPKOUTR_PGA */
2375#define WM8962_SPKMIXR_TO_SPKOUTR_PGA_WIDTH 1 /* SPKMIXR_TO_SPKOUTR_PGA */
2376#define WM8962_DACL_TO_SPKMIXR 0x0020 /* DACL_TO_SPKMIXR */
2377#define WM8962_DACL_TO_SPKMIXR_MASK 0x0020 /* DACL_TO_SPKMIXR */
2378#define WM8962_DACL_TO_SPKMIXR_SHIFT 5 /* DACL_TO_SPKMIXR */
2379#define WM8962_DACL_TO_SPKMIXR_WIDTH 1 /* DACL_TO_SPKMIXR */
2380#define WM8962_DACR_TO_SPKMIXR 0x0010 /* DACR_TO_SPKMIXR */
2381#define WM8962_DACR_TO_SPKMIXR_MASK 0x0010 /* DACR_TO_SPKMIXR */
2382#define WM8962_DACR_TO_SPKMIXR_SHIFT 4 /* DACR_TO_SPKMIXR */
2383#define WM8962_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */
2384#define WM8962_MIXINL_TO_SPKMIXR 0x0008 /* MIXINL_TO_SPKMIXR */
2385#define WM8962_MIXINL_TO_SPKMIXR_MASK 0x0008 /* MIXINL_TO_SPKMIXR */
2386#define WM8962_MIXINL_TO_SPKMIXR_SHIFT 3 /* MIXINL_TO_SPKMIXR */
2387#define WM8962_MIXINL_TO_SPKMIXR_WIDTH 1 /* MIXINL_TO_SPKMIXR */
2388#define WM8962_MIXINR_TO_SPKMIXR 0x0004 /* MIXINR_TO_SPKMIXR */
2389#define WM8962_MIXINR_TO_SPKMIXR_MASK 0x0004 /* MIXINR_TO_SPKMIXR */
2390#define WM8962_MIXINR_TO_SPKMIXR_SHIFT 2 /* MIXINR_TO_SPKMIXR */
2391#define WM8962_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */
2392#define WM8962_IN4L_TO_SPKMIXR 0x0002 /* IN4L_TO_SPKMIXR */
2393#define WM8962_IN4L_TO_SPKMIXR_MASK 0x0002 /* IN4L_TO_SPKMIXR */
2394#define WM8962_IN4L_TO_SPKMIXR_SHIFT 1 /* IN4L_TO_SPKMIXR */
2395#define WM8962_IN4L_TO_SPKMIXR_WIDTH 1 /* IN4L_TO_SPKMIXR */
2396#define WM8962_IN4R_TO_SPKMIXR 0x0001 /* IN4R_TO_SPKMIXR */
2397#define WM8962_IN4R_TO_SPKMIXR_MASK 0x0001 /* IN4R_TO_SPKMIXR */
2398#define WM8962_IN4R_TO_SPKMIXR_SHIFT 0 /* IN4R_TO_SPKMIXR */
2399#define WM8962_IN4R_TO_SPKMIXR_WIDTH 1 /* IN4R_TO_SPKMIXR */
2400
2401/*
2402 * R107 (0x6B) - Speaker Mixer (3)
2403 */
2404#define WM8962_SPKMIXL_MUTE 0x0100 /* SPKMIXL_MUTE */
2405#define WM8962_SPKMIXL_MUTE_MASK 0x0100 /* SPKMIXL_MUTE */
2406#define WM8962_SPKMIXL_MUTE_SHIFT 8 /* SPKMIXL_MUTE */
2407#define WM8962_SPKMIXL_MUTE_WIDTH 1 /* SPKMIXL_MUTE */
2408#define WM8962_MIXINL_SPKMIXL_VOL 0x0080 /* MIXINL_SPKMIXL_VOL */
2409#define WM8962_MIXINL_SPKMIXL_VOL_MASK 0x0080 /* MIXINL_SPKMIXL_VOL */
2410#define WM8962_MIXINL_SPKMIXL_VOL_SHIFT 7 /* MIXINL_SPKMIXL_VOL */
2411#define WM8962_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */
2412#define WM8962_MIXINR_SPKMIXL_VOL 0x0040 /* MIXINR_SPKMIXL_VOL */
2413#define WM8962_MIXINR_SPKMIXL_VOL_MASK 0x0040 /* MIXINR_SPKMIXL_VOL */
2414#define WM8962_MIXINR_SPKMIXL_VOL_SHIFT 6 /* MIXINR_SPKMIXL_VOL */
2415#define WM8962_MIXINR_SPKMIXL_VOL_WIDTH 1 /* MIXINR_SPKMIXL_VOL */
2416#define WM8962_IN4L_SPKMIXL_VOL_MASK 0x0038 /* IN4L_SPKMIXL_VOL - [5:3] */
2417#define WM8962_IN4L_SPKMIXL_VOL_SHIFT 3 /* IN4L_SPKMIXL_VOL - [5:3] */
2418#define WM8962_IN4L_SPKMIXL_VOL_WIDTH 3 /* IN4L_SPKMIXL_VOL - [5:3] */
2419#define WM8962_IN4R_SPKMIXL_VOL_MASK 0x0007 /* IN4R_SPKMIXL_VOL - [2:0] */
2420#define WM8962_IN4R_SPKMIXL_VOL_SHIFT 0 /* IN4R_SPKMIXL_VOL - [2:0] */
2421#define WM8962_IN4R_SPKMIXL_VOL_WIDTH 3 /* IN4R_SPKMIXL_VOL - [2:0] */
2422
2423/*
2424 * R108 (0x6C) - Speaker Mixer (4)
2425 */
2426#define WM8962_SPKMIXR_MUTE 0x0100 /* SPKMIXR_MUTE */
2427#define WM8962_SPKMIXR_MUTE_MASK 0x0100 /* SPKMIXR_MUTE */
2428#define WM8962_SPKMIXR_MUTE_SHIFT 8 /* SPKMIXR_MUTE */
2429#define WM8962_SPKMIXR_MUTE_WIDTH 1 /* SPKMIXR_MUTE */
2430#define WM8962_MIXINL_SPKMIXR_VOL 0x0080 /* MIXINL_SPKMIXR_VOL */
2431#define WM8962_MIXINL_SPKMIXR_VOL_MASK 0x0080 /* MIXINL_SPKMIXR_VOL */
2432#define WM8962_MIXINL_SPKMIXR_VOL_SHIFT 7 /* MIXINL_SPKMIXR_VOL */
2433#define WM8962_MIXINL_SPKMIXR_VOL_WIDTH 1 /* MIXINL_SPKMIXR_VOL */
2434#define WM8962_MIXINR_SPKMIXR_VOL 0x0040 /* MIXINR_SPKMIXR_VOL */
2435#define WM8962_MIXINR_SPKMIXR_VOL_MASK 0x0040 /* MIXINR_SPKMIXR_VOL */
2436#define WM8962_MIXINR_SPKMIXR_VOL_SHIFT 6 /* MIXINR_SPKMIXR_VOL */
2437#define WM8962_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */
2438#define WM8962_IN4L_SPKMIXR_VOL_MASK 0x0038 /* IN4L_SPKMIXR_VOL - [5:3] */
2439#define WM8962_IN4L_SPKMIXR_VOL_SHIFT 3 /* IN4L_SPKMIXR_VOL - [5:3] */
2440#define WM8962_IN4L_SPKMIXR_VOL_WIDTH 3 /* IN4L_SPKMIXR_VOL - [5:3] */
2441#define WM8962_IN4R_SPKMIXR_VOL_MASK 0x0007 /* IN4R_SPKMIXR_VOL - [2:0] */
2442#define WM8962_IN4R_SPKMIXR_VOL_SHIFT 0 /* IN4R_SPKMIXR_VOL - [2:0] */
2443#define WM8962_IN4R_SPKMIXR_VOL_WIDTH 3 /* IN4R_SPKMIXR_VOL - [2:0] */
2444
2445/*
2446 * R109 (0x6D) - Speaker Mixer (5)
2447 */
2448#define WM8962_DACL_SPKMIXL_VOL 0x0080 /* DACL_SPKMIXL_VOL */
2449#define WM8962_DACL_SPKMIXL_VOL_MASK 0x0080 /* DACL_SPKMIXL_VOL */
2450#define WM8962_DACL_SPKMIXL_VOL_SHIFT 7 /* DACL_SPKMIXL_VOL */
2451#define WM8962_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */
2452#define WM8962_DACR_SPKMIXL_VOL 0x0040 /* DACR_SPKMIXL_VOL */
2453#define WM8962_DACR_SPKMIXL_VOL_MASK 0x0040 /* DACR_SPKMIXL_VOL */
2454#define WM8962_DACR_SPKMIXL_VOL_SHIFT 6 /* DACR_SPKMIXL_VOL */
2455#define WM8962_DACR_SPKMIXL_VOL_WIDTH 1 /* DACR_SPKMIXL_VOL */
2456#define WM8962_DACL_SPKMIXR_VOL 0x0020 /* DACL_SPKMIXR_VOL */
2457#define WM8962_DACL_SPKMIXR_VOL_MASK 0x0020 /* DACL_SPKMIXR_VOL */
2458#define WM8962_DACL_SPKMIXR_VOL_SHIFT 5 /* DACL_SPKMIXR_VOL */
2459#define WM8962_DACL_SPKMIXR_VOL_WIDTH 1 /* DACL_SPKMIXR_VOL */
2460#define WM8962_DACR_SPKMIXR_VOL 0x0010 /* DACR_SPKMIXR_VOL */
2461#define WM8962_DACR_SPKMIXR_VOL_MASK 0x0010 /* DACR_SPKMIXR_VOL */
2462#define WM8962_DACR_SPKMIXR_VOL_SHIFT 4 /* DACR_SPKMIXR_VOL */
2463#define WM8962_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */
2464
2465/*
2466 * R110 (0x6E) - Beep Generator (1)
2467 */
2468#define WM8962_BEEP_GAIN_MASK 0x00F0 /* BEEP_GAIN - [7:4] */
2469#define WM8962_BEEP_GAIN_SHIFT 4 /* BEEP_GAIN - [7:4] */
2470#define WM8962_BEEP_GAIN_WIDTH 4 /* BEEP_GAIN - [7:4] */
2471#define WM8962_BEEP_RATE_MASK 0x0006 /* BEEP_RATE - [2:1] */
2472#define WM8962_BEEP_RATE_SHIFT 1 /* BEEP_RATE - [2:1] */
2473#define WM8962_BEEP_RATE_WIDTH 2 /* BEEP_RATE - [2:1] */
2474#define WM8962_BEEP_ENA 0x0001 /* BEEP_ENA */
2475#define WM8962_BEEP_ENA_MASK 0x0001 /* BEEP_ENA */
2476#define WM8962_BEEP_ENA_SHIFT 0 /* BEEP_ENA */
2477#define WM8962_BEEP_ENA_WIDTH 1 /* BEEP_ENA */
2478
2479/*
2480 * R115 (0x73) - Oscillator Trim (3)
2481 */
2482#define WM8962_OSC_TRIM_XTI_MASK 0x001F /* OSC_TRIM_XTI - [4:0] */
2483#define WM8962_OSC_TRIM_XTI_SHIFT 0 /* OSC_TRIM_XTI - [4:0] */
2484#define WM8962_OSC_TRIM_XTI_WIDTH 5 /* OSC_TRIM_XTI - [4:0] */
2485
2486/*
2487 * R116 (0x74) - Oscillator Trim (4)
2488 */
2489#define WM8962_OSC_TRIM_XTO_MASK 0x001F /* OSC_TRIM_XTO - [4:0] */
2490#define WM8962_OSC_TRIM_XTO_SHIFT 0 /* OSC_TRIM_XTO - [4:0] */
2491#define WM8962_OSC_TRIM_XTO_WIDTH 5 /* OSC_TRIM_XTO - [4:0] */
2492
2493/*
2494 * R119 (0x77) - Oscillator Trim (7)
2495 */
2496#define WM8962_XTO_CAP_SEL_MASK 0x00F0 /* XTO_CAP_SEL - [7:4] */
2497#define WM8962_XTO_CAP_SEL_SHIFT 4 /* XTO_CAP_SEL - [7:4] */
2498#define WM8962_XTO_CAP_SEL_WIDTH 4 /* XTO_CAP_SEL - [7:4] */
2499#define WM8962_XTI_CAP_SEL_MASK 0x000F /* XTI_CAP_SEL - [3:0] */
2500#define WM8962_XTI_CAP_SEL_SHIFT 0 /* XTI_CAP_SEL - [3:0] */
2501#define WM8962_XTI_CAP_SEL_WIDTH 4 /* XTI_CAP_SEL - [3:0] */
2502
2503/*
2504 * R124 (0x7C) - Analogue Clocking1
2505 */
2506#define WM8962_CLKOUT2_SEL_MASK 0x0060 /* CLKOUT2_SEL - [6:5] */
2507#define WM8962_CLKOUT2_SEL_SHIFT 5 /* CLKOUT2_SEL - [6:5] */
2508#define WM8962_CLKOUT2_SEL_WIDTH 2 /* CLKOUT2_SEL - [6:5] */
2509#define WM8962_CLKOUT3_SEL_MASK 0x0018 /* CLKOUT3_SEL - [4:3] */
2510#define WM8962_CLKOUT3_SEL_SHIFT 3 /* CLKOUT3_SEL - [4:3] */
2511#define WM8962_CLKOUT3_SEL_WIDTH 2 /* CLKOUT3_SEL - [4:3] */
2512#define WM8962_CLKOUT5_SEL 0x0001 /* CLKOUT5_SEL */
2513#define WM8962_CLKOUT5_SEL_MASK 0x0001 /* CLKOUT5_SEL */
2514#define WM8962_CLKOUT5_SEL_SHIFT 0 /* CLKOUT5_SEL */
2515#define WM8962_CLKOUT5_SEL_WIDTH 1 /* CLKOUT5_SEL */
2516
2517/*
2518 * R125 (0x7D) - Analogue Clocking2
2519 */
2520#define WM8962_PLL2_OUTDIV 0x0080 /* PLL2_OUTDIV */
2521#define WM8962_PLL2_OUTDIV_MASK 0x0080 /* PLL2_OUTDIV */
2522#define WM8962_PLL2_OUTDIV_SHIFT 7 /* PLL2_OUTDIV */
2523#define WM8962_PLL2_OUTDIV_WIDTH 1 /* PLL2_OUTDIV */
2524#define WM8962_PLL3_OUTDIV 0x0040 /* PLL3_OUTDIV */
2525#define WM8962_PLL3_OUTDIV_MASK 0x0040 /* PLL3_OUTDIV */
2526#define WM8962_PLL3_OUTDIV_SHIFT 6 /* PLL3_OUTDIV */
2527#define WM8962_PLL3_OUTDIV_WIDTH 1 /* PLL3_OUTDIV */
2528#define WM8962_PLL_SYSCLK_DIV_MASK 0x0018 /* PLL_SYSCLK_DIV - [4:3] */
2529#define WM8962_PLL_SYSCLK_DIV_SHIFT 3 /* PLL_SYSCLK_DIV - [4:3] */
2530#define WM8962_PLL_SYSCLK_DIV_WIDTH 2 /* PLL_SYSCLK_DIV - [4:3] */
2531#define WM8962_CLKOUT3_DIV 0x0004 /* CLKOUT3_DIV */
2532#define WM8962_CLKOUT3_DIV_MASK 0x0004 /* CLKOUT3_DIV */
2533#define WM8962_CLKOUT3_DIV_SHIFT 2 /* CLKOUT3_DIV */
2534#define WM8962_CLKOUT3_DIV_WIDTH 1 /* CLKOUT3_DIV */
2535#define WM8962_CLKOUT2_DIV 0x0002 /* CLKOUT2_DIV */
2536#define WM8962_CLKOUT2_DIV_MASK 0x0002 /* CLKOUT2_DIV */
2537#define WM8962_CLKOUT2_DIV_SHIFT 1 /* CLKOUT2_DIV */
2538#define WM8962_CLKOUT2_DIV_WIDTH 1 /* CLKOUT2_DIV */
2539#define WM8962_CLKOUT5_DIV 0x0001 /* CLKOUT5_DIV */
2540#define WM8962_CLKOUT5_DIV_MASK 0x0001 /* CLKOUT5_DIV */
2541#define WM8962_CLKOUT5_DIV_SHIFT 0 /* CLKOUT5_DIV */
2542#define WM8962_CLKOUT5_DIV_WIDTH 1 /* CLKOUT5_DIV */
2543
2544/*
2545 * R126 (0x7E) - Analogue Clocking3
2546 */
2547#define WM8962_CLKOUT2_OE 0x0008 /* CLKOUT2_OE */
2548#define WM8962_CLKOUT2_OE_MASK 0x0008 /* CLKOUT2_OE */
2549#define WM8962_CLKOUT2_OE_SHIFT 3 /* CLKOUT2_OE */
2550#define WM8962_CLKOUT2_OE_WIDTH 1 /* CLKOUT2_OE */
2551#define WM8962_CLKOUT3_OE 0x0004 /* CLKOUT3_OE */
2552#define WM8962_CLKOUT3_OE_MASK 0x0004 /* CLKOUT3_OE */
2553#define WM8962_CLKOUT3_OE_SHIFT 2 /* CLKOUT3_OE */
2554#define WM8962_CLKOUT3_OE_WIDTH 1 /* CLKOUT3_OE */
2555#define WM8962_CLKOUT5_OE 0x0001 /* CLKOUT5_OE */
2556#define WM8962_CLKOUT5_OE_MASK 0x0001 /* CLKOUT5_OE */
2557#define WM8962_CLKOUT5_OE_SHIFT 0 /* CLKOUT5_OE */
2558#define WM8962_CLKOUT5_OE_WIDTH 1 /* CLKOUT5_OE */
2559
2560/*
2561 * R127 (0x7F) - PLL Software Reset
2562 */
2563#define WM8962_SW_RESET_PLL_MASK 0xFFFF /* SW_RESET_PLL - [15:0] */
2564#define WM8962_SW_RESET_PLL_SHIFT 0 /* SW_RESET_PLL - [15:0] */
2565#define WM8962_SW_RESET_PLL_WIDTH 16 /* SW_RESET_PLL - [15:0] */
2566
2567/*
2568 * R129 (0x81) - PLL2
2569 */
2570#define WM8962_OSC_ENA 0x0080 /* OSC_ENA */
2571#define WM8962_OSC_ENA_MASK 0x0080 /* OSC_ENA */
2572#define WM8962_OSC_ENA_SHIFT 7 /* OSC_ENA */
2573#define WM8962_OSC_ENA_WIDTH 1 /* OSC_ENA */
2574#define WM8962_PLL2_ENA 0x0020 /* PLL2_ENA */
2575#define WM8962_PLL2_ENA_MASK 0x0020 /* PLL2_ENA */
2576#define WM8962_PLL2_ENA_SHIFT 5 /* PLL2_ENA */
2577#define WM8962_PLL2_ENA_WIDTH 1 /* PLL2_ENA */
2578#define WM8962_PLL3_ENA 0x0010 /* PLL3_ENA */
2579#define WM8962_PLL3_ENA_MASK 0x0010 /* PLL3_ENA */
2580#define WM8962_PLL3_ENA_SHIFT 4 /* PLL3_ENA */
2581#define WM8962_PLL3_ENA_WIDTH 1 /* PLL3_ENA */
2582
2583/*
2584 * R131 (0x83) - PLL 4
2585 */
2586#define WM8962_PLL_CLK_SRC 0x0002 /* PLL_CLK_SRC */
2587#define WM8962_PLL_CLK_SRC_MASK 0x0002 /* PLL_CLK_SRC */
2588#define WM8962_PLL_CLK_SRC_SHIFT 1 /* PLL_CLK_SRC */
2589#define WM8962_PLL_CLK_SRC_WIDTH 1 /* PLL_CLK_SRC */
2590#define WM8962_FLL_TO_PLL3 0x0001 /* FLL_TO_PLL3 */
2591#define WM8962_FLL_TO_PLL3_MASK 0x0001 /* FLL_TO_PLL3 */
2592#define WM8962_FLL_TO_PLL3_SHIFT 0 /* FLL_TO_PLL3 */
2593#define WM8962_FLL_TO_PLL3_WIDTH 1 /* FLL_TO_PLL3 */
2594
2595/*
2596 * R136 (0x88) - PLL 9
2597 */
2598#define WM8962_PLL2_FRAC 0x0040 /* PLL2_FRAC */
2599#define WM8962_PLL2_FRAC_MASK 0x0040 /* PLL2_FRAC */
2600#define WM8962_PLL2_FRAC_SHIFT 6 /* PLL2_FRAC */
2601#define WM8962_PLL2_FRAC_WIDTH 1 /* PLL2_FRAC */
2602#define WM8962_PLL2_N_MASK 0x001F /* PLL2_N - [4:0] */
2603#define WM8962_PLL2_N_SHIFT 0 /* PLL2_N - [4:0] */
2604#define WM8962_PLL2_N_WIDTH 5 /* PLL2_N - [4:0] */
2605
2606/*
2607 * R137 (0x89) - PLL 10
2608 */
2609#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */
2610#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */
2611#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */
2612
2613/*
2614 * R138 (0x8A) - PLL 11
2615 */
2616#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */
2617#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */
2618#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */
2619
2620/*
2621 * R139 (0x8B) - PLL 12
2622 */
2623#define WM8962_PLL2_K_MASK 0x00FF /* PLL2_K - [7:0] */
2624#define WM8962_PLL2_K_SHIFT 0 /* PLL2_K - [7:0] */
2625#define WM8962_PLL2_K_WIDTH 8 /* PLL2_K - [7:0] */
2626
2627/*
2628 * R140 (0x8C) - PLL 13
2629 */
2630#define WM8962_PLL3_FRAC 0x0040 /* PLL3_FRAC */
2631#define WM8962_PLL3_FRAC_MASK 0x0040 /* PLL3_FRAC */
2632#define WM8962_PLL3_FRAC_SHIFT 6 /* PLL3_FRAC */
2633#define WM8962_PLL3_FRAC_WIDTH 1 /* PLL3_FRAC */
2634#define WM8962_PLL3_N_MASK 0x001F /* PLL3_N - [4:0] */
2635#define WM8962_PLL3_N_SHIFT 0 /* PLL3_N - [4:0] */
2636#define WM8962_PLL3_N_WIDTH 5 /* PLL3_N - [4:0] */
2637
2638/*
2639 * R141 (0x8D) - PLL 14
2640 */
2641#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */
2642#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */
2643#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */
2644
2645/*
2646 * R142 (0x8E) - PLL 15
2647 */
2648#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */
2649#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */
2650#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */
2651
2652/*
2653 * R143 (0x8F) - PLL 16
2654 */
2655#define WM8962_PLL3_K_MASK 0x00FF /* PLL3_K - [7:0] */
2656#define WM8962_PLL3_K_SHIFT 0 /* PLL3_K - [7:0] */
2657#define WM8962_PLL3_K_WIDTH 8 /* PLL3_K - [7:0] */
2658
2659/*
2660 * R155 (0x9B) - FLL Control (1)
2661 */
2662#define WM8962_FLL_REFCLK_SRC_MASK 0x0060 /* FLL_REFCLK_SRC - [6:5] */
2663#define WM8962_FLL_REFCLK_SRC_SHIFT 5 /* FLL_REFCLK_SRC - [6:5] */
2664#define WM8962_FLL_REFCLK_SRC_WIDTH 2 /* FLL_REFCLK_SRC - [6:5] */
2665#define WM8962_FLL_FRAC 0x0004 /* FLL_FRAC */
2666#define WM8962_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */
2667#define WM8962_FLL_FRAC_SHIFT 2 /* FLL_FRAC */
2668#define WM8962_FLL_FRAC_WIDTH 1 /* FLL_FRAC */
2669#define WM8962_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */
2670#define WM8962_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */
2671#define WM8962_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */
2672#define WM8962_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */
2673#define WM8962_FLL_ENA 0x0001 /* FLL_ENA */
2674#define WM8962_FLL_ENA_MASK 0x0001 /* FLL_ENA */
2675#define WM8962_FLL_ENA_SHIFT 0 /* FLL_ENA */
2676#define WM8962_FLL_ENA_WIDTH 1 /* FLL_ENA */
2677
2678/*
2679 * R156 (0x9C) - FLL Control (2)
2680 */
2681#define WM8962_FLL_OUTDIV_MASK 0x01F8 /* FLL_OUTDIV - [8:3] */
2682#define WM8962_FLL_OUTDIV_SHIFT 3 /* FLL_OUTDIV - [8:3] */
2683#define WM8962_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [8:3] */
2684#define WM8962_FLL_REFCLK_DIV_MASK 0x0003 /* FLL_REFCLK_DIV - [1:0] */
2685#define WM8962_FLL_REFCLK_DIV_SHIFT 0 /* FLL_REFCLK_DIV - [1:0] */
2686#define WM8962_FLL_REFCLK_DIV_WIDTH 2 /* FLL_REFCLK_DIV - [1:0] */
2687
2688/*
2689 * R157 (0x9D) - FLL Control (3)
2690 */
2691#define WM8962_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
2692#define WM8962_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
2693#define WM8962_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
2694
2695/*
2696 * R159 (0x9F) - FLL Control (5)
2697 */
2698#define WM8962_FLL_FRC_NCO_VAL_MASK 0x007E /* FLL_FRC_NCO_VAL - [6:1] */
2699#define WM8962_FLL_FRC_NCO_VAL_SHIFT 1 /* FLL_FRC_NCO_VAL - [6:1] */
2700#define WM8962_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [6:1] */
2701#define WM8962_FLL_FRC_NCO 0x0001 /* FLL_FRC_NCO */
2702#define WM8962_FLL_FRC_NCO_MASK 0x0001 /* FLL_FRC_NCO */
2703#define WM8962_FLL_FRC_NCO_SHIFT 0 /* FLL_FRC_NCO */
2704#define WM8962_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */
2705
2706/*
2707 * R160 (0xA0) - FLL Control (6)
2708 */
2709#define WM8962_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */
2710#define WM8962_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */
2711#define WM8962_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */
2712
2713/*
2714 * R161 (0xA1) - FLL Control (7)
2715 */
2716#define WM8962_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */
2717#define WM8962_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */
2718#define WM8962_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */
2719
2720/*
2721 * R162 (0xA2) - FLL Control (8)
2722 */
2723#define WM8962_FLL_N_MASK 0x03FF /* FLL_N - [9:0] */
2724#define WM8962_FLL_N_SHIFT 0 /* FLL_N - [9:0] */
2725#define WM8962_FLL_N_WIDTH 10 /* FLL_N - [9:0] */
2726
2727/*
2728 * R252 (0xFC) - General test 1
2729 */
2730#define WM8962_REG_SYNC 0x0004 /* REG_SYNC */
2731#define WM8962_REG_SYNC_MASK 0x0004 /* REG_SYNC */
2732#define WM8962_REG_SYNC_SHIFT 2 /* REG_SYNC */
2733#define WM8962_REG_SYNC_WIDTH 1 /* REG_SYNC */
2734#define WM8962_AUTO_INC 0x0001 /* AUTO_INC */
2735#define WM8962_AUTO_INC_MASK 0x0001 /* AUTO_INC */
2736#define WM8962_AUTO_INC_SHIFT 0 /* AUTO_INC */
2737#define WM8962_AUTO_INC_WIDTH 1 /* AUTO_INC */
2738
2739/*
2740 * R256 (0x100) - DF1
2741 */
2742#define WM8962_DRC_DF1_ENA 0x0008 /* DRC_DF1_ENA */
2743#define WM8962_DRC_DF1_ENA_MASK 0x0008 /* DRC_DF1_ENA */
2744#define WM8962_DRC_DF1_ENA_SHIFT 3 /* DRC_DF1_ENA */
2745#define WM8962_DRC_DF1_ENA_WIDTH 1 /* DRC_DF1_ENA */
2746#define WM8962_DF1_SHARED_COEFF 0x0004 /* DF1_SHARED_COEFF */
2747#define WM8962_DF1_SHARED_COEFF_MASK 0x0004 /* DF1_SHARED_COEFF */
2748#define WM8962_DF1_SHARED_COEFF_SHIFT 2 /* DF1_SHARED_COEFF */
2749#define WM8962_DF1_SHARED_COEFF_WIDTH 1 /* DF1_SHARED_COEFF */
2750#define WM8962_DF1_SHARED_COEFF_SEL 0x0002 /* DF1_SHARED_COEFF_SEL */
2751#define WM8962_DF1_SHARED_COEFF_SEL_MASK 0x0002 /* DF1_SHARED_COEFF_SEL */
2752#define WM8962_DF1_SHARED_COEFF_SEL_SHIFT 1 /* DF1_SHARED_COEFF_SEL */
2753#define WM8962_DF1_SHARED_COEFF_SEL_WIDTH 1 /* DF1_SHARED_COEFF_SEL */
2754#define WM8962_DF1_ENA 0x0001 /* DF1_ENA */
2755#define WM8962_DF1_ENA_MASK 0x0001 /* DF1_ENA */
2756#define WM8962_DF1_ENA_SHIFT 0 /* DF1_ENA */
2757#define WM8962_DF1_ENA_WIDTH 1 /* DF1_ENA */
2758
2759/*
2760 * R257 (0x101) - DF2
2761 */
2762#define WM8962_DF1_COEFF_L0_MASK 0xFFFF /* DF1_COEFF_L0 - [15:0] */
2763#define WM8962_DF1_COEFF_L0_SHIFT 0 /* DF1_COEFF_L0 - [15:0] */
2764#define WM8962_DF1_COEFF_L0_WIDTH 16 /* DF1_COEFF_L0 - [15:0] */
2765
2766/*
2767 * R258 (0x102) - DF3
2768 */
2769#define WM8962_DF1_COEFF_L1_MASK 0xFFFF /* DF1_COEFF_L1 - [15:0] */
2770#define WM8962_DF1_COEFF_L1_SHIFT 0 /* DF1_COEFF_L1 - [15:0] */
2771#define WM8962_DF1_COEFF_L1_WIDTH 16 /* DF1_COEFF_L1 - [15:0] */
2772
2773/*
2774 * R259 (0x103) - DF4
2775 */
2776#define WM8962_DF1_COEFF_L2_MASK 0xFFFF /* DF1_COEFF_L2 - [15:0] */
2777#define WM8962_DF1_COEFF_L2_SHIFT 0 /* DF1_COEFF_L2 - [15:0] */
2778#define WM8962_DF1_COEFF_L2_WIDTH 16 /* DF1_COEFF_L2 - [15:0] */
2779
2780/*
2781 * R260 (0x104) - DF5
2782 */
2783#define WM8962_DF1_COEFF_R0_MASK 0xFFFF /* DF1_COEFF_R0 - [15:0] */
2784#define WM8962_DF1_COEFF_R0_SHIFT 0 /* DF1_COEFF_R0 - [15:0] */
2785#define WM8962_DF1_COEFF_R0_WIDTH 16 /* DF1_COEFF_R0 - [15:0] */
2786
2787/*
2788 * R261 (0x105) - DF6
2789 */
2790#define WM8962_DF1_COEFF_R1_MASK 0xFFFF /* DF1_COEFF_R1 - [15:0] */
2791#define WM8962_DF1_COEFF_R1_SHIFT 0 /* DF1_COEFF_R1 - [15:0] */
2792#define WM8962_DF1_COEFF_R1_WIDTH 16 /* DF1_COEFF_R1 - [15:0] */
2793
2794/*
2795 * R262 (0x106) - DF7
2796 */
2797#define WM8962_DF1_COEFF_R2_MASK 0xFFFF /* DF1_COEFF_R2 - [15:0] */
2798#define WM8962_DF1_COEFF_R2_SHIFT 0 /* DF1_COEFF_R2 - [15:0] */
2799#define WM8962_DF1_COEFF_R2_WIDTH 16 /* DF1_COEFF_R2 - [15:0] */
2800
2801/*
2802 * R264 (0x108) - LHPF1
2803 */
2804#define WM8962_LHPF_MODE 0x0002 /* LHPF_MODE */
2805#define WM8962_LHPF_MODE_MASK 0x0002 /* LHPF_MODE */
2806#define WM8962_LHPF_MODE_SHIFT 1 /* LHPF_MODE */
2807#define WM8962_LHPF_MODE_WIDTH 1 /* LHPF_MODE */
2808#define WM8962_LHPF_ENA 0x0001 /* LHPF_ENA */
2809#define WM8962_LHPF_ENA_MASK 0x0001 /* LHPF_ENA */
2810#define WM8962_LHPF_ENA_SHIFT 0 /* LHPF_ENA */
2811#define WM8962_LHPF_ENA_WIDTH 1 /* LHPF_ENA */
2812
2813/*
2814 * R265 (0x109) - LHPF2
2815 */
2816#define WM8962_LHPF_COEFF_MASK 0xFFFF /* LHPF_COEFF - [15:0] */
2817#define WM8962_LHPF_COEFF_SHIFT 0 /* LHPF_COEFF - [15:0] */
2818#define WM8962_LHPF_COEFF_WIDTH 16 /* LHPF_COEFF - [15:0] */
2819
2820/*
2821 * R268 (0x10C) - THREED1
2822 */
2823#define WM8962_ADC_MONOMIX 0x0040 /* ADC_MONOMIX */
2824#define WM8962_ADC_MONOMIX_MASK 0x0040 /* ADC_MONOMIX */
2825#define WM8962_ADC_MONOMIX_SHIFT 6 /* ADC_MONOMIX */
2826#define WM8962_ADC_MONOMIX_WIDTH 1 /* ADC_MONOMIX */
2827#define WM8962_THREED_SIGN_L 0x0020 /* THREED_SIGN_L */
2828#define WM8962_THREED_SIGN_L_MASK 0x0020 /* THREED_SIGN_L */
2829#define WM8962_THREED_SIGN_L_SHIFT 5 /* THREED_SIGN_L */
2830#define WM8962_THREED_SIGN_L_WIDTH 1 /* THREED_SIGN_L */
2831#define WM8962_THREED_SIGN_R 0x0010 /* THREED_SIGN_R */
2832#define WM8962_THREED_SIGN_R_MASK 0x0010 /* THREED_SIGN_R */
2833#define WM8962_THREED_SIGN_R_SHIFT 4 /* THREED_SIGN_R */
2834#define WM8962_THREED_SIGN_R_WIDTH 1 /* THREED_SIGN_R */
2835#define WM8962_THREED_LHPF_MODE 0x0004 /* THREED_LHPF_MODE */
2836#define WM8962_THREED_LHPF_MODE_MASK 0x0004 /* THREED_LHPF_MODE */
2837#define WM8962_THREED_LHPF_MODE_SHIFT 2 /* THREED_LHPF_MODE */
2838#define WM8962_THREED_LHPF_MODE_WIDTH 1 /* THREED_LHPF_MODE */
2839#define WM8962_THREED_LHPF_ENA 0x0002 /* THREED_LHPF_ENA */
2840#define WM8962_THREED_LHPF_ENA_MASK 0x0002 /* THREED_LHPF_ENA */
2841#define WM8962_THREED_LHPF_ENA_SHIFT 1 /* THREED_LHPF_ENA */
2842#define WM8962_THREED_LHPF_ENA_WIDTH 1 /* THREED_LHPF_ENA */
2843#define WM8962_THREED_ENA 0x0001 /* THREED_ENA */
2844#define WM8962_THREED_ENA_MASK 0x0001 /* THREED_ENA */
2845#define WM8962_THREED_ENA_SHIFT 0 /* THREED_ENA */
2846#define WM8962_THREED_ENA_WIDTH 1 /* THREED_ENA */
2847
2848/*
2849 * R269 (0x10D) - THREED2
2850 */
2851#define WM8962_THREED_FGAINL_MASK 0xF800 /* THREED_FGAINL - [15:11] */
2852#define WM8962_THREED_FGAINL_SHIFT 11 /* THREED_FGAINL - [15:11] */
2853#define WM8962_THREED_FGAINL_WIDTH 5 /* THREED_FGAINL - [15:11] */
2854#define WM8962_THREED_CGAINL_MASK 0x07C0 /* THREED_CGAINL - [10:6] */
2855#define WM8962_THREED_CGAINL_SHIFT 6 /* THREED_CGAINL - [10:6] */
2856#define WM8962_THREED_CGAINL_WIDTH 5 /* THREED_CGAINL - [10:6] */
2857#define WM8962_THREED_DELAYL_MASK 0x003C /* THREED_DELAYL - [5:2] */
2858#define WM8962_THREED_DELAYL_SHIFT 2 /* THREED_DELAYL - [5:2] */
2859#define WM8962_THREED_DELAYL_WIDTH 4 /* THREED_DELAYL - [5:2] */
2860
2861/*
2862 * R270 (0x10E) - THREED3
2863 */
2864#define WM8962_THREED_LHPF_COEFF_MASK 0xFFFF /* THREED_LHPF_COEFF - [15:0] */
2865#define WM8962_THREED_LHPF_COEFF_SHIFT 0 /* THREED_LHPF_COEFF - [15:0] */
2866#define WM8962_THREED_LHPF_COEFF_WIDTH 16 /* THREED_LHPF_COEFF - [15:0] */
2867
2868/*
2869 * R271 (0x10F) - THREED4
2870 */
2871#define WM8962_THREED_FGAINR_MASK 0xF800 /* THREED_FGAINR - [15:11] */
2872#define WM8962_THREED_FGAINR_SHIFT 11 /* THREED_FGAINR - [15:11] */
2873#define WM8962_THREED_FGAINR_WIDTH 5 /* THREED_FGAINR - [15:11] */
2874#define WM8962_THREED_CGAINR_MASK 0x07C0 /* THREED_CGAINR - [10:6] */
2875#define WM8962_THREED_CGAINR_SHIFT 6 /* THREED_CGAINR - [10:6] */
2876#define WM8962_THREED_CGAINR_WIDTH 5 /* THREED_CGAINR - [10:6] */
2877#define WM8962_THREED_DELAYR_MASK 0x003C /* THREED_DELAYR - [5:2] */
2878#define WM8962_THREED_DELAYR_SHIFT 2 /* THREED_DELAYR - [5:2] */
2879#define WM8962_THREED_DELAYR_WIDTH 4 /* THREED_DELAYR - [5:2] */
2880
2881/*
2882 * R276 (0x114) - DRC 1
2883 */
2884#define WM8962_DRC_SIG_DET_RMS_MASK 0x7C00 /* DRC_SIG_DET_RMS - [14:10] */
2885#define WM8962_DRC_SIG_DET_RMS_SHIFT 10 /* DRC_SIG_DET_RMS - [14:10] */
2886#define WM8962_DRC_SIG_DET_RMS_WIDTH 5 /* DRC_SIG_DET_RMS - [14:10] */
2887#define WM8962_DRC_SIG_DET_PK_MASK 0x0300 /* DRC_SIG_DET_PK - [9:8] */
2888#define WM8962_DRC_SIG_DET_PK_SHIFT 8 /* DRC_SIG_DET_PK - [9:8] */
2889#define WM8962_DRC_SIG_DET_PK_WIDTH 2 /* DRC_SIG_DET_PK - [9:8] */
2890#define WM8962_DRC_NG_ENA 0x0080 /* DRC_NG_ENA */
2891#define WM8962_DRC_NG_ENA_MASK 0x0080 /* DRC_NG_ENA */
2892#define WM8962_DRC_NG_ENA_SHIFT 7 /* DRC_NG_ENA */
2893#define WM8962_DRC_NG_ENA_WIDTH 1 /* DRC_NG_ENA */
2894#define WM8962_DRC_SIG_DET_MODE 0x0040 /* DRC_SIG_DET_MODE */
2895#define WM8962_DRC_SIG_DET_MODE_MASK 0x0040 /* DRC_SIG_DET_MODE */
2896#define WM8962_DRC_SIG_DET_MODE_SHIFT 6 /* DRC_SIG_DET_MODE */
2897#define WM8962_DRC_SIG_DET_MODE_WIDTH 1 /* DRC_SIG_DET_MODE */
2898#define WM8962_DRC_SIG_DET 0x0020 /* DRC_SIG_DET */
2899#define WM8962_DRC_SIG_DET_MASK 0x0020 /* DRC_SIG_DET */
2900#define WM8962_DRC_SIG_DET_SHIFT 5 /* DRC_SIG_DET */
2901#define WM8962_DRC_SIG_DET_WIDTH 1 /* DRC_SIG_DET */
2902#define WM8962_DRC_KNEE2_OP_ENA 0x0010 /* DRC_KNEE2_OP_ENA */
2903#define WM8962_DRC_KNEE2_OP_ENA_MASK 0x0010 /* DRC_KNEE2_OP_ENA */
2904#define WM8962_DRC_KNEE2_OP_ENA_SHIFT 4 /* DRC_KNEE2_OP_ENA */
2905#define WM8962_DRC_KNEE2_OP_ENA_WIDTH 1 /* DRC_KNEE2_OP_ENA */
2906#define WM8962_DRC_QR 0x0008 /* DRC_QR */
2907#define WM8962_DRC_QR_MASK 0x0008 /* DRC_QR */
2908#define WM8962_DRC_QR_SHIFT 3 /* DRC_QR */
2909#define WM8962_DRC_QR_WIDTH 1 /* DRC_QR */
2910#define WM8962_DRC_ANTICLIP 0x0004 /* DRC_ANTICLIP */
2911#define WM8962_DRC_ANTICLIP_MASK 0x0004 /* DRC_ANTICLIP */
2912#define WM8962_DRC_ANTICLIP_SHIFT 2 /* DRC_ANTICLIP */
2913#define WM8962_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */
2914#define WM8962_DRC_MODE 0x0002 /* DRC_MODE */
2915#define WM8962_DRC_MODE_MASK 0x0002 /* DRC_MODE */
2916#define WM8962_DRC_MODE_SHIFT 1 /* DRC_MODE */
2917#define WM8962_DRC_MODE_WIDTH 1 /* DRC_MODE */
2918#define WM8962_DRC_ENA 0x0001 /* DRC_ENA */
2919#define WM8962_DRC_ENA_MASK 0x0001 /* DRC_ENA */
2920#define WM8962_DRC_ENA_SHIFT 0 /* DRC_ENA */
2921#define WM8962_DRC_ENA_WIDTH 1 /* DRC_ENA */
2922
2923/*
2924 * R277 (0x115) - DRC 2
2925 */
2926#define WM8962_DRC_ATK_MASK 0x1E00 /* DRC_ATK - [12:9] */
2927#define WM8962_DRC_ATK_SHIFT 9 /* DRC_ATK - [12:9] */
2928#define WM8962_DRC_ATK_WIDTH 4 /* DRC_ATK - [12:9] */
2929#define WM8962_DRC_DCY_MASK 0x01E0 /* DRC_DCY - [8:5] */
2930#define WM8962_DRC_DCY_SHIFT 5 /* DRC_DCY - [8:5] */
2931#define WM8962_DRC_DCY_WIDTH 4 /* DRC_DCY - [8:5] */
2932#define WM8962_DRC_MINGAIN_MASK 0x001C /* DRC_MINGAIN - [4:2] */
2933#define WM8962_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [4:2] */
2934#define WM8962_DRC_MINGAIN_WIDTH 3 /* DRC_MINGAIN - [4:2] */
2935#define WM8962_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
2936#define WM8962_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
2937#define WM8962_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
2938
2939/*
2940 * R278 (0x116) - DRC 3
2941 */
2942#define WM8962_DRC_NG_MINGAIN_MASK 0xF000 /* DRC_NG_MINGAIN - [15:12] */
2943#define WM8962_DRC_NG_MINGAIN_SHIFT 12 /* DRC_NG_MINGAIN - [15:12] */
2944#define WM8962_DRC_NG_MINGAIN_WIDTH 4 /* DRC_NG_MINGAIN - [15:12] */
2945#define WM8962_DRC_QR_THR_MASK 0x0C00 /* DRC_QR_THR - [11:10] */
2946#define WM8962_DRC_QR_THR_SHIFT 10 /* DRC_QR_THR - [11:10] */
2947#define WM8962_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [11:10] */
2948#define WM8962_DRC_QR_DCY_MASK 0x0300 /* DRC_QR_DCY - [9:8] */
2949#define WM8962_DRC_QR_DCY_SHIFT 8 /* DRC_QR_DCY - [9:8] */
2950#define WM8962_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [9:8] */
2951#define WM8962_DRC_NG_EXP_MASK 0x00C0 /* DRC_NG_EXP - [7:6] */
2952#define WM8962_DRC_NG_EXP_SHIFT 6 /* DRC_NG_EXP - [7:6] */
2953#define WM8962_DRC_NG_EXP_WIDTH 2 /* DRC_NG_EXP - [7:6] */
2954#define WM8962_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */
2955#define WM8962_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */
2956#define WM8962_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */
2957#define WM8962_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */
2958#define WM8962_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */
2959#define WM8962_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */
2960
2961/*
2962 * R279 (0x117) - DRC 4
2963 */
2964#define WM8962_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */
2965#define WM8962_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */
2966#define WM8962_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */
2967#define WM8962_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */
2968#define WM8962_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */
2969#define WM8962_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */
2970
2971/*
2972 * R280 (0x118) - DRC 5
2973 */
2974#define WM8962_DRC_KNEE2_IP_MASK 0x03E0 /* DRC_KNEE2_IP - [9:5] */
2975#define WM8962_DRC_KNEE2_IP_SHIFT 5 /* DRC_KNEE2_IP - [9:5] */
2976#define WM8962_DRC_KNEE2_IP_WIDTH 5 /* DRC_KNEE2_IP - [9:5] */
2977#define WM8962_DRC_KNEE2_OP_MASK 0x001F /* DRC_KNEE2_OP - [4:0] */
2978#define WM8962_DRC_KNEE2_OP_SHIFT 0 /* DRC_KNEE2_OP - [4:0] */
2979#define WM8962_DRC_KNEE2_OP_WIDTH 5 /* DRC_KNEE2_OP - [4:0] */
2980
2981/*
2982 * R285 (0x11D) - Tloopback
2983 */
2984#define WM8962_TLB_ENA 0x0002 /* TLB_ENA */
2985#define WM8962_TLB_ENA_MASK 0x0002 /* TLB_ENA */
2986#define WM8962_TLB_ENA_SHIFT 1 /* TLB_ENA */
2987#define WM8962_TLB_ENA_WIDTH 1 /* TLB_ENA */
2988#define WM8962_TLB_MODE 0x0001 /* TLB_MODE */
2989#define WM8962_TLB_MODE_MASK 0x0001 /* TLB_MODE */
2990#define WM8962_TLB_MODE_SHIFT 0 /* TLB_MODE */
2991#define WM8962_TLB_MODE_WIDTH 1 /* TLB_MODE */
2992
2993/*
2994 * R335 (0x14F) - EQ1
2995 */
2996#define WM8962_EQ_SHARED_COEFF 0x0004 /* EQ_SHARED_COEFF */
2997#define WM8962_EQ_SHARED_COEFF_MASK 0x0004 /* EQ_SHARED_COEFF */
2998#define WM8962_EQ_SHARED_COEFF_SHIFT 2 /* EQ_SHARED_COEFF */
2999#define WM8962_EQ_SHARED_COEFF_WIDTH 1 /* EQ_SHARED_COEFF */
3000#define WM8962_EQ_SHARED_COEFF_SEL 0x0002 /* EQ_SHARED_COEFF_SEL */
3001#define WM8962_EQ_SHARED_COEFF_SEL_MASK 0x0002 /* EQ_SHARED_COEFF_SEL */
3002#define WM8962_EQ_SHARED_COEFF_SEL_SHIFT 1 /* EQ_SHARED_COEFF_SEL */
3003#define WM8962_EQ_SHARED_COEFF_SEL_WIDTH 1 /* EQ_SHARED_COEFF_SEL */
3004#define WM8962_EQ_ENA 0x0001 /* EQ_ENA */
3005#define WM8962_EQ_ENA_MASK 0x0001 /* EQ_ENA */
3006#define WM8962_EQ_ENA_SHIFT 0 /* EQ_ENA */
3007#define WM8962_EQ_ENA_WIDTH 1 /* EQ_ENA */
3008
3009/*
3010 * R336 (0x150) - EQ2
3011 */
3012#define WM8962_EQL_B1_GAIN_MASK 0xF800 /* EQL_B1_GAIN - [15:11] */
3013#define WM8962_EQL_B1_GAIN_SHIFT 11 /* EQL_B1_GAIN - [15:11] */
3014#define WM8962_EQL_B1_GAIN_WIDTH 5 /* EQL_B1_GAIN - [15:11] */
3015#define WM8962_EQL_B2_GAIN_MASK 0x07C0 /* EQL_B2_GAIN - [10:6] */
3016#define WM8962_EQL_B2_GAIN_SHIFT 6 /* EQL_B2_GAIN - [10:6] */
3017#define WM8962_EQL_B2_GAIN_WIDTH 5 /* EQL_B2_GAIN - [10:6] */
3018#define WM8962_EQL_B3_GAIN_MASK 0x003E /* EQL_B3_GAIN - [5:1] */
3019#define WM8962_EQL_B3_GAIN_SHIFT 1 /* EQL_B3_GAIN - [5:1] */
3020#define WM8962_EQL_B3_GAIN_WIDTH 5 /* EQL_B3_GAIN - [5:1] */
3021
3022/*
3023 * R337 (0x151) - EQ3
3024 */
3025#define WM8962_EQL_B4_GAIN_MASK 0xF800 /* EQL_B4_GAIN - [15:11] */
3026#define WM8962_EQL_B4_GAIN_SHIFT 11 /* EQL_B4_GAIN - [15:11] */
3027#define WM8962_EQL_B4_GAIN_WIDTH 5 /* EQL_B4_GAIN - [15:11] */
3028#define WM8962_EQL_B5_GAIN_MASK 0x07C0 /* EQL_B5_GAIN - [10:6] */
3029#define WM8962_EQL_B5_GAIN_SHIFT 6 /* EQL_B5_GAIN - [10:6] */
3030#define WM8962_EQL_B5_GAIN_WIDTH 5 /* EQL_B5_GAIN - [10:6] */
3031
3032/*
3033 * R338 (0x152) - EQ4
3034 */
3035#define WM8962_EQL_B1_A_MASK 0xFFFF /* EQL_B1_A - [15:0] */
3036#define WM8962_EQL_B1_A_SHIFT 0 /* EQL_B1_A - [15:0] */
3037#define WM8962_EQL_B1_A_WIDTH 16 /* EQL_B1_A - [15:0] */
3038
3039/*
3040 * R339 (0x153) - EQ5
3041 */
3042#define WM8962_EQL_B1_B_MASK 0xFFFF /* EQL_B1_B - [15:0] */
3043#define WM8962_EQL_B1_B_SHIFT 0 /* EQL_B1_B - [15:0] */
3044#define WM8962_EQL_B1_B_WIDTH 16 /* EQL_B1_B - [15:0] */
3045
3046/*
3047 * R340 (0x154) - EQ6
3048 */
3049#define WM8962_EQL_B1_PG_MASK 0xFFFF /* EQL_B1_PG - [15:0] */
3050#define WM8962_EQL_B1_PG_SHIFT 0 /* EQL_B1_PG - [15:0] */
3051#define WM8962_EQL_B1_PG_WIDTH 16 /* EQL_B1_PG - [15:0] */
3052
3053/*
3054 * R341 (0x155) - EQ7
3055 */
3056#define WM8962_EQL_B2_A_MASK 0xFFFF /* EQL_B2_A - [15:0] */
3057#define WM8962_EQL_B2_A_SHIFT 0 /* EQL_B2_A - [15:0] */
3058#define WM8962_EQL_B2_A_WIDTH 16 /* EQL_B2_A - [15:0] */
3059
3060/*
3061 * R342 (0x156) - EQ8
3062 */
3063#define WM8962_EQL_B2_B_MASK 0xFFFF /* EQL_B2_B - [15:0] */
3064#define WM8962_EQL_B2_B_SHIFT 0 /* EQL_B2_B - [15:0] */
3065#define WM8962_EQL_B2_B_WIDTH 16 /* EQL_B2_B - [15:0] */
3066
3067/*
3068 * R343 (0x157) - EQ9
3069 */
3070#define WM8962_EQL_B2_C_MASK 0xFFFF /* EQL_B2_C - [15:0] */
3071#define WM8962_EQL_B2_C_SHIFT 0 /* EQL_B2_C - [15:0] */
3072#define WM8962_EQL_B2_C_WIDTH 16 /* EQL_B2_C - [15:0] */
3073
3074/*
3075 * R344 (0x158) - EQ10
3076 */
3077#define WM8962_EQL_B2_PG_MASK 0xFFFF /* EQL_B2_PG - [15:0] */
3078#define WM8962_EQL_B2_PG_SHIFT 0 /* EQL_B2_PG - [15:0] */
3079#define WM8962_EQL_B2_PG_WIDTH 16 /* EQL_B2_PG - [15:0] */
3080
3081/*
3082 * R345 (0x159) - EQ11
3083 */
3084#define WM8962_EQL_B3_A_MASK 0xFFFF /* EQL_B3_A - [15:0] */
3085#define WM8962_EQL_B3_A_SHIFT 0 /* EQL_B3_A - [15:0] */
3086#define WM8962_EQL_B3_A_WIDTH 16 /* EQL_B3_A - [15:0] */
3087
3088/*
3089 * R346 (0x15A) - EQ12
3090 */
3091#define WM8962_EQL_B3_B_MASK 0xFFFF /* EQL_B3_B - [15:0] */
3092#define WM8962_EQL_B3_B_SHIFT 0 /* EQL_B3_B - [15:0] */
3093#define WM8962_EQL_B3_B_WIDTH 16 /* EQL_B3_B - [15:0] */
3094
3095/*
3096 * R347 (0x15B) - EQ13
3097 */
3098#define WM8962_EQL_B3_C_MASK 0xFFFF /* EQL_B3_C - [15:0] */
3099#define WM8962_EQL_B3_C_SHIFT 0 /* EQL_B3_C - [15:0] */
3100#define WM8962_EQL_B3_C_WIDTH 16 /* EQL_B3_C - [15:0] */
3101
3102/*
3103 * R348 (0x15C) - EQ14
3104 */
3105#define WM8962_EQL_B3_PG_MASK 0xFFFF /* EQL_B3_PG - [15:0] */
3106#define WM8962_EQL_B3_PG_SHIFT 0 /* EQL_B3_PG - [15:0] */
3107#define WM8962_EQL_B3_PG_WIDTH 16 /* EQL_B3_PG - [15:0] */
3108
3109/*
3110 * R349 (0x15D) - EQ15
3111 */
3112#define WM8962_EQL_B4_A_MASK 0xFFFF /* EQL_B4_A - [15:0] */
3113#define WM8962_EQL_B4_A_SHIFT 0 /* EQL_B4_A - [15:0] */
3114#define WM8962_EQL_B4_A_WIDTH 16 /* EQL_B4_A - [15:0] */
3115
3116/*
3117 * R350 (0x15E) - EQ16
3118 */
3119#define WM8962_EQL_B4_B_MASK 0xFFFF /* EQL_B4_B - [15:0] */
3120#define WM8962_EQL_B4_B_SHIFT 0 /* EQL_B4_B - [15:0] */
3121#define WM8962_EQL_B4_B_WIDTH 16 /* EQL_B4_B - [15:0] */
3122
3123/*
3124 * R351 (0x15F) - EQ17
3125 */
3126#define WM8962_EQL_B4_C_MASK 0xFFFF /* EQL_B4_C - [15:0] */
3127#define WM8962_EQL_B4_C_SHIFT 0 /* EQL_B4_C - [15:0] */
3128#define WM8962_EQL_B4_C_WIDTH 16 /* EQL_B4_C - [15:0] */
3129
3130/*
3131 * R352 (0x160) - EQ18
3132 */
3133#define WM8962_EQL_B4_PG_MASK 0xFFFF /* EQL_B4_PG - [15:0] */
3134#define WM8962_EQL_B4_PG_SHIFT 0 /* EQL_B4_PG - [15:0] */
3135#define WM8962_EQL_B4_PG_WIDTH 16 /* EQL_B4_PG - [15:0] */
3136
3137/*
3138 * R353 (0x161) - EQ19
3139 */
3140#define WM8962_EQL_B5_A_MASK 0xFFFF /* EQL_B5_A - [15:0] */
3141#define WM8962_EQL_B5_A_SHIFT 0 /* EQL_B5_A - [15:0] */
3142#define WM8962_EQL_B5_A_WIDTH 16 /* EQL_B5_A - [15:0] */
3143
3144/*
3145 * R354 (0x162) - EQ20
3146 */
3147#define WM8962_EQL_B5_B_MASK 0xFFFF /* EQL_B5_B - [15:0] */
3148#define WM8962_EQL_B5_B_SHIFT 0 /* EQL_B5_B - [15:0] */
3149#define WM8962_EQL_B5_B_WIDTH 16 /* EQL_B5_B - [15:0] */
3150
3151/*
3152 * R355 (0x163) - EQ21
3153 */
3154#define WM8962_EQL_B5_PG_MASK 0xFFFF /* EQL_B5_PG - [15:0] */
3155#define WM8962_EQL_B5_PG_SHIFT 0 /* EQL_B5_PG - [15:0] */
3156#define WM8962_EQL_B5_PG_WIDTH 16 /* EQL_B5_PG - [15:0] */
3157
3158/*
3159 * R356 (0x164) - EQ22
3160 */
3161#define WM8962_EQR_B1_GAIN_MASK 0xF800 /* EQR_B1_GAIN - [15:11] */
3162#define WM8962_EQR_B1_GAIN_SHIFT 11 /* EQR_B1_GAIN - [15:11] */
3163#define WM8962_EQR_B1_GAIN_WIDTH 5 /* EQR_B1_GAIN - [15:11] */
3164#define WM8962_EQR_B2_GAIN_MASK 0x07C0 /* EQR_B2_GAIN - [10:6] */
3165#define WM8962_EQR_B2_GAIN_SHIFT 6 /* EQR_B2_GAIN - [10:6] */
3166#define WM8962_EQR_B2_GAIN_WIDTH 5 /* EQR_B2_GAIN - [10:6] */
3167#define WM8962_EQR_B3_GAIN_MASK 0x003E /* EQR_B3_GAIN - [5:1] */
3168#define WM8962_EQR_B3_GAIN_SHIFT 1 /* EQR_B3_GAIN - [5:1] */
3169#define WM8962_EQR_B3_GAIN_WIDTH 5 /* EQR_B3_GAIN - [5:1] */
3170
3171/*
3172 * R357 (0x165) - EQ23
3173 */
3174#define WM8962_EQR_B4_GAIN_MASK 0xF800 /* EQR_B4_GAIN - [15:11] */
3175#define WM8962_EQR_B4_GAIN_SHIFT 11 /* EQR_B4_GAIN - [15:11] */
3176#define WM8962_EQR_B4_GAIN_WIDTH 5 /* EQR_B4_GAIN - [15:11] */
3177#define WM8962_EQR_B5_GAIN_MASK 0x07C0 /* EQR_B5_GAIN - [10:6] */
3178#define WM8962_EQR_B5_GAIN_SHIFT 6 /* EQR_B5_GAIN - [10:6] */
3179#define WM8962_EQR_B5_GAIN_WIDTH 5 /* EQR_B5_GAIN - [10:6] */
3180
3181/*
3182 * R358 (0x166) - EQ24
3183 */
3184#define WM8962_EQR_B1_A_MASK 0xFFFF /* EQR_B1_A - [15:0] */
3185#define WM8962_EQR_B1_A_SHIFT 0 /* EQR_B1_A - [15:0] */
3186#define WM8962_EQR_B1_A_WIDTH 16 /* EQR_B1_A - [15:0] */
3187
3188/*
3189 * R359 (0x167) - EQ25
3190 */
3191#define WM8962_EQR_B1_B_MASK 0xFFFF /* EQR_B1_B - [15:0] */
3192#define WM8962_EQR_B1_B_SHIFT 0 /* EQR_B1_B - [15:0] */
3193#define WM8962_EQR_B1_B_WIDTH 16 /* EQR_B1_B - [15:0] */
3194
3195/*
3196 * R360 (0x168) - EQ26
3197 */
3198#define WM8962_EQR_B1_PG_MASK 0xFFFF /* EQR_B1_PG - [15:0] */
3199#define WM8962_EQR_B1_PG_SHIFT 0 /* EQR_B1_PG - [15:0] */
3200#define WM8962_EQR_B1_PG_WIDTH 16 /* EQR_B1_PG - [15:0] */
3201
3202/*
3203 * R361 (0x169) - EQ27
3204 */
3205#define WM8962_EQR_B2_A_MASK 0xFFFF /* EQR_B2_A - [15:0] */
3206#define WM8962_EQR_B2_A_SHIFT 0 /* EQR_B2_A - [15:0] */
3207#define WM8962_EQR_B2_A_WIDTH 16 /* EQR_B2_A - [15:0] */
3208
3209/*
3210 * R362 (0x16A) - EQ28
3211 */
3212#define WM8962_EQR_B2_B_MASK 0xFFFF /* EQR_B2_B - [15:0] */
3213#define WM8962_EQR_B2_B_SHIFT 0 /* EQR_B2_B - [15:0] */
3214#define WM8962_EQR_B2_B_WIDTH 16 /* EQR_B2_B - [15:0] */
3215
3216/*
3217 * R363 (0x16B) - EQ29
3218 */
3219#define WM8962_EQR_B2_C_MASK 0xFFFF /* EQR_B2_C - [15:0] */
3220#define WM8962_EQR_B2_C_SHIFT 0 /* EQR_B2_C - [15:0] */
3221#define WM8962_EQR_B2_C_WIDTH 16 /* EQR_B2_C - [15:0] */
3222
3223/*
3224 * R364 (0x16C) - EQ30
3225 */
3226#define WM8962_EQR_B2_PG_MASK 0xFFFF /* EQR_B2_PG - [15:0] */
3227#define WM8962_EQR_B2_PG_SHIFT 0 /* EQR_B2_PG - [15:0] */
3228#define WM8962_EQR_B2_PG_WIDTH 16 /* EQR_B2_PG - [15:0] */
3229
3230/*
3231 * R365 (0x16D) - EQ31
3232 */
3233#define WM8962_EQR_B3_A_MASK 0xFFFF /* EQR_B3_A - [15:0] */
3234#define WM8962_EQR_B3_A_SHIFT 0 /* EQR_B3_A - [15:0] */
3235#define WM8962_EQR_B3_A_WIDTH 16 /* EQR_B3_A - [15:0] */
3236
3237/*
3238 * R366 (0x16E) - EQ32
3239 */
3240#define WM8962_EQR_B3_B_MASK 0xFFFF /* EQR_B3_B - [15:0] */
3241#define WM8962_EQR_B3_B_SHIFT 0 /* EQR_B3_B - [15:0] */
3242#define WM8962_EQR_B3_B_WIDTH 16 /* EQR_B3_B - [15:0] */
3243
3244/*
3245 * R367 (0x16F) - EQ33
3246 */
3247#define WM8962_EQR_B3_C_MASK 0xFFFF /* EQR_B3_C - [15:0] */
3248#define WM8962_EQR_B3_C_SHIFT 0 /* EQR_B3_C - [15:0] */
3249#define WM8962_EQR_B3_C_WIDTH 16 /* EQR_B3_C - [15:0] */
3250
3251/*
3252 * R368 (0x170) - EQ34
3253 */
3254#define WM8962_EQR_B3_PG_MASK 0xFFFF /* EQR_B3_PG - [15:0] */
3255#define WM8962_EQR_B3_PG_SHIFT 0 /* EQR_B3_PG - [15:0] */
3256#define WM8962_EQR_B3_PG_WIDTH 16 /* EQR_B3_PG - [15:0] */
3257
3258/*
3259 * R369 (0x171) - EQ35
3260 */
3261#define WM8962_EQR_B4_A_MASK 0xFFFF /* EQR_B4_A - [15:0] */
3262#define WM8962_EQR_B4_A_SHIFT 0 /* EQR_B4_A - [15:0] */
3263#define WM8962_EQR_B4_A_WIDTH 16 /* EQR_B4_A - [15:0] */
3264
3265/*
3266 * R370 (0x172) - EQ36
3267 */
3268#define WM8962_EQR_B4_B_MASK 0xFFFF /* EQR_B4_B - [15:0] */
3269#define WM8962_EQR_B4_B_SHIFT 0 /* EQR_B4_B - [15:0] */
3270#define WM8962_EQR_B4_B_WIDTH 16 /* EQR_B4_B - [15:0] */
3271
3272/*
3273 * R371 (0x173) - EQ37
3274 */
3275#define WM8962_EQR_B4_C_MASK 0xFFFF /* EQR_B4_C - [15:0] */
3276#define WM8962_EQR_B4_C_SHIFT 0 /* EQR_B4_C - [15:0] */
3277#define WM8962_EQR_B4_C_WIDTH 16 /* EQR_B4_C - [15:0] */
3278
3279/*
3280 * R372 (0x174) - EQ38
3281 */
3282#define WM8962_EQR_B4_PG_MASK 0xFFFF /* EQR_B4_PG - [15:0] */
3283#define WM8962_EQR_B4_PG_SHIFT 0 /* EQR_B4_PG - [15:0] */
3284#define WM8962_EQR_B4_PG_WIDTH 16 /* EQR_B4_PG - [15:0] */
3285
3286/*
3287 * R373 (0x175) - EQ39
3288 */
3289#define WM8962_EQR_B5_A_MASK 0xFFFF /* EQR_B5_A - [15:0] */
3290#define WM8962_EQR_B5_A_SHIFT 0 /* EQR_B5_A - [15:0] */
3291#define WM8962_EQR_B5_A_WIDTH 16 /* EQR_B5_A - [15:0] */
3292
3293/*
3294 * R374 (0x176) - EQ40
3295 */
3296#define WM8962_EQR_B5_B_MASK 0xFFFF /* EQR_B5_B - [15:0] */
3297#define WM8962_EQR_B5_B_SHIFT 0 /* EQR_B5_B - [15:0] */
3298#define WM8962_EQR_B5_B_WIDTH 16 /* EQR_B5_B - [15:0] */
3299
3300/*
3301 * R375 (0x177) - EQ41
3302 */
3303#define WM8962_EQR_B5_PG_MASK 0xFFFF /* EQR_B5_PG - [15:0] */
3304#define WM8962_EQR_B5_PG_SHIFT 0 /* EQR_B5_PG - [15:0] */
3305#define WM8962_EQR_B5_PG_WIDTH 16 /* EQR_B5_PG - [15:0] */
3306
3307/*
3308 * R513 (0x201) - GPIO 2
3309 */
3310#define WM8962_GP2_POL 0x0400 /* GP2_POL */
3311#define WM8962_GP2_POL_MASK 0x0400 /* GP2_POL */
3312#define WM8962_GP2_POL_SHIFT 10 /* GP2_POL */
3313#define WM8962_GP2_POL_WIDTH 1 /* GP2_POL */
3314#define WM8962_GP2_LVL 0x0040 /* GP2_LVL */
3315#define WM8962_GP2_LVL_MASK 0x0040 /* GP2_LVL */
3316#define WM8962_GP2_LVL_SHIFT 6 /* GP2_LVL */
3317#define WM8962_GP2_LVL_WIDTH 1 /* GP2_LVL */
3318#define WM8962_GP2_FN_MASK 0x001F /* GP2_FN - [4:0] */
3319#define WM8962_GP2_FN_SHIFT 0 /* GP2_FN - [4:0] */
3320#define WM8962_GP2_FN_WIDTH 5 /* GP2_FN - [4:0] */
3321
3322/*
3323 * R514 (0x202) - GPIO 3
3324 */
3325#define WM8962_GP3_POL 0x0400 /* GP3_POL */
3326#define WM8962_GP3_POL_MASK 0x0400 /* GP3_POL */
3327#define WM8962_GP3_POL_SHIFT 10 /* GP3_POL */
3328#define WM8962_GP3_POL_WIDTH 1 /* GP3_POL */
3329#define WM8962_GP3_LVL 0x0040 /* GP3_LVL */
3330#define WM8962_GP3_LVL_MASK 0x0040 /* GP3_LVL */
3331#define WM8962_GP3_LVL_SHIFT 6 /* GP3_LVL */
3332#define WM8962_GP3_LVL_WIDTH 1 /* GP3_LVL */
3333#define WM8962_GP3_FN_MASK 0x001F /* GP3_FN - [4:0] */
3334#define WM8962_GP3_FN_SHIFT 0 /* GP3_FN - [4:0] */
3335#define WM8962_GP3_FN_WIDTH 5 /* GP3_FN - [4:0] */
3336
3337/*
3338 * R516 (0x204) - GPIO 5
3339 */
3340#define WM8962_GP5_DIR 0x8000 /* GP5_DIR */
3341#define WM8962_GP5_DIR_MASK 0x8000 /* GP5_DIR */
3342#define WM8962_GP5_DIR_SHIFT 15 /* GP5_DIR */
3343#define WM8962_GP5_DIR_WIDTH 1 /* GP5_DIR */
3344#define WM8962_GP5_PU 0x4000 /* GP5_PU */
3345#define WM8962_GP5_PU_MASK 0x4000 /* GP5_PU */
3346#define WM8962_GP5_PU_SHIFT 14 /* GP5_PU */
3347#define WM8962_GP5_PU_WIDTH 1 /* GP5_PU */
3348#define WM8962_GP5_PD 0x2000 /* GP5_PD */
3349#define WM8962_GP5_PD_MASK 0x2000 /* GP5_PD */
3350#define WM8962_GP5_PD_SHIFT 13 /* GP5_PD */
3351#define WM8962_GP5_PD_WIDTH 1 /* GP5_PD */
3352#define WM8962_GP5_POL 0x0400 /* GP5_POL */
3353#define WM8962_GP5_POL_MASK 0x0400 /* GP5_POL */
3354#define WM8962_GP5_POL_SHIFT 10 /* GP5_POL */
3355#define WM8962_GP5_POL_WIDTH 1 /* GP5_POL */
3356#define WM8962_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */
3357#define WM8962_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */
3358#define WM8962_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */
3359#define WM8962_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */
3360#define WM8962_GP5_DB 0x0100 /* GP5_DB */
3361#define WM8962_GP5_DB_MASK 0x0100 /* GP5_DB */
3362#define WM8962_GP5_DB_SHIFT 8 /* GP5_DB */
3363#define WM8962_GP5_DB_WIDTH 1 /* GP5_DB */
3364#define WM8962_GP5_LVL 0x0040 /* GP5_LVL */
3365#define WM8962_GP5_LVL_MASK 0x0040 /* GP5_LVL */
3366#define WM8962_GP5_LVL_SHIFT 6 /* GP5_LVL */
3367#define WM8962_GP5_LVL_WIDTH 1 /* GP5_LVL */
3368#define WM8962_GP5_FN_MASK 0x001F /* GP5_FN - [4:0] */
3369#define WM8962_GP5_FN_SHIFT 0 /* GP5_FN - [4:0] */
3370#define WM8962_GP5_FN_WIDTH 5 /* GP5_FN - [4:0] */
3371
3372/*
3373 * R517 (0x205) - GPIO 6
3374 */
3375#define WM8962_GP6_DIR 0x8000 /* GP6_DIR */
3376#define WM8962_GP6_DIR_MASK 0x8000 /* GP6_DIR */
3377#define WM8962_GP6_DIR_SHIFT 15 /* GP6_DIR */
3378#define WM8962_GP6_DIR_WIDTH 1 /* GP6_DIR */
3379#define WM8962_GP6_PU 0x4000 /* GP6_PU */
3380#define WM8962_GP6_PU_MASK 0x4000 /* GP6_PU */
3381#define WM8962_GP6_PU_SHIFT 14 /* GP6_PU */
3382#define WM8962_GP6_PU_WIDTH 1 /* GP6_PU */
3383#define WM8962_GP6_PD 0x2000 /* GP6_PD */
3384#define WM8962_GP6_PD_MASK 0x2000 /* GP6_PD */
3385#define WM8962_GP6_PD_SHIFT 13 /* GP6_PD */
3386#define WM8962_GP6_PD_WIDTH 1 /* GP6_PD */
3387#define WM8962_GP6_POL 0x0400 /* GP6_POL */
3388#define WM8962_GP6_POL_MASK 0x0400 /* GP6_POL */
3389#define WM8962_GP6_POL_SHIFT 10 /* GP6_POL */
3390#define WM8962_GP6_POL_WIDTH 1 /* GP6_POL */
3391#define WM8962_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */
3392#define WM8962_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */
3393#define WM8962_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */
3394#define WM8962_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */
3395#define WM8962_GP6_DB 0x0100 /* GP6_DB */
3396#define WM8962_GP6_DB_MASK 0x0100 /* GP6_DB */
3397#define WM8962_GP6_DB_SHIFT 8 /* GP6_DB */
3398#define WM8962_GP6_DB_WIDTH 1 /* GP6_DB */
3399#define WM8962_GP6_LVL 0x0040 /* GP6_LVL */
3400#define WM8962_GP6_LVL_MASK 0x0040 /* GP6_LVL */
3401#define WM8962_GP6_LVL_SHIFT 6 /* GP6_LVL */
3402#define WM8962_GP6_LVL_WIDTH 1 /* GP6_LVL */
3403#define WM8962_GP6_FN_MASK 0x001F /* GP6_FN - [4:0] */
3404#define WM8962_GP6_FN_SHIFT 0 /* GP6_FN - [4:0] */
3405#define WM8962_GP6_FN_WIDTH 5 /* GP6_FN - [4:0] */
3406
3407/*
3408 * R560 (0x230) - Interrupt Status 1
3409 */
3410#define WM8962_GP6_EINT 0x0020 /* GP6_EINT */
3411#define WM8962_GP6_EINT_MASK 0x0020 /* GP6_EINT */
3412#define WM8962_GP6_EINT_SHIFT 5 /* GP6_EINT */
3413#define WM8962_GP6_EINT_WIDTH 1 /* GP6_EINT */
3414#define WM8962_GP5_EINT 0x0010 /* GP5_EINT */
3415#define WM8962_GP5_EINT_MASK 0x0010 /* GP5_EINT */
3416#define WM8962_GP5_EINT_SHIFT 4 /* GP5_EINT */
3417#define WM8962_GP5_EINT_WIDTH 1 /* GP5_EINT */
3418
3419/*
3420 * R561 (0x231) - Interrupt Status 2
3421 */
3422#define WM8962_MICSCD_EINT 0x8000 /* MICSCD_EINT */
3423#define WM8962_MICSCD_EINT_MASK 0x8000 /* MICSCD_EINT */
3424#define WM8962_MICSCD_EINT_SHIFT 15 /* MICSCD_EINT */
3425#define WM8962_MICSCD_EINT_WIDTH 1 /* MICSCD_EINT */
3426#define WM8962_MICD_EINT 0x4000 /* MICD_EINT */
3427#define WM8962_MICD_EINT_MASK 0x4000 /* MICD_EINT */
3428#define WM8962_MICD_EINT_SHIFT 14 /* MICD_EINT */
3429#define WM8962_MICD_EINT_WIDTH 1 /* MICD_EINT */
3430#define WM8962_FIFOS_ERR_EINT 0x2000 /* FIFOS_ERR_EINT */
3431#define WM8962_FIFOS_ERR_EINT_MASK 0x2000 /* FIFOS_ERR_EINT */
3432#define WM8962_FIFOS_ERR_EINT_SHIFT 13 /* FIFOS_ERR_EINT */
3433#define WM8962_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */
3434#define WM8962_ALC_LOCK_EINT 0x1000 /* ALC_LOCK_EINT */
3435#define WM8962_ALC_LOCK_EINT_MASK 0x1000 /* ALC_LOCK_EINT */
3436#define WM8962_ALC_LOCK_EINT_SHIFT 12 /* ALC_LOCK_EINT */
3437#define WM8962_ALC_LOCK_EINT_WIDTH 1 /* ALC_LOCK_EINT */
3438#define WM8962_ALC_THRESH_EINT 0x0800 /* ALC_THRESH_EINT */
3439#define WM8962_ALC_THRESH_EINT_MASK 0x0800 /* ALC_THRESH_EINT */
3440#define WM8962_ALC_THRESH_EINT_SHIFT 11 /* ALC_THRESH_EINT */
3441#define WM8962_ALC_THRESH_EINT_WIDTH 1 /* ALC_THRESH_EINT */
3442#define WM8962_ALC_SAT_EINT 0x0400 /* ALC_SAT_EINT */
3443#define WM8962_ALC_SAT_EINT_MASK 0x0400 /* ALC_SAT_EINT */
3444#define WM8962_ALC_SAT_EINT_SHIFT 10 /* ALC_SAT_EINT */
3445#define WM8962_ALC_SAT_EINT_WIDTH 1 /* ALC_SAT_EINT */
3446#define WM8962_ALC_PKOVR_EINT 0x0200 /* ALC_PKOVR_EINT */
3447#define WM8962_ALC_PKOVR_EINT_MASK 0x0200 /* ALC_PKOVR_EINT */
3448#define WM8962_ALC_PKOVR_EINT_SHIFT 9 /* ALC_PKOVR_EINT */
3449#define WM8962_ALC_PKOVR_EINT_WIDTH 1 /* ALC_PKOVR_EINT */
3450#define WM8962_ALC_NGATE_EINT 0x0100 /* ALC_NGATE_EINT */
3451#define WM8962_ALC_NGATE_EINT_MASK 0x0100 /* ALC_NGATE_EINT */
3452#define WM8962_ALC_NGATE_EINT_SHIFT 8 /* ALC_NGATE_EINT */
3453#define WM8962_ALC_NGATE_EINT_WIDTH 1 /* ALC_NGATE_EINT */
3454#define WM8962_WSEQ_DONE_EINT 0x0080 /* WSEQ_DONE_EINT */
3455#define WM8962_WSEQ_DONE_EINT_MASK 0x0080 /* WSEQ_DONE_EINT */
3456#define WM8962_WSEQ_DONE_EINT_SHIFT 7 /* WSEQ_DONE_EINT */
3457#define WM8962_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */
3458#define WM8962_DRC_ACTDET_EINT 0x0040 /* DRC_ACTDET_EINT */
3459#define WM8962_DRC_ACTDET_EINT_MASK 0x0040 /* DRC_ACTDET_EINT */
3460#define WM8962_DRC_ACTDET_EINT_SHIFT 6 /* DRC_ACTDET_EINT */
3461#define WM8962_DRC_ACTDET_EINT_WIDTH 1 /* DRC_ACTDET_EINT */
3462#define WM8962_FLL_LOCK_EINT 0x0020 /* FLL_LOCK_EINT */
3463#define WM8962_FLL_LOCK_EINT_MASK 0x0020 /* FLL_LOCK_EINT */
3464#define WM8962_FLL_LOCK_EINT_SHIFT 5 /* FLL_LOCK_EINT */
3465#define WM8962_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */
3466#define WM8962_PLL3_LOCK_EINT 0x0008 /* PLL3_LOCK_EINT */
3467#define WM8962_PLL3_LOCK_EINT_MASK 0x0008 /* PLL3_LOCK_EINT */
3468#define WM8962_PLL3_LOCK_EINT_SHIFT 3 /* PLL3_LOCK_EINT */
3469#define WM8962_PLL3_LOCK_EINT_WIDTH 1 /* PLL3_LOCK_EINT */
3470#define WM8962_PLL2_LOCK_EINT 0x0004 /* PLL2_LOCK_EINT */
3471#define WM8962_PLL2_LOCK_EINT_MASK 0x0004 /* PLL2_LOCK_EINT */
3472#define WM8962_PLL2_LOCK_EINT_SHIFT 2 /* PLL2_LOCK_EINT */
3473#define WM8962_PLL2_LOCK_EINT_WIDTH 1 /* PLL2_LOCK_EINT */
3474#define WM8962_TEMP_SHUT_EINT 0x0001 /* TEMP_SHUT_EINT */
3475#define WM8962_TEMP_SHUT_EINT_MASK 0x0001 /* TEMP_SHUT_EINT */
3476#define WM8962_TEMP_SHUT_EINT_SHIFT 0 /* TEMP_SHUT_EINT */
3477#define WM8962_TEMP_SHUT_EINT_WIDTH 1 /* TEMP_SHUT_EINT */
3478
3479/*
3480 * R568 (0x238) - Interrupt Status 1 Mask
3481 */
3482#define WM8962_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */
3483#define WM8962_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */
3484#define WM8962_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */
3485#define WM8962_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */
3486#define WM8962_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */
3487#define WM8962_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */
3488#define WM8962_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */
3489#define WM8962_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */
3490
3491/*
3492 * R569 (0x239) - Interrupt Status 2 Mask
3493 */
3494#define WM8962_IM_MICSCD_EINT 0x8000 /* IM_MICSCD_EINT */
3495#define WM8962_IM_MICSCD_EINT_MASK 0x8000 /* IM_MICSCD_EINT */
3496#define WM8962_IM_MICSCD_EINT_SHIFT 15 /* IM_MICSCD_EINT */
3497#define WM8962_IM_MICSCD_EINT_WIDTH 1 /* IM_MICSCD_EINT */
3498#define WM8962_IM_MICD_EINT 0x4000 /* IM_MICD_EINT */
3499#define WM8962_IM_MICD_EINT_MASK 0x4000 /* IM_MICD_EINT */
3500#define WM8962_IM_MICD_EINT_SHIFT 14 /* IM_MICD_EINT */
3501#define WM8962_IM_MICD_EINT_WIDTH 1 /* IM_MICD_EINT */
3502#define WM8962_IM_FIFOS_ERR_EINT 0x2000 /* IM_FIFOS_ERR_EINT */
3503#define WM8962_IM_FIFOS_ERR_EINT_MASK 0x2000 /* IM_FIFOS_ERR_EINT */
3504#define WM8962_IM_FIFOS_ERR_EINT_SHIFT 13 /* IM_FIFOS_ERR_EINT */
3505#define WM8962_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */
3506#define WM8962_IM_ALC_LOCK_EINT 0x1000 /* IM_ALC_LOCK_EINT */
3507#define WM8962_IM_ALC_LOCK_EINT_MASK 0x1000 /* IM_ALC_LOCK_EINT */
3508#define WM8962_IM_ALC_LOCK_EINT_SHIFT 12 /* IM_ALC_LOCK_EINT */
3509#define WM8962_IM_ALC_LOCK_EINT_WIDTH 1 /* IM_ALC_LOCK_EINT */
3510#define WM8962_IM_ALC_THRESH_EINT 0x0800 /* IM_ALC_THRESH_EINT */
3511#define WM8962_IM_ALC_THRESH_EINT_MASK 0x0800 /* IM_ALC_THRESH_EINT */
3512#define WM8962_IM_ALC_THRESH_EINT_SHIFT 11 /* IM_ALC_THRESH_EINT */
3513#define WM8962_IM_ALC_THRESH_EINT_WIDTH 1 /* IM_ALC_THRESH_EINT */
3514#define WM8962_IM_ALC_SAT_EINT 0x0400 /* IM_ALC_SAT_EINT */
3515#define WM8962_IM_ALC_SAT_EINT_MASK 0x0400 /* IM_ALC_SAT_EINT */
3516#define WM8962_IM_ALC_SAT_EINT_SHIFT 10 /* IM_ALC_SAT_EINT */
3517#define WM8962_IM_ALC_SAT_EINT_WIDTH 1 /* IM_ALC_SAT_EINT */
3518#define WM8962_IM_ALC_PKOVR_EINT 0x0200 /* IM_ALC_PKOVR_EINT */
3519#define WM8962_IM_ALC_PKOVR_EINT_MASK 0x0200 /* IM_ALC_PKOVR_EINT */
3520#define WM8962_IM_ALC_PKOVR_EINT_SHIFT 9 /* IM_ALC_PKOVR_EINT */
3521#define WM8962_IM_ALC_PKOVR_EINT_WIDTH 1 /* IM_ALC_PKOVR_EINT */
3522#define WM8962_IM_ALC_NGATE_EINT 0x0100 /* IM_ALC_NGATE_EINT */
3523#define WM8962_IM_ALC_NGATE_EINT_MASK 0x0100 /* IM_ALC_NGATE_EINT */
3524#define WM8962_IM_ALC_NGATE_EINT_SHIFT 8 /* IM_ALC_NGATE_EINT */
3525#define WM8962_IM_ALC_NGATE_EINT_WIDTH 1 /* IM_ALC_NGATE_EINT */
3526#define WM8962_IM_WSEQ_DONE_EINT 0x0080 /* IM_WSEQ_DONE_EINT */
3527#define WM8962_IM_WSEQ_DONE_EINT_MASK 0x0080 /* IM_WSEQ_DONE_EINT */
3528#define WM8962_IM_WSEQ_DONE_EINT_SHIFT 7 /* IM_WSEQ_DONE_EINT */
3529#define WM8962_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */
3530#define WM8962_IM_DRC_ACTDET_EINT 0x0040 /* IM_DRC_ACTDET_EINT */
3531#define WM8962_IM_DRC_ACTDET_EINT_MASK 0x0040 /* IM_DRC_ACTDET_EINT */
3532#define WM8962_IM_DRC_ACTDET_EINT_SHIFT 6 /* IM_DRC_ACTDET_EINT */
3533#define WM8962_IM_DRC_ACTDET_EINT_WIDTH 1 /* IM_DRC_ACTDET_EINT */
3534#define WM8962_IM_FLL_LOCK_EINT 0x0020 /* IM_FLL_LOCK_EINT */
3535#define WM8962_IM_FLL_LOCK_EINT_MASK 0x0020 /* IM_FLL_LOCK_EINT */
3536#define WM8962_IM_FLL_LOCK_EINT_SHIFT 5 /* IM_FLL_LOCK_EINT */
3537#define WM8962_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */
3538#define WM8962_IM_PLL3_LOCK_EINT 0x0008 /* IM_PLL3_LOCK_EINT */
3539#define WM8962_IM_PLL3_LOCK_EINT_MASK 0x0008 /* IM_PLL3_LOCK_EINT */
3540#define WM8962_IM_PLL3_LOCK_EINT_SHIFT 3 /* IM_PLL3_LOCK_EINT */
3541#define WM8962_IM_PLL3_LOCK_EINT_WIDTH 1 /* IM_PLL3_LOCK_EINT */
3542#define WM8962_IM_PLL2_LOCK_EINT 0x0004 /* IM_PLL2_LOCK_EINT */
3543#define WM8962_IM_PLL2_LOCK_EINT_MASK 0x0004 /* IM_PLL2_LOCK_EINT */
3544#define WM8962_IM_PLL2_LOCK_EINT_SHIFT 2 /* IM_PLL2_LOCK_EINT */
3545#define WM8962_IM_PLL2_LOCK_EINT_WIDTH 1 /* IM_PLL2_LOCK_EINT */
3546#define WM8962_IM_TEMP_SHUT_EINT 0x0001 /* IM_TEMP_SHUT_EINT */
3547#define WM8962_IM_TEMP_SHUT_EINT_MASK 0x0001 /* IM_TEMP_SHUT_EINT */
3548#define WM8962_IM_TEMP_SHUT_EINT_SHIFT 0 /* IM_TEMP_SHUT_EINT */
3549#define WM8962_IM_TEMP_SHUT_EINT_WIDTH 1 /* IM_TEMP_SHUT_EINT */
3550
3551/*
3552 * R576 (0x240) - Interrupt Control
3553 */
3554#define WM8962_IRQ_POL 0x0001 /* IRQ_POL */
3555#define WM8962_IRQ_POL_MASK 0x0001 /* IRQ_POL */
3556#define WM8962_IRQ_POL_SHIFT 0 /* IRQ_POL */
3557#define WM8962_IRQ_POL_WIDTH 1 /* IRQ_POL */
3558
3559/*
3560 * R584 (0x248) - IRQ Debounce
3561 */
3562#define WM8962_FLL_LOCK_DB 0x0020 /* FLL_LOCK_DB */
3563#define WM8962_FLL_LOCK_DB_MASK 0x0020 /* FLL_LOCK_DB */
3564#define WM8962_FLL_LOCK_DB_SHIFT 5 /* FLL_LOCK_DB */
3565#define WM8962_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */
3566#define WM8962_PLL3_LOCK_DB 0x0008 /* PLL3_LOCK_DB */
3567#define WM8962_PLL3_LOCK_DB_MASK 0x0008 /* PLL3_LOCK_DB */
3568#define WM8962_PLL3_LOCK_DB_SHIFT 3 /* PLL3_LOCK_DB */
3569#define WM8962_PLL3_LOCK_DB_WIDTH 1 /* PLL3_LOCK_DB */
3570#define WM8962_PLL2_LOCK_DB 0x0004 /* PLL2_LOCK_DB */
3571#define WM8962_PLL2_LOCK_DB_MASK 0x0004 /* PLL2_LOCK_DB */
3572#define WM8962_PLL2_LOCK_DB_SHIFT 2 /* PLL2_LOCK_DB */
3573#define WM8962_PLL2_LOCK_DB_WIDTH 1 /* PLL2_LOCK_DB */
3574#define WM8962_TEMP_SHUT_DB 0x0001 /* TEMP_SHUT_DB */
3575#define WM8962_TEMP_SHUT_DB_MASK 0x0001 /* TEMP_SHUT_DB */
3576#define WM8962_TEMP_SHUT_DB_SHIFT 0 /* TEMP_SHUT_DB */
3577#define WM8962_TEMP_SHUT_DB_WIDTH 1 /* TEMP_SHUT_DB */
3578
3579/*
3580 * R586 (0x24A) - MICINT Source Pol
3581 */
3582#define WM8962_MICSCD_IRQ_POL 0x8000 /* MICSCD_IRQ_POL */
3583#define WM8962_MICSCD_IRQ_POL_MASK 0x8000 /* MICSCD_IRQ_POL */
3584#define WM8962_MICSCD_IRQ_POL_SHIFT 15 /* MICSCD_IRQ_POL */
3585#define WM8962_MICSCD_IRQ_POL_WIDTH 1 /* MICSCD_IRQ_POL */
3586#define WM8962_MICD_IRQ_POL 0x4000 /* MICD_IRQ_POL */
3587#define WM8962_MICD_IRQ_POL_MASK 0x4000 /* MICD_IRQ_POL */
3588#define WM8962_MICD_IRQ_POL_SHIFT 14 /* MICD_IRQ_POL */
3589#define WM8962_MICD_IRQ_POL_WIDTH 1 /* MICD_IRQ_POL */
3590
3591/*
3592 * R768 (0x300) - DSP2 Power Management
3593 */
3594#define WM8962_DSP2_ENA 0x0001 /* DSP2_ENA */
3595#define WM8962_DSP2_ENA_MASK 0x0001 /* DSP2_ENA */
3596#define WM8962_DSP2_ENA_SHIFT 0 /* DSP2_ENA */
3597#define WM8962_DSP2_ENA_WIDTH 1 /* DSP2_ENA */
3598
3599/*
3600 * R1037 (0x40D) - DSP2_ExecControl
3601 */
3602#define WM8962_DSP2_STOPC 0x0020 /* DSP2_STOPC */
3603#define WM8962_DSP2_STOPC_MASK 0x0020 /* DSP2_STOPC */
3604#define WM8962_DSP2_STOPC_SHIFT 5 /* DSP2_STOPC */
3605#define WM8962_DSP2_STOPC_WIDTH 1 /* DSP2_STOPC */
3606#define WM8962_DSP2_STOPS 0x0010 /* DSP2_STOPS */
3607#define WM8962_DSP2_STOPS_MASK 0x0010 /* DSP2_STOPS */
3608#define WM8962_DSP2_STOPS_SHIFT 4 /* DSP2_STOPS */
3609#define WM8962_DSP2_STOPS_WIDTH 1 /* DSP2_STOPS */
3610#define WM8962_DSP2_STOPI 0x0008 /* DSP2_STOPI */
3611#define WM8962_DSP2_STOPI_MASK 0x0008 /* DSP2_STOPI */
3612#define WM8962_DSP2_STOPI_SHIFT 3 /* DSP2_STOPI */
3613#define WM8962_DSP2_STOPI_WIDTH 1 /* DSP2_STOPI */
3614#define WM8962_DSP2_STOP 0x0004 /* DSP2_STOP */
3615#define WM8962_DSP2_STOP_MASK 0x0004 /* DSP2_STOP */
3616#define WM8962_DSP2_STOP_SHIFT 2 /* DSP2_STOP */
3617#define WM8962_DSP2_STOP_WIDTH 1 /* DSP2_STOP */
3618#define WM8962_DSP2_RUNR 0x0002 /* DSP2_RUNR */
3619#define WM8962_DSP2_RUNR_MASK 0x0002 /* DSP2_RUNR */
3620#define WM8962_DSP2_RUNR_SHIFT 1 /* DSP2_RUNR */
3621#define WM8962_DSP2_RUNR_WIDTH 1 /* DSP2_RUNR */
3622#define WM8962_DSP2_RUN 0x0001 /* DSP2_RUN */
3623#define WM8962_DSP2_RUN_MASK 0x0001 /* DSP2_RUN */
3624#define WM8962_DSP2_RUN_SHIFT 0 /* DSP2_RUN */
3625#define WM8962_DSP2_RUN_WIDTH 1 /* DSP2_RUN */
3626
3627/*
3628 * R8192 (0x2000) - DSP2 Instruction RAM 0
3629 */
3630#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_MASK 0x03FF /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
3631#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_SHIFT 0 /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
3632#define WM8962_DSP2_INSTR_RAM_1024_10_9_0_WIDTH 10 /* DSP2_INSTR_RAM_1024_10_9_0 - [9:0] */
3633
3634/*
3635 * R9216 (0x2400) - DSP2 Address RAM 2
3636 */
3637#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_MASK 0x003F /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
3638#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
3639#define WM8962_DSP2_ADDR_RAM_1024_38_37_32_WIDTH 6 /* DSP2_ADDR_RAM_1024_38_37_32 - [5:0] */
3640
3641/*
3642 * R9217 (0x2401) - DSP2 Address RAM 1
3643 */
3644#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_MASK 0xFFFF /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
3645#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
3646#define WM8962_DSP2_ADDR_RAM_1024_38_31_16_WIDTH 16 /* DSP2_ADDR_RAM_1024_38_31_16 - [15:0] */
3647
3648/*
3649 * R9218 (0x2402) - DSP2 Address RAM 0
3650 */
3651#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_MASK 0xFFFF /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
3652#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_SHIFT 0 /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
3653#define WM8962_DSP2_ADDR_RAM_1024_38_15_0_WIDTH 16 /* DSP2_ADDR_RAM_1024_38_15_0 - [15:0] */
3654
3655/*
3656 * R12288 (0x3000) - DSP2 Data1 RAM 1
3657 */
3658#define WM8962_DSP2_DATA1_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
3659#define WM8962_DSP2_DATA1_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
3660#define WM8962_DSP2_DATA1_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA1_RAM_384_24_23_16 - [7:0] */
3661
3662/*
3663 * R12289 (0x3001) - DSP2 Data1 RAM 0
3664 */
3665#define WM8962_DSP2_DATA1_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
3666#define WM8962_DSP2_DATA1_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
3667#define WM8962_DSP2_DATA1_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA1_RAM_384_24_15_0 - [15:0] */
3668
3669/*
3670 * R13312 (0x3400) - DSP2 Data2 RAM 1
3671 */
3672#define WM8962_DSP2_DATA2_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
3673#define WM8962_DSP2_DATA2_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
3674#define WM8962_DSP2_DATA2_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA2_RAM_384_24_23_16 - [7:0] */
3675
3676/*
3677 * R13313 (0x3401) - DSP2 Data2 RAM 0
3678 */
3679#define WM8962_DSP2_DATA2_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
3680#define WM8962_DSP2_DATA2_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
3681#define WM8962_DSP2_DATA2_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA2_RAM_384_24_15_0 - [15:0] */
3682
3683/*
3684 * R14336 (0x3800) - DSP2 Data3 RAM 1
3685 */
3686#define WM8962_DSP2_DATA3_RAM_384_24_23_16_MASK 0x00FF /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
3687#define WM8962_DSP2_DATA3_RAM_384_24_23_16_SHIFT 0 /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
3688#define WM8962_DSP2_DATA3_RAM_384_24_23_16_WIDTH 8 /* DSP2_DATA3_RAM_384_24_23_16 - [7:0] */
3689
3690/*
3691 * R14337 (0x3801) - DSP2 Data3 RAM 0
3692 */
3693#define WM8962_DSP2_DATA3_RAM_384_24_15_0_MASK 0xFFFF /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
3694#define WM8962_DSP2_DATA3_RAM_384_24_15_0_SHIFT 0 /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
3695#define WM8962_DSP2_DATA3_RAM_384_24_15_0_WIDTH 16 /* DSP2_DATA3_RAM_384_24_15_0 - [15:0] */
3696
3697/*
3698 * R15360 (0x3C00) - DSP2 Coeff RAM 0
3699 */
3700#define WM8962_DSP2_CMAP_RAM_384_11_10_0_MASK 0x07FF /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
3701#define WM8962_DSP2_CMAP_RAM_384_11_10_0_SHIFT 0 /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
3702#define WM8962_DSP2_CMAP_RAM_384_11_10_0_WIDTH 11 /* DSP2_CMAP_RAM_384_11_10_0 - [10:0] */
3703
3704/*
3705 * R16384 (0x4000) - RETUNEADC_SHARED_COEFF_1
3706 */
3707#define WM8962_ADC_RETUNE_SCV 0x0080 /* ADC_RETUNE_SCV */
3708#define WM8962_ADC_RETUNE_SCV_MASK 0x0080 /* ADC_RETUNE_SCV */
3709#define WM8962_ADC_RETUNE_SCV_SHIFT 7 /* ADC_RETUNE_SCV */
3710#define WM8962_ADC_RETUNE_SCV_WIDTH 1 /* ADC_RETUNE_SCV */
3711#define WM8962_RETUNEADC_SHARED_COEFF_22_16_MASK 0x007F /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
3712#define WM8962_RETUNEADC_SHARED_COEFF_22_16_SHIFT 0 /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
3713#define WM8962_RETUNEADC_SHARED_COEFF_22_16_WIDTH 7 /* RETUNEADC_SHARED_COEFF_22_16 - [6:0] */
3714
3715/*
3716 * R16385 (0x4001) - RETUNEADC_SHARED_COEFF_0
3717 */
3718#define WM8962_RETUNEADC_SHARED_COEFF_15_00_MASK 0xFFFF /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
3719#define WM8962_RETUNEADC_SHARED_COEFF_15_00_SHIFT 0 /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
3720#define WM8962_RETUNEADC_SHARED_COEFF_15_00_WIDTH 16 /* RETUNEADC_SHARED_COEFF_15_00 - [15:0] */
3721
3722/*
3723 * R16386 (0x4002) - RETUNEDAC_SHARED_COEFF_1
3724 */
3725#define WM8962_DAC_RETUNE_SCV 0x0080 /* DAC_RETUNE_SCV */
3726#define WM8962_DAC_RETUNE_SCV_MASK 0x0080 /* DAC_RETUNE_SCV */
3727#define WM8962_DAC_RETUNE_SCV_SHIFT 7 /* DAC_RETUNE_SCV */
3728#define WM8962_DAC_RETUNE_SCV_WIDTH 1 /* DAC_RETUNE_SCV */
3729#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_MASK 0x007F /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
3730#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_SHIFT 0 /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
3731#define WM8962_RETUNEDAC_SHARED_COEFF_23_16_WIDTH 7 /* RETUNEDAC_SHARED_COEFF_23_16 - [6:0] */
3732
3733/*
3734 * R16387 (0x4003) - RETUNEDAC_SHARED_COEFF_0
3735 */
3736#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_MASK 0xFFFF /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
3737#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_SHIFT 0 /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
3738#define WM8962_RETUNEDAC_SHARED_COEFF_15_00_WIDTH 16 /* RETUNEDAC_SHARED_COEFF_15_00 - [15:0] */
3739
3740/*
3741 * R16388 (0x4004) - SOUNDSTAGE_ENABLES_1
3742 */
3743#define WM8962_SOUNDSTAGE_ENABLES_23_16_MASK 0x00FF /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
3744#define WM8962_SOUNDSTAGE_ENABLES_23_16_SHIFT 0 /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
3745#define WM8962_SOUNDSTAGE_ENABLES_23_16_WIDTH 8 /* SOUNDSTAGE_ENABLES_23_16 - [7:0] */
3746
3747/*
3748 * R16389 (0x4005) - SOUNDSTAGE_ENABLES_0
3749 */
3750#define WM8962_SOUNDSTAGE_ENABLES_15_06_MASK 0xFFC0 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
3751#define WM8962_SOUNDSTAGE_ENABLES_15_06_SHIFT 6 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
3752#define WM8962_SOUNDSTAGE_ENABLES_15_06_WIDTH 10 /* SOUNDSTAGE_ENABLES_15_06 - [15:6] */
3753#define WM8962_RTN_ADC_ENA 0x0020 /* RTN_ADC_ENA */
3754#define WM8962_RTN_ADC_ENA_MASK 0x0020 /* RTN_ADC_ENA */
3755#define WM8962_RTN_ADC_ENA_SHIFT 5 /* RTN_ADC_ENA */
3756#define WM8962_RTN_ADC_ENA_WIDTH 1 /* RTN_ADC_ENA */
3757#define WM8962_RTN_DAC_ENA 0x0010 /* RTN_DAC_ENA */
3758#define WM8962_RTN_DAC_ENA_MASK 0x0010 /* RTN_DAC_ENA */
3759#define WM8962_RTN_DAC_ENA_SHIFT 4 /* RTN_DAC_ENA */
3760#define WM8962_RTN_DAC_ENA_WIDTH 1 /* RTN_DAC_ENA */
3761#define WM8962_HDBASS_ENA 0x0008 /* HDBASS_ENA */
3762#define WM8962_HDBASS_ENA_MASK 0x0008 /* HDBASS_ENA */
3763#define WM8962_HDBASS_ENA_SHIFT 3 /* HDBASS_ENA */
3764#define WM8962_HDBASS_ENA_WIDTH 1 /* HDBASS_ENA */
3765#define WM8962_HPF2_ENA 0x0004 /* HPF2_ENA */
3766#define WM8962_HPF2_ENA_MASK 0x0004 /* HPF2_ENA */
3767#define WM8962_HPF2_ENA_SHIFT 2 /* HPF2_ENA */
3768#define WM8962_HPF2_ENA_WIDTH 1 /* HPF2_ENA */
3769#define WM8962_HPF1_ENA 0x0002 /* HPF1_ENA */
3770#define WM8962_HPF1_ENA_MASK 0x0002 /* HPF1_ENA */
3771#define WM8962_HPF1_ENA_SHIFT 1 /* HPF1_ENA */
3772#define WM8962_HPF1_ENA_WIDTH 1 /* HPF1_ENA */
3773#define WM8962_VSS_ENA 0x0001 /* VSS_ENA */
3774#define WM8962_VSS_ENA_MASK 0x0001 /* VSS_ENA */
3775#define WM8962_VSS_ENA_SHIFT 0 /* VSS_ENA */
3776#define WM8962_VSS_ENA_WIDTH 1 /* VSS_ENA */
3777
3778int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
3779
3780#endif
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index a99620f335d2..63f6dbf5d070 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -30,14 +30,13 @@
30 30
31#include "wm8971.h" 31#include "wm8971.h"
32 32
33#define WM8971_VERSION "0.9"
34
35#define WM8971_REG_COUNT 43 33#define WM8971_REG_COUNT 43
36 34
37static struct workqueue_struct *wm8971_workq = NULL; 35static struct workqueue_struct *wm8971_workq = NULL;
38 36
39/* codec private data */ 37/* codec private data */
40struct wm8971_priv { 38struct wm8971_priv {
39 enum snd_soc_control_type control_type;
41 unsigned int sysclk; 40 unsigned int sysclk;
42}; 41};
43 42
@@ -492,8 +491,7 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
492 struct snd_soc_dai *dai) 491 struct snd_soc_dai *dai)
493{ 492{
494 struct snd_soc_pcm_runtime *rtd = substream->private_data; 493 struct snd_soc_pcm_runtime *rtd = substream->private_data;
495 struct snd_soc_device *socdev = rtd->socdev; 494 struct snd_soc_codec *codec = rtd->codec;
496 struct snd_soc_codec *codec = socdev->card->codec;
497 struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); 495 struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
498 u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; 496 u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
499 u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; 497 u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
@@ -573,8 +571,8 @@ static struct snd_soc_dai_ops wm8971_dai_ops = {
573 .set_sysclk = wm8971_set_dai_sysclk, 571 .set_sysclk = wm8971_set_dai_sysclk,
574}; 572};
575 573
576struct snd_soc_dai wm8971_dai = { 574static struct snd_soc_dai_driver wm8971_dai = {
577 .name = "WM8971", 575 .name = "wm8971-hifi",
578 .playback = { 576 .playback = {
579 .stream_name = "Playback", 577 .stream_name = "Playback",
580 .channels_min = 1, 578 .channels_min = 1,
@@ -589,7 +587,6 @@ struct snd_soc_dai wm8971_dai = {
589 .formats = WM8971_FORMATS,}, 587 .formats = WM8971_FORMATS,},
590 .ops = &wm8971_dai_ops, 588 .ops = &wm8971_dai_ops,
591}; 589};
592EXPORT_SYMBOL_GPL(wm8971_dai);
593 590
594static void wm8971_work(struct work_struct *work) 591static void wm8971_work(struct work_struct *work)
595{ 592{
@@ -598,19 +595,14 @@ static void wm8971_work(struct work_struct *work)
598 wm8971_set_bias_level(codec, codec->bias_level); 595 wm8971_set_bias_level(codec, codec->bias_level);
599} 596}
600 597
601static int wm8971_suspend(struct platform_device *pdev, pm_message_t state) 598static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
602{ 599{
603 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
604 struct snd_soc_codec *codec = socdev->card->codec;
605
606 wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); 600 wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
607 return 0; 601 return 0;
608} 602}
609 603
610static int wm8971_resume(struct platform_device *pdev) 604static int wm8971_resume(struct snd_soc_codec *codec)
611{ 605{
612 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
613 struct snd_soc_codec *codec = socdev->card->codec;
614 int i; 606 int i;
615 u8 data[2]; 607 u8 data[2];
616 u16 *cache = codec->reg_cache; 608 u16 *cache = codec->reg_cache;
@@ -639,37 +631,24 @@ static int wm8971_resume(struct platform_device *pdev)
639 return 0; 631 return 0;
640} 632}
641 633
642static int wm8971_init(struct snd_soc_device *socdev, 634static int wm8971_probe(struct snd_soc_codec *codec)
643 enum snd_soc_control_type control)
644{ 635{
645 struct snd_soc_codec *codec = socdev->card->codec; 636 struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
646 int reg, ret = 0; 637 int ret = 0;
647 638 u16 reg;
648 codec->name = "WM8971";
649 codec->owner = THIS_MODULE;
650 codec->set_bias_level = wm8971_set_bias_level;
651 codec->dai = &wm8971_dai;
652 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
653 codec->num_dai = 1;
654 codec->reg_cache = kmemdup(wm8971_reg, sizeof(wm8971_reg), GFP_KERNEL);
655
656 if (codec->reg_cache == NULL)
657 return -ENOMEM;
658 639
659 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 640 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);
660 if (ret < 0) { 641 if (ret < 0) {
661 printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); 642 printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
662 goto err; 643 return ret;
663 } 644 }
664 645
665 wm8971_reset(codec); 646 INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work);
647 wm8971_workq = create_workqueue("wm8971");
648 if (wm8971_workq == NULL)
649 return -ENOMEM;
666 650
667 /* register pcms */ 651 wm8971_reset(codec);
668 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
669 if (ret < 0) {
670 printk(KERN_ERR "wm8971: failed to create pcms\n");
671 goto err;
672 }
673 652
674 /* charge output caps - set vmid to 5k for quick power up */ 653 /* charge output caps - set vmid to 5k for quick power up */
675 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; 654 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
@@ -704,40 +683,54 @@ static int wm8971_init(struct snd_soc_device *socdev,
704 wm8971_add_widgets(codec); 683 wm8971_add_widgets(codec);
705 684
706 return ret; 685 return ret;
707
708err:
709 kfree(codec->reg_cache);
710 return ret;
711} 686}
712 687
713/* If the i2c layer weren't so broken, we could pass this kind of data
714 around */
715static struct snd_soc_device *wm8971_socdev;
716 688
717#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) 689/* power down chip */
690static int wm8971_remove(struct snd_soc_codec *codec)
691{
692 wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
693
694 if (wm8971_workq)
695 destroy_workqueue(wm8971_workq);
696 return 0;
697}
718 698
719static int wm8971_i2c_probe(struct i2c_client *i2c, 699static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
720 const struct i2c_device_id *id) 700 .probe = wm8971_probe,
701 .remove = wm8971_remove,
702 .suspend = wm8971_suspend,
703 .resume = wm8971_resume,
704 .set_bias_level = wm8971_set_bias_level,
705 .reg_cache_size = ARRAY_SIZE(wm8971_reg),
706 .reg_word_size = sizeof(u16),
707 .reg_cache_default = wm8971_reg,
708};
709
710#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
711static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
712 const struct i2c_device_id *id)
721{ 713{
722 struct snd_soc_device *socdev = wm8971_socdev; 714 struct wm8971_priv *wm8971;
723 struct snd_soc_codec *codec = socdev->card->codec;
724 int ret; 715 int ret;
725 716
726 i2c_set_clientdata(i2c, codec); 717 wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
718 if (wm8971 == NULL)
719 return -ENOMEM;
727 720
728 codec->control_data = i2c; 721 i2c_set_clientdata(i2c, wm8971);
729 722
730 ret = wm8971_init(socdev, SND_SOC_I2C); 723 ret = snd_soc_register_codec(&i2c->dev,
724 &soc_codec_dev_wm8971, &wm8971_dai, 1);
731 if (ret < 0) 725 if (ret < 0)
732 pr_err("failed to initialise WM8971\n"); 726 kfree(wm8971);
733
734 return ret; 727 return ret;
735} 728}
736 729
737static int wm8971_i2c_remove(struct i2c_client *client) 730static __devexit int wm8971_i2c_remove(struct i2c_client *client)
738{ 731{
739 struct snd_soc_codec *codec = i2c_get_clientdata(client); 732 snd_soc_unregister_codec(&client->dev);
740 kfree(codec->reg_cache); 733 kfree(i2c_get_clientdata(client));
741 return 0; 734 return 0;
742} 735}
743 736
@@ -749,148 +742,34 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);
749 742
750static struct i2c_driver wm8971_i2c_driver = { 743static struct i2c_driver wm8971_i2c_driver = {
751 .driver = { 744 .driver = {
752 .name = "WM8971 I2C Codec", 745 .name = "wm8971-codec",
753 .owner = THIS_MODULE, 746 .owner = THIS_MODULE,
754 }, 747 },
755 .probe = wm8971_i2c_probe, 748 .probe = wm8971_i2c_probe,
756 .remove = wm8971_i2c_remove, 749 .remove = __devexit_p(wm8971_i2c_remove),
757 .id_table = wm8971_i2c_id, 750 .id_table = wm8971_i2c_id,
758}; 751};
759
760static int wm8971_add_i2c_device(struct platform_device *pdev,
761 const struct wm8971_setup_data *setup)
762{
763 struct i2c_board_info info;
764 struct i2c_adapter *adapter;
765 struct i2c_client *client;
766 int ret;
767
768 ret = i2c_add_driver(&wm8971_i2c_driver);
769 if (ret != 0) {
770 dev_err(&pdev->dev, "can't add i2c driver\n");
771 return ret;
772 }
773
774 memset(&info, 0, sizeof(struct i2c_board_info));
775 info.addr = setup->i2c_address;
776 strlcpy(info.type, "wm8971", I2C_NAME_SIZE);
777
778 adapter = i2c_get_adapter(setup->i2c_bus);
779 if (!adapter) {
780 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
781 setup->i2c_bus);
782 goto err_driver;
783 }
784
785 client = i2c_new_device(adapter, &info);
786 i2c_put_adapter(adapter);
787 if (!client) {
788 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
789 (unsigned int)info.addr);
790 goto err_driver;
791 }
792
793 return 0;
794
795err_driver:
796 i2c_del_driver(&wm8971_i2c_driver);
797 return -ENODEV;
798}
799
800#endif 752#endif
801 753
802static int wm8971_probe(struct platform_device *pdev) 754static int __init wm8971_modinit(void)
803{ 755{
804 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
805 struct wm8971_setup_data *setup;
806 struct snd_soc_codec *codec;
807 struct wm8971_priv *wm8971;
808 int ret = 0; 756 int ret = 0;
809 757#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
810 pr_info("WM8971 Audio Codec %s", WM8971_VERSION); 758 ret = i2c_add_driver(&wm8971_i2c_driver);
811
812 setup = socdev->codec_data;
813 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
814 if (codec == NULL)
815 return -ENOMEM;
816
817 wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
818 if (wm8971 == NULL) {
819 kfree(codec);
820 return -ENOMEM;
821 }
822
823 snd_soc_codec_set_drvdata(codec, wm8971);
824 socdev->card->codec = codec;
825 mutex_init(&codec->mutex);
826 INIT_LIST_HEAD(&codec->dapm_widgets);
827 INIT_LIST_HEAD(&codec->dapm_paths);
828 wm8971_socdev = socdev;
829
830 INIT_DELAYED_WORK(&codec->delayed_work, wm8971_work);
831 wm8971_workq = create_workqueue("wm8971");
832 if (wm8971_workq == NULL) {
833 kfree(snd_soc_codec_get_drvdata(codec));
834 kfree(codec);
835 return -ENOMEM;
836 }
837
838#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
839 if (setup->i2c_address) {
840 ret = wm8971_add_i2c_device(pdev, setup);
841 }
842#endif
843 /* Add other interfaces here */
844
845 if (ret != 0) { 759 if (ret != 0) {
846 destroy_workqueue(wm8971_workq); 760 printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n",
847 kfree(snd_soc_codec_get_drvdata(codec)); 761 ret);
848 kfree(codec);
849 } 762 }
850
851 return ret;
852}
853
854/* power down chip */
855static int wm8971_remove(struct platform_device *pdev)
856{
857 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
858 struct snd_soc_codec *codec = socdev->card->codec;
859
860 if (codec->control_data)
861 wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
862 if (wm8971_workq)
863 destroy_workqueue(wm8971_workq);
864 snd_soc_free_pcms(socdev);
865 snd_soc_dapm_free(socdev);
866#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
867 i2c_unregister_device(codec->control_data);
868 i2c_del_driver(&wm8971_i2c_driver);
869#endif 763#endif
870 kfree(snd_soc_codec_get_drvdata(codec)); 764 return ret;
871 kfree(codec);
872
873 return 0;
874}
875
876struct snd_soc_codec_device soc_codec_dev_wm8971 = {
877 .probe = wm8971_probe,
878 .remove = wm8971_remove,
879 .suspend = wm8971_suspend,
880 .resume = wm8971_resume,
881};
882
883EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
884
885static int __init wm8971_modinit(void)
886{
887 return snd_soc_register_dai(&wm8971_dai);
888} 765}
889module_init(wm8971_modinit); 766module_init(wm8971_modinit);
890 767
891static void __exit wm8971_exit(void) 768static void __exit wm8971_exit(void)
892{ 769{
893 snd_soc_unregister_dai(&wm8971_dai); 770#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
771 i2c_del_driver(&wm8971_i2c_driver);
772#endif
894} 773}
895module_exit(wm8971_exit); 774module_exit(wm8971_exit);
896 775
diff --git a/sound/soc/codecs/wm8971.h b/sound/soc/codecs/wm8971.h
index ef4f08f9f344..f31c38fddfc4 100644
--- a/sound/soc/codecs/wm8971.h
+++ b/sound/soc/codecs/wm8971.h
@@ -53,12 +53,4 @@
53 53
54#define WM8971_SYSCLK 0 54#define WM8971_SYSCLK 0
55 55
56struct wm8971_setup_data {
57 int i2c_bus;
58 unsigned short i2c_address;
59};
60
61extern struct snd_soc_dai wm8971_dai;
62extern struct snd_soc_codec_device soc_codec_dev_wm8971;
63
64#endif 56#endif
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 1468fe10cbbe..b4363f6d19b3 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -51,12 +51,10 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
51#define WM8974_POWER1_BUFIOEN 0x04 51#define WM8974_POWER1_BUFIOEN 0x04
52 52
53struct wm8974_priv { 53struct wm8974_priv {
54 struct snd_soc_codec codec; 54 enum snd_soc_control_type control_type;
55 u16 reg_cache[WM8974_CACHEREGNUM]; 55 u16 reg_cache[WM8974_CACHEREGNUM];
56}; 56};
57 57
58static struct snd_soc_codec *wm8974_codec;
59
60#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) 58#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0)
61 59
62static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; 60static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
@@ -566,8 +564,8 @@ static struct snd_soc_dai_ops wm8974_ops = {
566 .set_pll = wm8974_set_dai_pll, 564 .set_pll = wm8974_set_dai_pll,
567}; 565};
568 566
569struct snd_soc_dai wm8974_dai = { 567static struct snd_soc_dai_driver wm8974_dai = {
570 .name = "WM8974 HiFi", 568 .name = "wm8974-hifi",
571 .playback = { 569 .playback = {
572 .stream_name = "Playback", 570 .stream_name = "Playback",
573 .channels_min = 1, 571 .channels_min = 1,
@@ -583,21 +581,15 @@ struct snd_soc_dai wm8974_dai = {
583 .ops = &wm8974_ops, 581 .ops = &wm8974_ops,
584 .symmetric_rates = 1, 582 .symmetric_rates = 1,
585}; 583};
586EXPORT_SYMBOL_GPL(wm8974_dai);
587 584
588static int wm8974_suspend(struct platform_device *pdev, pm_message_t state) 585static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
589{ 586{
590 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
591 struct snd_soc_codec *codec = socdev->card->codec;
592
593 wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); 587 wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
594 return 0; 588 return 0;
595} 589}
596 590
597static int wm8974_resume(struct platform_device *pdev) 591static int wm8974_resume(struct snd_soc_codec *codec)
598{ 592{
599 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
600 struct snd_soc_codec *codec = socdev->card->codec;
601 int i; 593 int i;
602 u8 data[2]; 594 u8 data[2];
603 u16 *cache = codec->reg_cache; 595 u16 *cache = codec->reg_cache;
@@ -613,156 +605,72 @@ static int wm8974_resume(struct platform_device *pdev)
613 return 0; 605 return 0;
614} 606}
615 607
616static int wm8974_probe(struct platform_device *pdev) 608static int wm8974_probe(struct snd_soc_codec *codec)
617{ 609{
618 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
619 struct snd_soc_codec *codec;
620 int ret = 0; 610 int ret = 0;
621 611
622 if (wm8974_codec == NULL) { 612 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
623 dev_err(&pdev->dev, "Codec device not registered\n"); 613 if (ret < 0) {
624 return -ENODEV; 614 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
615 return ret;
625 } 616 }
626 617
627 socdev->card->codec = wm8974_codec; 618 ret = wm8974_reset(codec);
628 codec = wm8974_codec;
629
630 /* register pcms */
631 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
632 if (ret < 0) { 619 if (ret < 0) {
633 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 620 dev_err(codec->dev, "Failed to issue reset\n");
634 goto pcm_err; 621 return ret;
635 } 622 }
636 623
624 wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
637 snd_soc_add_controls(codec, wm8974_snd_controls, 625 snd_soc_add_controls(codec, wm8974_snd_controls,
638 ARRAY_SIZE(wm8974_snd_controls)); 626 ARRAY_SIZE(wm8974_snd_controls));
639 wm8974_add_widgets(codec); 627 wm8974_add_widgets(codec);
640 628
641 return ret; 629 return ret;
642
643pcm_err:
644 return ret;
645} 630}
646 631
647/* power down chip */ 632/* power down chip */
648static int wm8974_remove(struct platform_device *pdev) 633static int wm8974_remove(struct snd_soc_codec *codec)
649{ 634{
650 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 635 wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
651
652 snd_soc_free_pcms(socdev);
653 snd_soc_dapm_free(socdev);
654
655 return 0; 636 return 0;
656} 637}
657 638
658struct snd_soc_codec_device soc_codec_dev_wm8974 = { 639static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
659 .probe = wm8974_probe, 640 .probe = wm8974_probe,
660 .remove = wm8974_remove, 641 .remove = wm8974_remove,
661 .suspend = wm8974_suspend, 642 .suspend = wm8974_suspend,
662 .resume = wm8974_resume, 643 .resume = wm8974_resume,
644 .set_bias_level = wm8974_set_bias_level,
645 .reg_cache_size = ARRAY_SIZE(wm8974_reg),
646 .reg_word_size = sizeof(u16),
647 .reg_cache_default = wm8974_reg,
663}; 648};
664EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974);
665
666static __devinit int wm8974_register(struct wm8974_priv *wm8974)
667{
668 int ret;
669 struct snd_soc_codec *codec = &wm8974->codec;
670
671 if (wm8974_codec) {
672 dev_err(codec->dev, "Another WM8974 is registered\n");
673 ret = -EINVAL;
674 goto err;
675 }
676
677 mutex_init(&codec->mutex);
678 INIT_LIST_HEAD(&codec->dapm_widgets);
679 INIT_LIST_HEAD(&codec->dapm_paths);
680
681 snd_soc_codec_set_drvdata(codec, wm8974);
682 codec->name = "WM8974";
683 codec->owner = THIS_MODULE;
684 codec->bias_level = SND_SOC_BIAS_OFF;
685 codec->set_bias_level = wm8974_set_bias_level;
686 codec->dai = &wm8974_dai;
687 codec->num_dai = 1;
688 codec->reg_cache_size = WM8974_CACHEREGNUM;
689 codec->reg_cache = &wm8974->reg_cache;
690
691 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
692 if (ret < 0) {
693 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
694 goto err;
695 }
696
697 memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg));
698
699 ret = wm8974_reset(codec);
700 if (ret < 0) {
701 dev_err(codec->dev, "Failed to issue reset\n");
702 goto err;
703 }
704
705 wm8974_dai.dev = codec->dev;
706
707 wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
708
709 wm8974_codec = codec;
710
711 ret = snd_soc_register_codec(codec);
712 if (ret != 0) {
713 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
714 goto err;
715 }
716
717 ret = snd_soc_register_dai(&wm8974_dai);
718 if (ret != 0) {
719 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
720 goto err_codec;
721 }
722
723 return 0;
724
725err_codec:
726 snd_soc_unregister_codec(codec);
727err:
728 kfree(wm8974);
729 return ret;
730}
731
732static __devexit void wm8974_unregister(struct wm8974_priv *wm8974)
733{
734 wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF);
735 snd_soc_unregister_dai(&wm8974_dai);
736 snd_soc_unregister_codec(&wm8974->codec);
737 kfree(wm8974);
738 wm8974_codec = NULL;
739}
740 649
650#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
741static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, 651static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
742 const struct i2c_device_id *id) 652 const struct i2c_device_id *id)
743{ 653{
744 struct wm8974_priv *wm8974; 654 struct wm8974_priv *wm8974;
745 struct snd_soc_codec *codec; 655 int ret;
746 656
747 wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL); 657 wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);
748 if (wm8974 == NULL) 658 if (wm8974 == NULL)
749 return -ENOMEM; 659 return -ENOMEM;
750 660
751 codec = &wm8974->codec;
752 codec->hw_write = (hw_write_t)i2c_master_send;
753
754 i2c_set_clientdata(i2c, wm8974); 661 i2c_set_clientdata(i2c, wm8974);
755 codec->control_data = i2c;
756
757 codec->dev = &i2c->dev;
758 662
759 return wm8974_register(wm8974); 663 ret = snd_soc_register_codec(&i2c->dev,
664 &soc_codec_dev_wm8974, &wm8974_dai, 1);
665 if (ret < 0)
666 kfree(wm8974);
667 return ret;
760} 668}
761 669
762static __devexit int wm8974_i2c_remove(struct i2c_client *client) 670static __devexit int wm8974_i2c_remove(struct i2c_client *client)
763{ 671{
764 struct wm8974_priv *wm8974 = i2c_get_clientdata(client); 672 snd_soc_unregister_codec(&client->dev);
765 wm8974_unregister(wm8974); 673 kfree(i2c_get_clientdata(client));
766 return 0; 674 return 0;
767} 675}
768 676
@@ -774,23 +682,34 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
774 682
775static struct i2c_driver wm8974_i2c_driver = { 683static struct i2c_driver wm8974_i2c_driver = {
776 .driver = { 684 .driver = {
777 .name = "WM8974", 685 .name = "wm8974-codec",
778 .owner = THIS_MODULE, 686 .owner = THIS_MODULE,
779 }, 687 },
780 .probe = wm8974_i2c_probe, 688 .probe = wm8974_i2c_probe,
781 .remove = __devexit_p(wm8974_i2c_remove), 689 .remove = __devexit_p(wm8974_i2c_remove),
782 .id_table = wm8974_i2c_id, 690 .id_table = wm8974_i2c_id,
783}; 691};
692#endif
784 693
785static int __init wm8974_modinit(void) 694static int __init wm8974_modinit(void)
786{ 695{
787 return i2c_add_driver(&wm8974_i2c_driver); 696 int ret = 0;
697#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
698 ret = i2c_add_driver(&wm8974_i2c_driver);
699 if (ret != 0) {
700 printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n",
701 ret);
702 }
703#endif
704 return ret;
788} 705}
789module_init(wm8974_modinit); 706module_init(wm8974_modinit);
790 707
791static void __exit wm8974_exit(void) 708static void __exit wm8974_exit(void)
792{ 709{
710#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
793 i2c_del_driver(&wm8974_i2c_driver); 711 i2c_del_driver(&wm8974_i2c_driver);
712#endif
794} 713}
795module_exit(wm8974_exit); 714module_exit(wm8974_exit);
796 715
diff --git a/sound/soc/codecs/wm8974.h b/sound/soc/codecs/wm8974.h
index 896a7f0f3fc4..3c94e7bb55a6 100644
--- a/sound/soc/codecs/wm8974.h
+++ b/sound/soc/codecs/wm8974.h
@@ -83,7 +83,4 @@
83#define WM8974_MCLKDIV_8 (6 << 5) 83#define WM8974_MCLKDIV_8 (6 << 5)
84#define WM8974_MCLKDIV_12 (7 << 5) 84#define WM8974_MCLKDIV_12 (7 << 5)
85 85
86extern struct snd_soc_dai wm8974_dai;
87extern struct snd_soc_codec_device soc_codec_dev_wm8974;
88
89#endif 86#endif
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 8a1ad778e7e3..13b979a71a7c 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -31,8 +31,6 @@
31 31
32#include "wm8978.h" 32#include "wm8978.h"
33 33
34static struct snd_soc_codec *wm8978_codec;
35
36/* wm8978 register cache. Note that register 0 is not included in the cache. */ 34/* wm8978 register cache. Note that register 0 is not included in the cache. */
37static const u16 wm8978_reg[WM8978_CACHEREGNUM] = { 35static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
38 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */ 36 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */
@@ -54,7 +52,8 @@ static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
54 52
55/* codec private data */ 53/* codec private data */
56struct wm8978_priv { 54struct wm8978_priv {
57 struct snd_soc_codec codec; 55 enum snd_soc_control_type control_type;
56 void *control_data;
58 unsigned int f_pllout; 57 unsigned int f_pllout;
59 unsigned int f_mclk; 58 unsigned int f_mclk;
60 unsigned int f_256fs; 59 unsigned int f_256fs;
@@ -374,8 +373,8 @@ struct wm8978_pll_div {
374 373
375#define FIXED_PLL_SIZE (1 << 24) 374#define FIXED_PLL_SIZE (1 << 24)
376 375
377static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target, 376static void pll_factors(struct snd_soc_codec *codec,
378 unsigned int source) 377 struct wm8978_pll_div *pll_div, unsigned int target, unsigned int source)
379{ 378{
380 u64 k_part; 379 u64 k_part;
381 unsigned int k, n_div, n_mod; 380 unsigned int k, n_div, n_mod;
@@ -390,7 +389,7 @@ static void pll_factors(struct wm8978_pll_div *pll_div, unsigned int target,
390 } 389 }
391 390
392 if (n_div < 6 || n_div > 12) 391 if (n_div < 6 || n_div > 12)
393 dev_warn(wm8978_codec->dev, 392 dev_warn(codec->dev,
394 "WM8978 N value exceeds recommended range! N = %u\n", 393 "WM8978 N value exceeds recommended range! N = %u\n",
395 n_div); 394 n_div);
396 395
@@ -505,7 +504,7 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec)
505 dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__, 504 dev_dbg(codec->dev, "%s: f_MCLK=%uHz, f_PLLOUT=%uHz\n", __func__,
506 wm8978->f_mclk, wm8978->f_pllout); 505 wm8978->f_mclk, wm8978->f_pllout);
507 506
508 pll_factors(&pll_div, f2, wm8978->f_mclk); 507 pll_factors(codec, &pll_div, f2, wm8978->f_mclk);
509 508
510 dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n", 509 dev_dbg(codec->dev, "%s: calculated PLL N=0x%x, K=0x%x, div2=%d\n",
511 __func__, pll_div.n, pll_div.k, pll_div.div2); 510 __func__, pll_div.n, pll_div.k, pll_div.div2);
@@ -690,8 +689,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
690 struct snd_soc_dai *dai) 689 struct snd_soc_dai *dai)
691{ 690{
692 struct snd_soc_pcm_runtime *rtd = substream->private_data; 691 struct snd_soc_pcm_runtime *rtd = substream->private_data;
693 struct snd_soc_device *socdev = rtd->socdev; 692 struct snd_soc_codec *codec = rtd->codec;
694 struct snd_soc_codec *codec = socdev->card->codec;
695 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); 693 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
696 /* Word length mask = 0x60 */ 694 /* Word length mask = 0x60 */
697 u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60; 695 u16 iface_ctl = snd_soc_read(codec, WM8978_AUDIO_INTERFACE) & ~0x60;
@@ -875,9 +873,8 @@ static struct snd_soc_dai_ops wm8978_dai_ops = {
875}; 873};
876 874
877/* Also supports 12kHz */ 875/* Also supports 12kHz */
878struct snd_soc_dai wm8978_dai = { 876static struct snd_soc_dai_driver wm8978_dai = {
879 .name = "WM8978 HiFi", 877 .name = "wm8978-hifi",
880 .id = 1,
881 .playback = { 878 .playback = {
882 .stream_name = "Playback", 879 .stream_name = "Playback",
883 .channels_min = 1, 880 .channels_min = 1,
@@ -894,13 +891,9 @@ struct snd_soc_dai wm8978_dai = {
894 }, 891 },
895 .ops = &wm8978_dai_ops, 892 .ops = &wm8978_dai_ops,
896}; 893};
897EXPORT_SYMBOL_GPL(wm8978_dai);
898 894
899static int wm8978_suspend(struct platform_device *pdev, pm_message_t state) 895static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state)
900{ 896{
901 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
902 struct snd_soc_codec *codec = socdev->card->codec;
903
904 wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF); 897 wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
905 /* Also switch PLL off */ 898 /* Also switch PLL off */
906 snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0); 899 snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0);
@@ -908,10 +901,8 @@ static int wm8978_suspend(struct platform_device *pdev, pm_message_t state)
908 return 0; 901 return 0;
909} 902}
910 903
911static int wm8978_resume(struct platform_device *pdev) 904static int wm8978_resume(struct snd_soc_codec *codec)
912{ 905{
913 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
914 struct snd_soc_codec *codec = socdev->card->codec;
915 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec); 906 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
916 int i; 907 int i;
917 u16 *cache = codec->reg_cache; 908 u16 *cache = codec->reg_cache;
@@ -933,54 +924,6 @@ static int wm8978_resume(struct platform_device *pdev)
933 return 0; 924 return 0;
934} 925}
935 926
936static int wm8978_probe(struct platform_device *pdev)
937{
938 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
939 struct snd_soc_codec *codec;
940 int ret = 0;
941
942 if (wm8978_codec == NULL) {
943 dev_err(&pdev->dev, "Codec device not registered\n");
944 return -ENODEV;
945 }
946
947 socdev->card->codec = wm8978_codec;
948 codec = wm8978_codec;
949
950 /* register pcms */
951 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
952 if (ret < 0) {
953 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
954 goto pcm_err;
955 }
956
957 snd_soc_add_controls(codec, wm8978_snd_controls,
958 ARRAY_SIZE(wm8978_snd_controls));
959 wm8978_add_widgets(codec);
960
961pcm_err:
962 return ret;
963}
964
965/* power down chip */
966static int wm8978_remove(struct platform_device *pdev)
967{
968 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
969
970 snd_soc_free_pcms(socdev);
971 snd_soc_dapm_free(socdev);
972
973 return 0;
974}
975
976struct snd_soc_codec_device soc_codec_dev_wm8978 = {
977 .probe = wm8978_probe,
978 .remove = wm8978_remove,
979 .suspend = wm8978_suspend,
980 .resume = wm8978_resume,
981};
982EXPORT_SYMBOL_GPL(soc_codec_dev_wm8978);
983
984/* 927/*
985 * These registers contain an "update" bit - bit 8. This means, for example, 928 * These registers contain an "update" bit - bit 8. This means, for example,
986 * that one can write new DAC digital volume for both channels, but only when 929 * that one can write new DAC digital volume for both channels, but only when
@@ -1000,44 +943,23 @@ static const int update_reg[] = {
1000 WM8978_ROUT2_SPK_CONTROL, 943 WM8978_ROUT2_SPK_CONTROL,
1001}; 944};
1002 945
1003static __devinit int wm8978_register(struct wm8978_priv *wm8978) 946static int wm8978_probe(struct snd_soc_codec *codec)
1004{ 947{
1005 int ret, i; 948 struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
1006 struct snd_soc_codec *codec = &wm8978->codec; 949 int ret = 0, i;
1007
1008 if (wm8978_codec) {
1009 dev_err(codec->dev, "Another WM8978 is registered\n");
1010 return -EINVAL;
1011 }
1012 950
1013 /* 951 /*
1014 * Set default system clock to PLL, it is more precise, this is also the 952 * Set default system clock to PLL, it is more precise, this is also the
1015 * default hardware setting 953 * default hardware setting
1016 */ 954 */
1017 wm8978->sysclk = WM8978_PLL; 955 wm8978->sysclk = WM8978_PLL;
1018 956 codec->control_data = wm8978->control_data;
1019 mutex_init(&codec->mutex);
1020 INIT_LIST_HEAD(&codec->dapm_widgets);
1021 INIT_LIST_HEAD(&codec->dapm_paths);
1022
1023 snd_soc_codec_set_drvdata(codec, wm8978);
1024 codec->name = "WM8978";
1025 codec->owner = THIS_MODULE;
1026 codec->bias_level = SND_SOC_BIAS_OFF;
1027 codec->set_bias_level = wm8978_set_bias_level;
1028 codec->dai = &wm8978_dai;
1029 codec->num_dai = 1;
1030 codec->reg_cache_size = WM8978_CACHEREGNUM;
1031 codec->reg_cache = &wm8978->reg_cache;
1032
1033 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); 957 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
1034 if (ret < 0) { 958 if (ret < 0) {
1035 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 959 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1036 goto err; 960 return ret;
1037 } 961 }
1038 962
1039 memcpy(codec->reg_cache, wm8978_reg, sizeof(wm8978_reg));
1040
1041 /* 963 /*
1042 * Set the update bit in all registers, that have one. This way all 964 * Set the update bit in all registers, that have one. This way all
1043 * writes to those registers will also cause the update bit to be 965 * writes to those registers will also cause the update bit to be
@@ -1050,74 +972,61 @@ static __devinit int wm8978_register(struct wm8978_priv *wm8978)
1050 ret = snd_soc_write(codec, WM8978_RESET, 0); 972 ret = snd_soc_write(codec, WM8978_RESET, 0);
1051 if (ret < 0) { 973 if (ret < 0) {
1052 dev_err(codec->dev, "Failed to issue reset\n"); 974 dev_err(codec->dev, "Failed to issue reset\n");
1053 goto err; 975 return ret;
1054 } 976 }
1055 977
1056 wm8978_dai.dev = codec->dev;
1057
1058 wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 978 wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1059 979
1060 wm8978_codec = codec; 980 snd_soc_add_controls(codec, wm8978_snd_controls,
1061 981 ARRAY_SIZE(wm8978_snd_controls));
1062 ret = snd_soc_register_codec(codec); 982 wm8978_add_widgets(codec);
1063 if (ret != 0) {
1064 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1065 goto err;
1066 }
1067
1068 ret = snd_soc_register_dai(&wm8978_dai);
1069 if (ret != 0) {
1070 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1071 goto err_codec;
1072 }
1073 983
1074 return 0; 984 return 0;
1075
1076err_codec:
1077 snd_soc_unregister_codec(codec);
1078err:
1079 return ret;
1080} 985}
1081 986
1082static __devexit void wm8978_unregister(struct wm8978_priv *wm8978) 987/* power down chip */
988static int wm8978_remove(struct snd_soc_codec *codec)
1083{ 989{
1084 wm8978_set_bias_level(&wm8978->codec, SND_SOC_BIAS_OFF); 990 wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
1085 snd_soc_unregister_dai(&wm8978_dai); 991 return 0;
1086 snd_soc_unregister_codec(&wm8978->codec);
1087 wm8978_codec = NULL;
1088} 992}
1089 993
994static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
995 .probe = wm8978_probe,
996 .remove = wm8978_remove,
997 .suspend = wm8978_suspend,
998 .resume = wm8978_resume,
999 .set_bias_level = wm8978_set_bias_level,
1000 .reg_cache_size = ARRAY_SIZE(wm8978_reg),
1001 .reg_word_size = sizeof(u16),
1002 .reg_cache_default = wm8978_reg,
1003};
1004
1005#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1090static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, 1006static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
1091 const struct i2c_device_id *id) 1007 const struct i2c_device_id *id)
1092{ 1008{
1093 int ret;
1094 struct wm8978_priv *wm8978; 1009 struct wm8978_priv *wm8978;
1095 struct snd_soc_codec *codec; 1010 int ret;
1096 1011
1097 wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL); 1012 wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL);
1098 if (wm8978 == NULL) 1013 if (wm8978 == NULL)
1099 return -ENOMEM; 1014 return -ENOMEM;
1100 1015
1101 codec = &wm8978->codec;
1102 codec->hw_write = (hw_write_t)i2c_master_send;
1103
1104 i2c_set_clientdata(i2c, wm8978); 1016 i2c_set_clientdata(i2c, wm8978);
1105 codec->control_data = i2c; 1017 wm8978->control_data = i2c;
1106
1107 codec->dev = &i2c->dev;
1108 1018
1109 ret = wm8978_register(wm8978); 1019 ret = snd_soc_register_codec(&i2c->dev,
1020 &soc_codec_dev_wm8978, &wm8978_dai, 1);
1110 if (ret < 0) 1021 if (ret < 0)
1111 kfree(wm8978); 1022 kfree(wm8978);
1112
1113 return ret; 1023 return ret;
1114} 1024}
1115 1025
1116static __devexit int wm8978_i2c_remove(struct i2c_client *client) 1026static __devexit int wm8978_i2c_remove(struct i2c_client *client)
1117{ 1027{
1118 struct wm8978_priv *wm8978 = i2c_get_clientdata(client); 1028 snd_soc_unregister_codec(&client->dev);
1119 wm8978_unregister(wm8978); 1029 kfree(i2c_get_clientdata(client));
1120 kfree(wm8978);
1121 return 0; 1030 return 0;
1122} 1031}
1123 1032
@@ -1129,23 +1038,34 @@ MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id);
1129 1038
1130static struct i2c_driver wm8978_i2c_driver = { 1039static struct i2c_driver wm8978_i2c_driver = {
1131 .driver = { 1040 .driver = {
1132 .name = "WM8978", 1041 .name = "wm8978",
1133 .owner = THIS_MODULE, 1042 .owner = THIS_MODULE,
1134 }, 1043 },
1135 .probe = wm8978_i2c_probe, 1044 .probe = wm8978_i2c_probe,
1136 .remove = __devexit_p(wm8978_i2c_remove), 1045 .remove = __devexit_p(wm8978_i2c_remove),
1137 .id_table = wm8978_i2c_id, 1046 .id_table = wm8978_i2c_id,
1138}; 1047};
1048#endif
1139 1049
1140static int __init wm8978_modinit(void) 1050static int __init wm8978_modinit(void)
1141{ 1051{
1142 return i2c_add_driver(&wm8978_i2c_driver); 1052 int ret = 0;
1053#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1054 ret = i2c_add_driver(&wm8978_i2c_driver);
1055 if (ret != 0) {
1056 printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n",
1057 ret);
1058 }
1059#endif
1060 return ret;
1143} 1061}
1144module_init(wm8978_modinit); 1062module_init(wm8978_modinit);
1145 1063
1146static void __exit wm8978_exit(void) 1064static void __exit wm8978_exit(void)
1147{ 1065{
1066#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1148 i2c_del_driver(&wm8978_i2c_driver); 1067 i2c_del_driver(&wm8978_i2c_driver);
1068#endif
1149} 1069}
1150module_exit(wm8978_exit); 1070module_exit(wm8978_exit);
1151 1071
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h
index 56ec83270917..c75525b7f154 100644
--- a/sound/soc/codecs/wm8978.h
+++ b/sound/soc/codecs/wm8978.h
@@ -80,7 +80,4 @@ enum wm8978_sysclk_src {
80 WM8978_MCLK 80 WM8978_MCLK
81}; 81};
82 82
83extern struct snd_soc_dai wm8978_dai;
84extern struct snd_soc_codec_device soc_codec_dev_wm8978;
85
86#endif /* __WM8978_H__ */ 83#endif /* __WM8978_H__ */
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
new file mode 100644
index 000000000000..fd2e7cca1228
--- /dev/null
+++ b/sound/soc/codecs/wm8985.c
@@ -0,0 +1,1192 @@
1/*
2 * wm8985.c -- WM8985 ALSA SoC Audio driver
3 *
4 * Copyright 2010 Wolfson Microelectronics plc
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * TODO:
13 * o Add OUT3/OUT4 mixer controls.
14 */
15
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/init.h>
19#include <linux/delay.h>
20#include <linux/pm.h>
21#include <linux/i2c.h>
22#include <linux/regulator/consumer.h>
23#include <linux/spi/spi.h>
24#include <linux/slab.h>
25#include <sound/core.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30#include <sound/initval.h>
31#include <sound/tlv.h>
32
33#include "wm8985.h"
34
35#define WM8985_NUM_SUPPLIES 4
36static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = {
37 "DCVDD",
38 "DBVDD",
39 "AVDD1",
40 "AVDD2"
41};
42
43static const u16 wm8985_reg_defs[] = {
44 0x0000, /* R0 - Software Reset */
45 0x0000, /* R1 - Power management 1 */
46 0x0000, /* R2 - Power management 2 */
47 0x0000, /* R3 - Power management 3 */
48 0x0050, /* R4 - Audio Interface */
49 0x0000, /* R5 - Companding control */
50 0x0140, /* R6 - Clock Gen control */
51 0x0000, /* R7 - Additional control */
52 0x0000, /* R8 - GPIO Control */
53 0x0000, /* R9 - Jack Detect Control 1 */
54 0x0000, /* R10 - DAC Control */
55 0x00FF, /* R11 - Left DAC digital Vol */
56 0x00FF, /* R12 - Right DAC digital vol */
57 0x0000, /* R13 - Jack Detect Control 2 */
58 0x0100, /* R14 - ADC Control */
59 0x00FF, /* R15 - Left ADC Digital Vol */
60 0x00FF, /* R16 - Right ADC Digital Vol */
61 0x0000, /* R17 */
62 0x012C, /* R18 - EQ1 - low shelf */
63 0x002C, /* R19 - EQ2 - peak 1 */
64 0x002C, /* R20 - EQ3 - peak 2 */
65 0x002C, /* R21 - EQ4 - peak 3 */
66 0x002C, /* R22 - EQ5 - high shelf */
67 0x0000, /* R23 */
68 0x0032, /* R24 - DAC Limiter 1 */
69 0x0000, /* R25 - DAC Limiter 2 */
70 0x0000, /* R26 */
71 0x0000, /* R27 - Notch Filter 1 */
72 0x0000, /* R28 - Notch Filter 2 */
73 0x0000, /* R29 - Notch Filter 3 */
74 0x0000, /* R30 - Notch Filter 4 */
75 0x0000, /* R31 */
76 0x0038, /* R32 - ALC control 1 */
77 0x000B, /* R33 - ALC control 2 */
78 0x0032, /* R34 - ALC control 3 */
79 0x0000, /* R35 - Noise Gate */
80 0x0008, /* R36 - PLL N */
81 0x000C, /* R37 - PLL K 1 */
82 0x0093, /* R38 - PLL K 2 */
83 0x00E9, /* R39 - PLL K 3 */
84 0x0000, /* R40 */
85 0x0000, /* R41 - 3D control */
86 0x0000, /* R42 - OUT4 to ADC */
87 0x0000, /* R43 - Beep control */
88 0x0033, /* R44 - Input ctrl */
89 0x0010, /* R45 - Left INP PGA gain ctrl */
90 0x0010, /* R46 - Right INP PGA gain ctrl */
91 0x0100, /* R47 - Left ADC BOOST ctrl */
92 0x0100, /* R48 - Right ADC BOOST ctrl */
93 0x0002, /* R49 - Output ctrl */
94 0x0001, /* R50 - Left mixer ctrl */
95 0x0001, /* R51 - Right mixer ctrl */
96 0x0039, /* R52 - LOUT1 (HP) volume ctrl */
97 0x0039, /* R53 - ROUT1 (HP) volume ctrl */
98 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */
99 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */
100 0x0001, /* R56 - OUT3 mixer ctrl */
101 0x0001, /* R57 - OUT4 (MONO) mix ctrl */
102 0x0001, /* R58 */
103 0x0000, /* R59 */
104 0x0004, /* R60 - OUTPUT ctrl */
105 0x0000, /* R61 - BIAS CTRL */
106 0x0180, /* R62 */
107 0x0000 /* R63 */
108};
109
110/*
111 * latch bit 8 of these registers to ensure instant
112 * volume updates
113 */
114static const int volume_update_regs[] = {
115 WM8985_LEFT_DAC_DIGITAL_VOL,
116 WM8985_RIGHT_DAC_DIGITAL_VOL,
117 WM8985_LEFT_ADC_DIGITAL_VOL,
118 WM8985_RIGHT_ADC_DIGITAL_VOL,
119 WM8985_LOUT2_SPK_VOLUME_CTRL,
120 WM8985_ROUT2_SPK_VOLUME_CTRL,
121 WM8985_LOUT1_HP_VOLUME_CTRL,
122 WM8985_ROUT1_HP_VOLUME_CTRL,
123 WM8985_LEFT_INP_PGA_GAIN_CTRL,
124 WM8985_RIGHT_INP_PGA_GAIN_CTRL
125};
126
127struct wm8985_priv {
128 enum snd_soc_control_type control_type;
129 struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES];
130 unsigned int sysclk;
131 unsigned int bclk;
132};
133
134static const struct {
135 int div;
136 int ratio;
137} fs_ratios[] = {
138 { 10, 128 },
139 { 15, 192 },
140 { 20, 256 },
141 { 30, 384 },
142 { 40, 512 },
143 { 60, 768 },
144 { 80, 1024 },
145 { 120, 1536 }
146};
147
148static const int srates[] = { 48000, 32000, 24000, 16000, 12000, 8000 };
149
150static const int bclk_divs[] = {
151 1, 2, 4, 8, 16, 32
152};
153
154static int eqmode_get(struct snd_kcontrol *kcontrol,
155 struct snd_ctl_elem_value *ucontrol);
156static int eqmode_put(struct snd_kcontrol *kcontrol,
157 struct snd_ctl_elem_value *ucontrol);
158
159static const DECLARE_TLV_DB_SCALE(dac_tlv, -12700, 50, 1);
160static const DECLARE_TLV_DB_SCALE(adc_tlv, -12700, 50, 1);
161static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
162static const DECLARE_TLV_DB_SCALE(lim_thresh_tlv, -600, 100, 0);
163static const DECLARE_TLV_DB_SCALE(lim_boost_tlv, 0, 100, 0);
164static const DECLARE_TLV_DB_SCALE(alc_min_tlv, -1200, 600, 0);
165static const DECLARE_TLV_DB_SCALE(alc_max_tlv, -675, 600, 0);
166static const DECLARE_TLV_DB_SCALE(alc_tar_tlv, -2250, 150, 0);
167static const DECLARE_TLV_DB_SCALE(pga_vol_tlv, -1200, 75, 0);
168static const DECLARE_TLV_DB_SCALE(boost_tlv, -1200, 300, 1);
169static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
170static const DECLARE_TLV_DB_SCALE(aux_tlv, -1500, 300, 0);
171static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
172static const DECLARE_TLV_DB_SCALE(pga_boost_tlv, 0, 2000, 0);
173
174static const char *alc_sel_text[] = { "Off", "Right", "Left", "Stereo" };
175static const SOC_ENUM_SINGLE_DECL(alc_sel, WM8985_ALC_CONTROL_1, 7,
176 alc_sel_text);
177
178static const char *alc_mode_text[] = { "ALC", "Limiter" };
179static const SOC_ENUM_SINGLE_DECL(alc_mode, WM8985_ALC_CONTROL_3, 8,
180 alc_mode_text);
181
182static const char *filter_mode_text[] = { "Audio", "Application" };
183static const SOC_ENUM_SINGLE_DECL(filter_mode, WM8985_ADC_CONTROL, 7,
184 filter_mode_text);
185
186static const char *eq_bw_text[] = { "Narrow", "Wide" };
187static const char *eqmode_text[] = { "Capture", "Playback" };
188static const SOC_ENUM_SINGLE_EXT_DECL(eqmode, eqmode_text);
189
190static const char *eq1_cutoff_text[] = {
191 "80Hz", "105Hz", "135Hz", "175Hz"
192};
193static const SOC_ENUM_SINGLE_DECL(eq1_cutoff, WM8985_EQ1_LOW_SHELF, 5,
194 eq1_cutoff_text);
195static const char *eq2_cutoff_text[] = {
196 "230Hz", "300Hz", "385Hz", "500Hz"
197};
198static const SOC_ENUM_SINGLE_DECL(eq2_bw, WM8985_EQ2_PEAK_1, 8, eq_bw_text);
199static const SOC_ENUM_SINGLE_DECL(eq2_cutoff, WM8985_EQ2_PEAK_1, 5,
200 eq2_cutoff_text);
201static const char *eq3_cutoff_text[] = {
202 "650Hz", "850Hz", "1.1kHz", "1.4kHz"
203};
204static const SOC_ENUM_SINGLE_DECL(eq3_bw, WM8985_EQ3_PEAK_2, 8, eq_bw_text);
205static const SOC_ENUM_SINGLE_DECL(eq3_cutoff, WM8985_EQ3_PEAK_2, 5,
206 eq3_cutoff_text);
207static const char *eq4_cutoff_text[] = {
208 "1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz"
209};
210static const SOC_ENUM_SINGLE_DECL(eq4_bw, WM8985_EQ4_PEAK_3, 8, eq_bw_text);
211static const SOC_ENUM_SINGLE_DECL(eq4_cutoff, WM8985_EQ4_PEAK_3, 5,
212 eq4_cutoff_text);
213static const char *eq5_cutoff_text[] = {
214 "5.3kHz", "6.9kHz", "9kHz", "11.7kHz"
215};
216static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8985_EQ5_HIGH_SHELF, 5,
217 eq5_cutoff_text);
218
219static const char *speaker_mode_text[] = { "Class A/B", "Class D" };
220static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
221
222static const char *depth_3d_text[] = {
223 "Off",
224 "6.67%",
225 "13.3%",
226 "20%",
227 "26.7%",
228 "33.3%",
229 "40%",
230 "46.6%",
231 "53.3%",
232 "60%",
233 "66.7%",
234 "73.3%",
235 "80%",
236 "86.7%",
237 "93.3%",
238 "100%"
239};
240static const SOC_ENUM_SINGLE_DECL(depth_3d, WM8985_3D_CONTROL, 0,
241 depth_3d_text);
242
243static const struct snd_kcontrol_new wm8985_snd_controls[] = {
244 SOC_SINGLE("Digital Loopback Switch", WM8985_COMPANDING_CONTROL,
245 0, 1, 0),
246
247 SOC_ENUM("ALC Capture Function", alc_sel),
248 SOC_SINGLE_TLV("ALC Capture Max Volume", WM8985_ALC_CONTROL_1,
249 3, 7, 0, alc_max_tlv),
250 SOC_SINGLE_TLV("ALC Capture Min Volume", WM8985_ALC_CONTROL_1,
251 0, 7, 0, alc_min_tlv),
252 SOC_SINGLE_TLV("ALC Capture Target Volume", WM8985_ALC_CONTROL_2,
253 0, 15, 0, alc_tar_tlv),
254 SOC_SINGLE("ALC Capture Attack", WM8985_ALC_CONTROL_3, 0, 10, 0),
255 SOC_SINGLE("ALC Capture Hold", WM8985_ALC_CONTROL_2, 4, 10, 0),
256 SOC_SINGLE("ALC Capture Decay", WM8985_ALC_CONTROL_3, 4, 10, 0),
257 SOC_ENUM("ALC Mode", alc_mode),
258 SOC_SINGLE("ALC Capture NG Switch", WM8985_NOISE_GATE,
259 3, 1, 0),
260 SOC_SINGLE("ALC Capture NG Threshold", WM8985_NOISE_GATE,
261 0, 7, 1),
262
263 SOC_DOUBLE_R_TLV("Capture Volume", WM8985_LEFT_ADC_DIGITAL_VOL,
264 WM8985_RIGHT_ADC_DIGITAL_VOL, 0, 255, 0, adc_tlv),
265 SOC_DOUBLE_R("Capture PGA ZC Switch", WM8985_LEFT_INP_PGA_GAIN_CTRL,
266 WM8985_RIGHT_INP_PGA_GAIN_CTRL, 7, 1, 0),
267 SOC_DOUBLE_R_TLV("Capture PGA Volume", WM8985_LEFT_INP_PGA_GAIN_CTRL,
268 WM8985_RIGHT_INP_PGA_GAIN_CTRL, 0, 63, 0, pga_vol_tlv),
269
270 SOC_DOUBLE_R_TLV("Capture PGA Boost Volume",
271 WM8985_LEFT_ADC_BOOST_CTRL, WM8985_RIGHT_ADC_BOOST_CTRL,
272 8, 1, 0, pga_boost_tlv),
273
274 SOC_DOUBLE("ADC Inversion Switch", WM8985_ADC_CONTROL, 0, 1, 1, 0),
275 SOC_SINGLE("ADC 128x Oversampling Switch", WM8985_ADC_CONTROL, 8, 1, 0),
276
277 SOC_DOUBLE_R_TLV("Playback Volume", WM8985_LEFT_DAC_DIGITAL_VOL,
278 WM8985_RIGHT_DAC_DIGITAL_VOL, 0, 255, 0, dac_tlv),
279
280 SOC_SINGLE("DAC Playback Limiter Switch", WM8985_DAC_LIMITER_1, 8, 1, 0),
281 SOC_SINGLE("DAC Playback Limiter Decay", WM8985_DAC_LIMITER_1, 4, 10, 0),
282 SOC_SINGLE("DAC Playback Limiter Attack", WM8985_DAC_LIMITER_1, 0, 11, 0),
283 SOC_SINGLE_TLV("DAC Playback Limiter Threshold", WM8985_DAC_LIMITER_2,
284 4, 7, 1, lim_thresh_tlv),
285 SOC_SINGLE_TLV("DAC Playback Limiter Boost Volume", WM8985_DAC_LIMITER_2,
286 0, 12, 0, lim_boost_tlv),
287 SOC_DOUBLE("DAC Inversion Switch", WM8985_DAC_CONTROL, 0, 1, 1, 0),
288 SOC_SINGLE("DAC Auto Mute Switch", WM8985_DAC_CONTROL, 2, 1, 0),
289 SOC_SINGLE("DAC 128x Oversampling Switch", WM8985_DAC_CONTROL, 3, 1, 0),
290
291 SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8985_LOUT1_HP_VOLUME_CTRL,
292 WM8985_ROUT1_HP_VOLUME_CTRL, 0, 63, 0, out_tlv),
293 SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8985_LOUT1_HP_VOLUME_CTRL,
294 WM8985_ROUT1_HP_VOLUME_CTRL, 7, 1, 0),
295 SOC_DOUBLE_R("Headphone Switch", WM8985_LOUT1_HP_VOLUME_CTRL,
296 WM8985_ROUT1_HP_VOLUME_CTRL, 6, 1, 1),
297
298 SOC_DOUBLE_R_TLV("Speaker Playback Volume", WM8985_LOUT2_SPK_VOLUME_CTRL,
299 WM8985_ROUT2_SPK_VOLUME_CTRL, 0, 63, 0, out_tlv),
300 SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8985_LOUT2_SPK_VOLUME_CTRL,
301 WM8985_ROUT2_SPK_VOLUME_CTRL, 7, 1, 0),
302 SOC_DOUBLE_R("Speaker Switch", WM8985_LOUT2_SPK_VOLUME_CTRL,
303 WM8985_ROUT2_SPK_VOLUME_CTRL, 6, 1, 1),
304
305 SOC_SINGLE("High Pass Filter Switch", WM8985_ADC_CONTROL, 8, 1, 0),
306 SOC_ENUM("High Pass Filter Mode", filter_mode),
307 SOC_SINGLE("High Pass Filter Cutoff", WM8985_ADC_CONTROL, 4, 7, 0),
308
309 SOC_DOUBLE_R_TLV("Aux Bypass Volume",
310 WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 6, 7, 0,
311 aux_tlv),
312
313 SOC_DOUBLE_R_TLV("Input PGA Bypass Volume",
314 WM8985_LEFT_MIXER_CTRL, WM8985_RIGHT_MIXER_CTRL, 2, 7, 0,
315 bypass_tlv),
316
317 SOC_ENUM_EXT("Equalizer Function", eqmode, eqmode_get, eqmode_put),
318 SOC_ENUM("EQ1 Cutoff", eq1_cutoff),
319 SOC_SINGLE_TLV("EQ1 Volume", WM8985_EQ1_LOW_SHELF, 0, 24, 1, eq_tlv),
320 SOC_ENUM("EQ2 Bandwith", eq2_bw),
321 SOC_ENUM("EQ2 Cutoff", eq2_cutoff),
322 SOC_SINGLE_TLV("EQ2 Volume", WM8985_EQ2_PEAK_1, 0, 24, 1, eq_tlv),
323 SOC_ENUM("EQ3 Bandwith", eq3_bw),
324 SOC_ENUM("EQ3 Cutoff", eq3_cutoff),
325 SOC_SINGLE_TLV("EQ3 Volume", WM8985_EQ3_PEAK_2, 0, 24, 1, eq_tlv),
326 SOC_ENUM("EQ4 Bandwith", eq4_bw),
327 SOC_ENUM("EQ4 Cutoff", eq4_cutoff),
328 SOC_SINGLE_TLV("EQ4 Volume", WM8985_EQ4_PEAK_3, 0, 24, 1, eq_tlv),
329 SOC_ENUM("EQ5 Cutoff", eq5_cutoff),
330 SOC_SINGLE_TLV("EQ5 Volume", WM8985_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),
331
332 SOC_ENUM("3D Depth", depth_3d),
333
334 SOC_ENUM("Speaker Mode", speaker_mode)
335};
336
337static const struct snd_kcontrol_new left_out_mixer[] = {
338 SOC_DAPM_SINGLE("Line Switch", WM8985_LEFT_MIXER_CTRL, 1, 1, 0),
339 SOC_DAPM_SINGLE("Aux Switch", WM8985_LEFT_MIXER_CTRL, 5, 1, 0),
340 SOC_DAPM_SINGLE("PCM Switch", WM8985_LEFT_MIXER_CTRL, 0, 1, 0),
341};
342
343static const struct snd_kcontrol_new right_out_mixer[] = {
344 SOC_DAPM_SINGLE("Line Switch", WM8985_RIGHT_MIXER_CTRL, 1, 1, 0),
345 SOC_DAPM_SINGLE("Aux Switch", WM8985_RIGHT_MIXER_CTRL, 5, 1, 0),
346 SOC_DAPM_SINGLE("PCM Switch", WM8985_RIGHT_MIXER_CTRL, 0, 1, 0),
347};
348
349static const struct snd_kcontrol_new left_input_mixer[] = {
350 SOC_DAPM_SINGLE("L2 Switch", WM8985_INPUT_CTRL, 2, 1, 0),
351 SOC_DAPM_SINGLE("MicN Switch", WM8985_INPUT_CTRL, 1, 1, 0),
352 SOC_DAPM_SINGLE("MicP Switch", WM8985_INPUT_CTRL, 0, 1, 0),
353};
354
355static const struct snd_kcontrol_new right_input_mixer[] = {
356 SOC_DAPM_SINGLE("R2 Switch", WM8985_INPUT_CTRL, 6, 1, 0),
357 SOC_DAPM_SINGLE("MicN Switch", WM8985_INPUT_CTRL, 5, 1, 0),
358 SOC_DAPM_SINGLE("MicP Switch", WM8985_INPUT_CTRL, 4, 1, 0),
359};
360
361static const struct snd_kcontrol_new left_boost_mixer[] = {
362 SOC_DAPM_SINGLE_TLV("L2 Volume", WM8985_LEFT_ADC_BOOST_CTRL,
363 4, 7, 0, boost_tlv),
364 SOC_DAPM_SINGLE_TLV("AUXL Volume", WM8985_LEFT_ADC_BOOST_CTRL,
365 0, 7, 0, boost_tlv)
366};
367
368static const struct snd_kcontrol_new right_boost_mixer[] = {
369 SOC_DAPM_SINGLE_TLV("R2 Volume", WM8985_RIGHT_ADC_BOOST_CTRL,
370 4, 7, 0, boost_tlv),
371 SOC_DAPM_SINGLE_TLV("AUXR Volume", WM8985_RIGHT_ADC_BOOST_CTRL,
372 0, 7, 0, boost_tlv)
373};
374
375static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
376 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8985_POWER_MANAGEMENT_3,
377 0, 0),
378 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8985_POWER_MANAGEMENT_3,
379 1, 0),
380 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8985_POWER_MANAGEMENT_2,
381 0, 0),
382 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8985_POWER_MANAGEMENT_2,
383 1, 0),
384
385 SND_SOC_DAPM_MIXER("Left Output Mixer", WM8985_POWER_MANAGEMENT_3,
386 2, 0, left_out_mixer, ARRAY_SIZE(left_out_mixer)),
387 SND_SOC_DAPM_MIXER("Right Output Mixer", WM8985_POWER_MANAGEMENT_3,
388 3, 0, right_out_mixer, ARRAY_SIZE(right_out_mixer)),
389
390 SND_SOC_DAPM_MIXER("Left Input Mixer", WM8985_POWER_MANAGEMENT_2,
391 2, 0, left_input_mixer, ARRAY_SIZE(left_input_mixer)),
392 SND_SOC_DAPM_MIXER("Right Input Mixer", WM8985_POWER_MANAGEMENT_2,
393 3, 0, right_input_mixer, ARRAY_SIZE(right_input_mixer)),
394
395 SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8985_POWER_MANAGEMENT_2,
396 4, 0, left_boost_mixer, ARRAY_SIZE(left_boost_mixer)),
397 SND_SOC_DAPM_MIXER("Right Boost Mixer", WM8985_POWER_MANAGEMENT_2,
398 5, 0, right_boost_mixer, ARRAY_SIZE(right_boost_mixer)),
399
400 SND_SOC_DAPM_PGA("Left Capture PGA", WM8985_LEFT_INP_PGA_GAIN_CTRL,
401 6, 1, NULL, 0),
402 SND_SOC_DAPM_PGA("Right Capture PGA", WM8985_RIGHT_INP_PGA_GAIN_CTRL,
403 6, 1, NULL, 0),
404
405 SND_SOC_DAPM_PGA("Left Headphone Out", WM8985_POWER_MANAGEMENT_2,
406 7, 0, NULL, 0),
407 SND_SOC_DAPM_PGA("Right Headphone Out", WM8985_POWER_MANAGEMENT_2,
408 8, 0, NULL, 0),
409
410 SND_SOC_DAPM_PGA("Left Speaker Out", WM8985_POWER_MANAGEMENT_3,
411 5, 0, NULL, 0),
412 SND_SOC_DAPM_PGA("Right Speaker Out", WM8985_POWER_MANAGEMENT_3,
413 6, 0, NULL, 0),
414
415 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0),
416
417 SND_SOC_DAPM_INPUT("LIN"),
418 SND_SOC_DAPM_INPUT("LIP"),
419 SND_SOC_DAPM_INPUT("RIN"),
420 SND_SOC_DAPM_INPUT("RIP"),
421 SND_SOC_DAPM_INPUT("AUXL"),
422 SND_SOC_DAPM_INPUT("AUXR"),
423 SND_SOC_DAPM_INPUT("L2"),
424 SND_SOC_DAPM_INPUT("R2"),
425 SND_SOC_DAPM_OUTPUT("HPL"),
426 SND_SOC_DAPM_OUTPUT("HPR"),
427 SND_SOC_DAPM_OUTPUT("SPKL"),
428 SND_SOC_DAPM_OUTPUT("SPKR")
429};
430
431static const struct snd_soc_dapm_route audio_map[] = {
432 { "Right Output Mixer", "PCM Switch", "Right DAC" },
433 { "Right Output Mixer", "Aux Switch", "AUXR" },
434 { "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
435
436 { "Left Output Mixer", "PCM Switch", "Left DAC" },
437 { "Left Output Mixer", "Aux Switch", "AUXL" },
438 { "Left Output Mixer", "Line Switch", "Left Boost Mixer" },
439
440 { "Right Headphone Out", NULL, "Right Output Mixer" },
441 { "HPR", NULL, "Right Headphone Out" },
442
443 { "Left Headphone Out", NULL, "Left Output Mixer" },
444 { "HPL", NULL, "Left Headphone Out" },
445
446 { "Right Speaker Out", NULL, "Right Output Mixer" },
447 { "SPKR", NULL, "Right Speaker Out" },
448
449 { "Left Speaker Out", NULL, "Left Output Mixer" },
450 { "SPKL", NULL, "Left Speaker Out" },
451
452 { "Right ADC", NULL, "Right Boost Mixer" },
453
454 { "Right Boost Mixer", "AUXR Volume", "AUXR" },
455 { "Right Boost Mixer", NULL, "Right Capture PGA" },
456 { "Right Boost Mixer", "R2 Volume", "R2" },
457
458 { "Left ADC", NULL, "Left Boost Mixer" },
459
460 { "Left Boost Mixer", "AUXL Volume", "AUXL" },
461 { "Left Boost Mixer", NULL, "Left Capture PGA" },
462 { "Left Boost Mixer", "L2 Volume", "L2" },
463
464 { "Right Capture PGA", NULL, "Right Input Mixer" },
465 { "Left Capture PGA", NULL, "Left Input Mixer" },
466
467 { "Right Input Mixer", "R2 Switch", "R2" },
468 { "Right Input Mixer", "MicN Switch", "RIN" },
469 { "Right Input Mixer", "MicP Switch", "RIP" },
470
471 { "Left Input Mixer", "L2 Switch", "L2" },
472 { "Left Input Mixer", "MicN Switch", "LIN" },
473 { "Left Input Mixer", "MicP Switch", "LIP" },
474};
475
476static int eqmode_get(struct snd_kcontrol *kcontrol,
477 struct snd_ctl_elem_value *ucontrol)
478{
479 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
480 unsigned int reg;
481
482 reg = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
483 if (reg & WM8985_EQ3DMODE)
484 ucontrol->value.integer.value[0] = 1;
485 else
486 ucontrol->value.integer.value[0] = 0;
487
488 return 0;
489}
490
491static int eqmode_put(struct snd_kcontrol *kcontrol,
492 struct snd_ctl_elem_value *ucontrol)
493{
494 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
495 unsigned int regpwr2, regpwr3;
496 unsigned int reg_eq;
497
498 if (ucontrol->value.integer.value[0] != 0
499 && ucontrol->value.integer.value[0] != 1)
500 return -EINVAL;
501
502 reg_eq = snd_soc_read(codec, WM8985_EQ1_LOW_SHELF);
503 switch ((reg_eq & WM8985_EQ3DMODE) >> WM8985_EQ3DMODE_SHIFT) {
504 case 0:
505 if (!ucontrol->value.integer.value[0])
506 return 0;
507 break;
508 case 1:
509 if (ucontrol->value.integer.value[0])
510 return 0;
511 break;
512 }
513
514 regpwr2 = snd_soc_read(codec, WM8985_POWER_MANAGEMENT_2);
515 regpwr3 = snd_soc_read(codec, WM8985_POWER_MANAGEMENT_3);
516 /* disable the DACs and ADCs */
517 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_2,
518 WM8985_ADCENR_MASK | WM8985_ADCENL_MASK, 0);
519 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_3,
520 WM8985_DACENR_MASK | WM8985_DACENL_MASK, 0);
521 snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL,
522 WM8985_M128ENB_MASK, WM8985_M128ENB);
523 /* set the desired eqmode */
524 snd_soc_update_bits(codec, WM8985_EQ1_LOW_SHELF,
525 WM8985_EQ3DMODE_MASK,
526 ucontrol->value.integer.value[0]
527 << WM8985_EQ3DMODE_SHIFT);
528 /* restore DAC/ADC configuration */
529 snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, regpwr2);
530 snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, regpwr3);
531 return 0;
532}
533
534static int wm8985_add_widgets(struct snd_soc_codec *codec)
535{
536 snd_soc_dapm_new_controls(codec, wm8985_dapm_widgets,
537 ARRAY_SIZE(wm8985_dapm_widgets));
538
539 snd_soc_dapm_add_routes(codec, audio_map,
540 ARRAY_SIZE(audio_map));
541 return 0;
542}
543
544static int wm8985_reset(struct snd_soc_codec *codec)
545{
546 return snd_soc_write(codec, WM8985_SOFTWARE_RESET, 0x0);
547}
548
549static int wm8985_dac_mute(struct snd_soc_dai *dai, int mute)
550{
551 struct snd_soc_codec *codec = dai->codec;
552
553 return snd_soc_update_bits(codec, WM8985_DAC_CONTROL,
554 WM8985_SOFTMUTE_MASK,
555 !!mute << WM8985_SOFTMUTE_SHIFT);
556}
557
558static int wm8985_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
559{
560 struct snd_soc_codec *codec;
561 u16 format, master, bcp, lrp;
562
563 codec = dai->codec;
564
565 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
566 case SND_SOC_DAIFMT_I2S:
567 format = 0x2;
568 break;
569 case SND_SOC_DAIFMT_RIGHT_J:
570 format = 0x0;
571 break;
572 case SND_SOC_DAIFMT_LEFT_J:
573 format = 0x1;
574 break;
575 case SND_SOC_DAIFMT_DSP_A:
576 case SND_SOC_DAIFMT_DSP_B:
577 format = 0x3;
578 break;
579 default:
580 dev_err(dai->dev, "Unknown dai format\n");
581 return -EINVAL;
582 }
583
584 snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
585 WM8985_FMT_MASK, format << WM8985_FMT_SHIFT);
586
587 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
588 case SND_SOC_DAIFMT_CBM_CFM:
589 master = 1;
590 break;
591 case SND_SOC_DAIFMT_CBS_CFS:
592 master = 0;
593 break;
594 default:
595 dev_err(dai->dev, "Unknown master/slave configuration\n");
596 return -EINVAL;
597 }
598
599 snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
600 WM8985_MS_MASK, master << WM8985_MS_SHIFT);
601
602 /* frame inversion is not valid for dsp modes */
603 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
604 case SND_SOC_DAIFMT_DSP_A:
605 case SND_SOC_DAIFMT_DSP_B:
606 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
607 case SND_SOC_DAIFMT_IB_IF:
608 case SND_SOC_DAIFMT_NB_IF:
609 return -EINVAL;
610 default:
611 break;
612 }
613 break;
614 default:
615 break;
616 }
617
618 bcp = lrp = 0;
619 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
620 case SND_SOC_DAIFMT_NB_NF:
621 break;
622 case SND_SOC_DAIFMT_IB_IF:
623 bcp = lrp = 1;
624 break;
625 case SND_SOC_DAIFMT_IB_NF:
626 bcp = 1;
627 break;
628 case SND_SOC_DAIFMT_NB_IF:
629 lrp = 1;
630 break;
631 default:
632 dev_err(dai->dev, "Unknown polarity configuration\n");
633 return -EINVAL;
634 }
635
636 snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
637 WM8985_LRP_MASK, lrp << WM8985_LRP_SHIFT);
638 snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
639 WM8985_BCP_MASK, bcp << WM8985_BCP_SHIFT);
640 return 0;
641}
642
643static int wm8985_hw_params(struct snd_pcm_substream *substream,
644 struct snd_pcm_hw_params *params,
645 struct snd_soc_dai *dai)
646{
647 int i;
648 struct snd_soc_codec *codec;
649 struct wm8985_priv *wm8985;
650 u16 blen, srate_idx;
651 unsigned int tmp;
652 int srate_best;
653
654 codec = dai->codec;
655 wm8985 = snd_soc_codec_get_drvdata(codec);
656
657 wm8985->bclk = snd_soc_params_to_bclk(params);
658 if ((int)wm8985->bclk < 0)
659 return wm8985->bclk;
660
661 switch (params_format(params)) {
662 case SNDRV_PCM_FORMAT_S16_LE:
663 blen = 0x0;
664 break;
665 case SNDRV_PCM_FORMAT_S20_3LE:
666 blen = 0x1;
667 break;
668 case SNDRV_PCM_FORMAT_S24_LE:
669 blen = 0x2;
670 break;
671 case SNDRV_PCM_FORMAT_S32_LE:
672 blen = 0x3;
673 break;
674 default:
675 dev_err(dai->dev, "Unsupported word length %u\n",
676 params_format(params));
677 return -EINVAL;
678 }
679
680 snd_soc_update_bits(codec, WM8985_AUDIO_INTERFACE,
681 WM8985_WL_MASK, blen << WM8985_WL_SHIFT);
682
683 /*
684 * match to the nearest possible sample rate and rely
685 * on the array index to configure the SR register
686 */
687 srate_idx = 0;
688 srate_best = abs(srates[0] - params_rate(params));
689 for (i = 1; i < ARRAY_SIZE(srates); ++i) {
690 if (abs(srates[i] - params_rate(params)) >= srate_best)
691 continue;
692 srate_idx = i;
693 srate_best = abs(srates[i] - params_rate(params));
694 }
695
696 dev_dbg(dai->dev, "Selected SRATE = %d\n", srates[srate_idx]);
697 snd_soc_update_bits(codec, WM8985_ADDITIONAL_CONTROL,
698 WM8985_SR_MASK, srate_idx << WM8985_SR_SHIFT);
699
700 dev_dbg(dai->dev, "Target BCLK = %uHz\n", wm8985->bclk);
701 dev_dbg(dai->dev, "SYSCLK = %uHz\n", wm8985->sysclk);
702
703 for (i = 0; i < ARRAY_SIZE(fs_ratios); ++i) {
704 if (wm8985->sysclk / params_rate(params)
705 == fs_ratios[i].ratio)
706 break;
707 }
708
709 if (i == ARRAY_SIZE(fs_ratios)) {
710 dev_err(dai->dev, "Unable to configure MCLK ratio %u/%u\n",
711 wm8985->sysclk, params_rate(params));
712 return -EINVAL;
713 }
714
715 dev_dbg(dai->dev, "MCLK ratio = %dfs\n", fs_ratios[i].ratio);
716 snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
717 WM8985_MCLKDIV_MASK, i << WM8985_MCLKDIV_SHIFT);
718
719 /* select the appropriate bclk divider */
720 tmp = (wm8985->sysclk / fs_ratios[i].div) * 10;
721 for (i = 0; i < ARRAY_SIZE(bclk_divs); ++i) {
722 if (wm8985->bclk == tmp / bclk_divs[i])
723 break;
724 }
725
726 if (i == ARRAY_SIZE(bclk_divs)) {
727 dev_err(dai->dev, "No matching BCLK divider found\n");
728 return -EINVAL;
729 }
730
731 dev_dbg(dai->dev, "BCLK div = %d\n", i);
732 snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
733 WM8985_BCLKDIV_MASK, i << WM8985_BCLKDIV_SHIFT);
734 return 0;
735}
736
737struct pll_div {
738 u32 div2:1;
739 u32 n:4;
740 u32 k:24;
741};
742
743#define FIXED_PLL_SIZE ((1ULL << 24) * 10)
744static int pll_factors(struct pll_div *pll_div, unsigned int target,
745 unsigned int source)
746{
747 u64 Kpart;
748 unsigned long int K, Ndiv, Nmod;
749
750 pll_div->div2 = 0;
751 Ndiv = target / source;
752 if (Ndiv < 6) {
753 source >>= 1;
754 pll_div->div2 = 1;
755 Ndiv = target / source;
756 }
757
758 if (Ndiv < 6 || Ndiv > 12) {
759 printk(KERN_ERR "%s: WM8985 N value is not within"
760 " the recommended range: %lu\n", __func__, Ndiv);
761 return -EINVAL;
762 }
763 pll_div->n = Ndiv;
764
765 Nmod = target % source;
766 Kpart = FIXED_PLL_SIZE * (u64)Nmod;
767
768 do_div(Kpart, source);
769
770 K = Kpart & 0xffffffff;
771 if ((K % 10) >= 5)
772 K += 5;
773 K /= 10;
774 pll_div->k = K;
775
776 return 0;
777}
778
779static int wm8985_set_pll(struct snd_soc_dai *dai, int pll_id,
780 int source, unsigned int freq_in,
781 unsigned int freq_out)
782{
783 int ret;
784 struct snd_soc_codec *codec;
785 struct pll_div pll_div;
786
787 codec = dai->codec;
788 if (freq_in && freq_out) {
789 ret = pll_factors(&pll_div, freq_out * 4 * 2, freq_in);
790 if (ret)
791 return ret;
792 }
793
794 /* disable the PLL before reprogramming it */
795 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
796 WM8985_PLLEN_MASK, 0);
797
798 if (!freq_in || !freq_out)
799 return 0;
800
801 /* set PLLN and PRESCALE */
802 snd_soc_write(codec, WM8985_PLL_N,
803 (pll_div.div2 << WM8985_PLL_PRESCALE_SHIFT)
804 | pll_div.n);
805 /* set PLLK */
806 snd_soc_write(codec, WM8985_PLL_K_3, pll_div.k & 0x1ff);
807 snd_soc_write(codec, WM8985_PLL_K_2, (pll_div.k >> 9) & 0x1ff);
808 snd_soc_write(codec, WM8985_PLL_K_1, (pll_div.k >> 18));
809 /* set the source of the clock to be the PLL */
810 snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
811 WM8985_CLKSEL_MASK, WM8985_CLKSEL);
812 /* enable the PLL */
813 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
814 WM8985_PLLEN_MASK, WM8985_PLLEN);
815 return 0;
816}
817
818static int wm8985_set_sysclk(struct snd_soc_dai *dai,
819 int clk_id, unsigned int freq, int dir)
820{
821 struct snd_soc_codec *codec;
822 struct wm8985_priv *wm8985;
823
824 codec = dai->codec;
825 wm8985 = snd_soc_codec_get_drvdata(codec);
826
827 switch (clk_id) {
828 case WM8985_CLKSRC_MCLK:
829 snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
830 WM8985_CLKSEL_MASK, 0);
831 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
832 WM8985_PLLEN_MASK, 0);
833 break;
834 case WM8985_CLKSRC_PLL:
835 snd_soc_update_bits(codec, WM8985_CLOCK_GEN_CONTROL,
836 WM8985_CLKSEL_MASK, WM8985_CLKSEL);
837 break;
838 default:
839 dev_err(dai->dev, "Unknown clock source %d\n", clk_id);
840 return -EINVAL;
841 }
842
843 wm8985->sysclk = freq;
844 return 0;
845}
846
847static void wm8985_sync_cache(struct snd_soc_codec *codec)
848{
849 short i;
850 u16 *cache;
851
852 if (!codec->cache_sync)
853 return;
854 codec->cache_only = 0;
855 /* restore cache */
856 cache = codec->reg_cache;
857 for (i = 0; i < codec->driver->reg_cache_size; i++) {
858 if (i == WM8985_SOFTWARE_RESET
859 || cache[i] == wm8985_reg_defs[i])
860 continue;
861 snd_soc_write(codec, i, cache[i]);
862 }
863 codec->cache_sync = 0;
864}
865
866static int wm8985_set_bias_level(struct snd_soc_codec *codec,
867 enum snd_soc_bias_level level)
868{
869 int ret;
870 struct wm8985_priv *wm8985;
871
872 wm8985 = snd_soc_codec_get_drvdata(codec);
873 switch (level) {
874 case SND_SOC_BIAS_ON:
875 case SND_SOC_BIAS_PREPARE:
876 /* VMID at 75k */
877 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
878 WM8985_VMIDSEL_MASK,
879 1 << WM8985_VMIDSEL_SHIFT);
880 break;
881 case SND_SOC_BIAS_STANDBY:
882 if (codec->bias_level == SND_SOC_BIAS_OFF) {
883 ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies),
884 wm8985->supplies);
885 if (ret) {
886 dev_err(codec->dev,
887 "Failed to enable supplies: %d\n",
888 ret);
889 return ret;
890 }
891
892 wm8985_sync_cache(codec);
893
894 /* enable anti-pop features */
895 snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
896 WM8985_POBCTRL_MASK,
897 WM8985_POBCTRL);
898 /* enable thermal shutdown */
899 snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
900 WM8985_TSDEN_MASK, WM8985_TSDEN);
901 snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
902 WM8985_TSOPCTRL_MASK,
903 WM8985_TSOPCTRL);
904 /* enable BIASEN */
905 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
906 WM8985_BIASEN_MASK, WM8985_BIASEN);
907 /* VMID at 75k */
908 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
909 WM8985_VMIDSEL_MASK,
910 1 << WM8985_VMIDSEL_SHIFT);
911 msleep(500);
912 /* disable anti-pop features */
913 snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
914 WM8985_POBCTRL_MASK, 0);
915 }
916 /* VMID at 300k */
917 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
918 WM8985_VMIDSEL_MASK,
919 2 << WM8985_VMIDSEL_SHIFT);
920 break;
921 case SND_SOC_BIAS_OFF:
922 /* disable thermal shutdown */
923 snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
924 WM8985_TSOPCTRL_MASK, 0);
925 snd_soc_update_bits(codec, WM8985_OUTPUT_CTRL0,
926 WM8985_TSDEN_MASK, 0);
927 /* disable VMIDSEL and BIASEN */
928 snd_soc_update_bits(codec, WM8985_POWER_MANAGEMENT_1,
929 WM8985_VMIDSEL_MASK | WM8985_BIASEN_MASK,
930 0);
931 snd_soc_write(codec, WM8985_POWER_MANAGEMENT_1, 0);
932 snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, 0);
933 snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, 0);
934
935 codec->cache_sync = 1;
936
937 regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies),
938 wm8985->supplies);
939 break;
940 }
941
942 codec->bias_level = level;
943 return 0;
944}
945
946#ifdef CONFIG_PM
947static int wm8985_suspend(struct snd_soc_codec *codec, pm_message_t state)
948{
949 wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
950 return 0;
951}
952
953static int wm8985_resume(struct snd_soc_codec *codec)
954{
955 wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
956 return 0;
957}
958#else
959#define wm8985_suspend NULL
960#define wm8985_resume NULL
961#endif
962
963static int wm8985_remove(struct snd_soc_codec *codec)
964{
965 struct wm8985_priv *wm8985;
966
967 wm8985 = snd_soc_codec_get_drvdata(codec);
968 wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
969 regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
970 return 0;
971}
972
973static int wm8985_probe(struct snd_soc_codec *codec)
974{
975 size_t i;
976 struct wm8985_priv *wm8985;
977 int ret;
978 u16 *cache;
979
980 wm8985 = snd_soc_codec_get_drvdata(codec);
981
982 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8985->control_type);
983 if (ret < 0) {
984 dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
985 return ret;
986 }
987
988 for (i = 0; i < ARRAY_SIZE(wm8985->supplies); i++)
989 wm8985->supplies[i].supply = wm8985_supply_names[i];
990
991 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8985->supplies),
992 wm8985->supplies);
993 if (ret) {
994 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
995 return ret;
996 }
997
998 ret = regulator_bulk_enable(ARRAY_SIZE(wm8985->supplies),
999 wm8985->supplies);
1000 if (ret) {
1001 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1002 goto err_reg_get;
1003 }
1004
1005 ret = wm8985_reset(codec);
1006 if (ret < 0) {
1007 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
1008 goto err_reg_enable;
1009 }
1010
1011 cache = codec->reg_cache;
1012 /* latch volume update bits */
1013 for (i = 0; i < ARRAY_SIZE(volume_update_regs); ++i)
1014 cache[volume_update_regs[i]] |= 0x100;
1015 /* enable BIASCUT */
1016 cache[WM8985_BIAS_CTRL] |= WM8985_BIASCUT;
1017 codec->cache_sync = 1;
1018
1019 snd_soc_add_controls(codec, wm8985_snd_controls,
1020 ARRAY_SIZE(wm8985_snd_controls));
1021 wm8985_add_widgets(codec);
1022
1023 wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1024 return 0;
1025
1026err_reg_enable:
1027 regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
1028err_reg_get:
1029 regulator_bulk_free(ARRAY_SIZE(wm8985->supplies), wm8985->supplies);
1030 return ret;
1031}
1032
1033static struct snd_soc_dai_ops wm8985_dai_ops = {
1034 .digital_mute = wm8985_dac_mute,
1035 .hw_params = wm8985_hw_params,
1036 .set_fmt = wm8985_set_fmt,
1037 .set_sysclk = wm8985_set_sysclk,
1038 .set_pll = wm8985_set_pll
1039};
1040
1041#define WM8985_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
1042 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
1043
1044static struct snd_soc_dai_driver wm8985_dai = {
1045 .name = "wm8985-hifi",
1046 .playback = {
1047 .stream_name = "Playback",
1048 .channels_min = 2,
1049 .channels_max = 2,
1050 .rates = SNDRV_PCM_RATE_8000_48000,
1051 .formats = WM8985_FORMATS,
1052 },
1053 .capture = {
1054 .stream_name = "Capture",
1055 .channels_min = 2,
1056 .channels_max = 2,
1057 .rates = SNDRV_PCM_RATE_8000_48000,
1058 .formats = WM8985_FORMATS,
1059 },
1060 .ops = &wm8985_dai_ops,
1061 .symmetric_rates = 1
1062};
1063
1064static struct snd_soc_codec_driver soc_codec_dev_wm8985 = {
1065 .probe = wm8985_probe,
1066 .remove = wm8985_remove,
1067 .suspend = wm8985_suspend,
1068 .resume = wm8985_resume,
1069 .set_bias_level = wm8985_set_bias_level,
1070 .reg_cache_size = ARRAY_SIZE(wm8985_reg_defs),
1071 .reg_word_size = sizeof(u16),
1072 .reg_cache_default = wm8985_reg_defs
1073};
1074
1075#if defined(CONFIG_SPI_MASTER)
1076static int __devinit wm8985_spi_probe(struct spi_device *spi)
1077{
1078 struct wm8985_priv *wm8985;
1079 int ret;
1080
1081 wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
1082 if (!wm8985)
1083 return -ENOMEM;
1084
1085 wm8985->control_type = SND_SOC_SPI;
1086 spi_set_drvdata(spi, wm8985);
1087
1088 ret = snd_soc_register_codec(&spi->dev,
1089 &soc_codec_dev_wm8985, &wm8985_dai, 1);
1090 if (ret < 0)
1091 kfree(wm8985);
1092 return ret;
1093}
1094
1095static int __devexit wm8985_spi_remove(struct spi_device *spi)
1096{
1097 snd_soc_unregister_codec(&spi->dev);
1098 kfree(spi_get_drvdata(spi));
1099 return 0;
1100}
1101
1102static struct spi_driver wm8985_spi_driver = {
1103 .driver = {
1104 .name = "wm8985",
1105 .owner = THIS_MODULE,
1106 },
1107 .probe = wm8985_spi_probe,
1108 .remove = __devexit_p(wm8985_spi_remove)
1109};
1110#endif
1111
1112#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1113static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
1114 const struct i2c_device_id *id)
1115{
1116 struct wm8985_priv *wm8985;
1117 int ret;
1118
1119 wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
1120 if (!wm8985)
1121 return -ENOMEM;
1122
1123 wm8985->control_type = SND_SOC_I2C;
1124 i2c_set_clientdata(i2c, wm8985);
1125
1126 ret = snd_soc_register_codec(&i2c->dev,
1127 &soc_codec_dev_wm8985, &wm8985_dai, 1);
1128 if (ret < 0)
1129 kfree(wm8985);
1130 return ret;
1131}
1132
1133static __devexit int wm8985_i2c_remove(struct i2c_client *client)
1134{
1135 snd_soc_unregister_codec(&client->dev);
1136 kfree(i2c_get_clientdata(client));
1137 return 0;
1138}
1139
1140static const struct i2c_device_id wm8985_i2c_id[] = {
1141 { "wm8985", 0 },
1142 { }
1143};
1144MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id);
1145
1146static struct i2c_driver wm8985_i2c_driver = {
1147 .driver = {
1148 .name = "wm8985",
1149 .owner = THIS_MODULE,
1150 },
1151 .probe = wm8985_i2c_probe,
1152 .remove = __devexit_p(wm8985_i2c_remove),
1153 .id_table = wm8985_i2c_id
1154};
1155#endif
1156
1157static int __init wm8985_modinit(void)
1158{
1159 int ret = 0;
1160
1161#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1162 ret = i2c_add_driver(&wm8985_i2c_driver);
1163 if (ret) {
1164 printk(KERN_ERR "Failed to register wm8985 I2C driver: %d\n",
1165 ret);
1166 }
1167#endif
1168#if defined(CONFIG_SPI_MASTER)
1169 ret = spi_register_driver(&wm8985_spi_driver);
1170 if (ret != 0) {
1171 printk(KERN_ERR "Failed to register wm8985 SPI driver: %d\n",
1172 ret);
1173 }
1174#endif
1175 return ret;
1176}
1177module_init(wm8985_modinit);
1178
1179static void __exit wm8985_exit(void)
1180{
1181#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1182 i2c_del_driver(&wm8985_i2c_driver);
1183#endif
1184#if defined(CONFIG_SPI_MASTER)
1185 spi_unregister_driver(&wm8985_spi_driver);
1186#endif
1187}
1188module_exit(wm8985_exit);
1189
1190MODULE_DESCRIPTION("ASoC WM8985 driver");
1191MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>");
1192MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8985.h b/sound/soc/codecs/wm8985.h
new file mode 100644
index 000000000000..2e71ff507638
--- /dev/null
+++ b/sound/soc/codecs/wm8985.h
@@ -0,0 +1,1045 @@
1/*
2 * wm8985.h -- WM8985 ASoC driver
3 *
4 * Copyright 2010 Wolfson Microelectronics plc
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _WM8985_H
14#define _WM8985_H
15
16#define WM8985_SOFTWARE_RESET 0x00
17#define WM8985_POWER_MANAGEMENT_1 0x01
18#define WM8985_POWER_MANAGEMENT_2 0x02
19#define WM8985_POWER_MANAGEMENT_3 0x03
20#define WM8985_AUDIO_INTERFACE 0x04
21#define WM8985_COMPANDING_CONTROL 0x05
22#define WM8985_CLOCK_GEN_CONTROL 0x06
23#define WM8985_ADDITIONAL_CONTROL 0x07
24#define WM8985_GPIO_CONTROL 0x08
25#define WM8985_JACK_DETECT_CONTROL_1 0x09
26#define WM8985_DAC_CONTROL 0x0A
27#define WM8985_LEFT_DAC_DIGITAL_VOL 0x0B
28#define WM8985_RIGHT_DAC_DIGITAL_VOL 0x0C
29#define WM8985_JACK_DETECT_CONTROL_2 0x0D
30#define WM8985_ADC_CONTROL 0x0E
31#define WM8985_LEFT_ADC_DIGITAL_VOL 0x0F
32#define WM8985_RIGHT_ADC_DIGITAL_VOL 0x10
33#define WM8985_EQ1_LOW_SHELF 0x12
34#define WM8985_EQ2_PEAK_1 0x13
35#define WM8985_EQ3_PEAK_2 0x14
36#define WM8985_EQ4_PEAK_3 0x15
37#define WM8985_EQ5_HIGH_SHELF 0x16
38#define WM8985_DAC_LIMITER_1 0x18
39#define WM8985_DAC_LIMITER_2 0x19
40#define WM8985_NOTCH_FILTER_1 0x1B
41#define WM8985_NOTCH_FILTER_2 0x1C
42#define WM8985_NOTCH_FILTER_3 0x1D
43#define WM8985_NOTCH_FILTER_4 0x1E
44#define WM8985_ALC_CONTROL_1 0x20
45#define WM8985_ALC_CONTROL_2 0x21
46#define WM8985_ALC_CONTROL_3 0x22
47#define WM8985_NOISE_GATE 0x23
48#define WM8985_PLL_N 0x24
49#define WM8985_PLL_K_1 0x25
50#define WM8985_PLL_K_2 0x26
51#define WM8985_PLL_K_3 0x27
52#define WM8985_3D_CONTROL 0x29
53#define WM8985_OUT4_TO_ADC 0x2A
54#define WM8985_BEEP_CONTROL 0x2B
55#define WM8985_INPUT_CTRL 0x2C
56#define WM8985_LEFT_INP_PGA_GAIN_CTRL 0x2D
57#define WM8985_RIGHT_INP_PGA_GAIN_CTRL 0x2E
58#define WM8985_LEFT_ADC_BOOST_CTRL 0x2F
59#define WM8985_RIGHT_ADC_BOOST_CTRL 0x30
60#define WM8985_OUTPUT_CTRL0 0x31
61#define WM8985_LEFT_MIXER_CTRL 0x32
62#define WM8985_RIGHT_MIXER_CTRL 0x33
63#define WM8985_LOUT1_HP_VOLUME_CTRL 0x34
64#define WM8985_ROUT1_HP_VOLUME_CTRL 0x35
65#define WM8985_LOUT2_SPK_VOLUME_CTRL 0x36
66#define WM8985_ROUT2_SPK_VOLUME_CTRL 0x37
67#define WM8985_OUT3_MIXER_CTRL 0x38
68#define WM8985_OUT4_MONO_MIX_CTRL 0x39
69#define WM8985_OUTPUT_CTRL1 0x3C
70#define WM8985_BIAS_CTRL 0x3D
71
72#define WM8985_REGISTER_COUNT 59
73#define WM8985_MAX_REGISTER 0x3F
74
75/*
76 * Field Definitions.
77 */
78
79/*
80 * R0 (0x00) - Software Reset
81 */
82#define WM8985_SOFTWARE_RESET_MASK 0x01FF /* SOFTWARE_RESET - [8:0] */
83#define WM8985_SOFTWARE_RESET_SHIFT 0 /* SOFTWARE_RESET - [8:0] */
84#define WM8985_SOFTWARE_RESET_WIDTH 9 /* SOFTWARE_RESET - [8:0] */
85
86/*
87 * R1 (0x01) - Power management 1
88 */
89#define WM8985_OUT4MIXEN 0x0080 /* OUT4MIXEN */
90#define WM8985_OUT4MIXEN_MASK 0x0080 /* OUT4MIXEN */
91#define WM8985_OUT4MIXEN_SHIFT 7 /* OUT4MIXEN */
92#define WM8985_OUT4MIXEN_WIDTH 1 /* OUT4MIXEN */
93#define WM8985_OUT3MIXEN 0x0040 /* OUT3MIXEN */
94#define WM8985_OUT3MIXEN_MASK 0x0040 /* OUT3MIXEN */
95#define WM8985_OUT3MIXEN_SHIFT 6 /* OUT3MIXEN */
96#define WM8985_OUT3MIXEN_WIDTH 1 /* OUT3MIXEN */
97#define WM8985_PLLEN 0x0020 /* PLLEN */
98#define WM8985_PLLEN_MASK 0x0020 /* PLLEN */
99#define WM8985_PLLEN_SHIFT 5 /* PLLEN */
100#define WM8985_PLLEN_WIDTH 1 /* PLLEN */
101#define WM8985_MICBEN 0x0010 /* MICBEN */
102#define WM8985_MICBEN_MASK 0x0010 /* MICBEN */
103#define WM8985_MICBEN_SHIFT 4 /* MICBEN */
104#define WM8985_MICBEN_WIDTH 1 /* MICBEN */
105#define WM8985_BIASEN 0x0008 /* BIASEN */
106#define WM8985_BIASEN_MASK 0x0008 /* BIASEN */
107#define WM8985_BIASEN_SHIFT 3 /* BIASEN */
108#define WM8985_BIASEN_WIDTH 1 /* BIASEN */
109#define WM8985_BUFIOEN 0x0004 /* BUFIOEN */
110#define WM8985_BUFIOEN_MASK 0x0004 /* BUFIOEN */
111#define WM8985_BUFIOEN_SHIFT 2 /* BUFIOEN */
112#define WM8985_BUFIOEN_WIDTH 1 /* BUFIOEN */
113#define WM8985_VMIDSEL 0x0003 /* VMIDSEL */
114#define WM8985_VMIDSEL_MASK 0x0003 /* VMIDSEL - [1:0] */
115#define WM8985_VMIDSEL_SHIFT 0 /* VMIDSEL - [1:0] */
116#define WM8985_VMIDSEL_WIDTH 2 /* VMIDSEL - [1:0] */
117
118/*
119 * R2 (0x02) - Power management 2
120 */
121#define WM8985_ROUT1EN 0x0100 /* ROUT1EN */
122#define WM8985_ROUT1EN_MASK 0x0100 /* ROUT1EN */
123#define WM8985_ROUT1EN_SHIFT 8 /* ROUT1EN */
124#define WM8985_ROUT1EN_WIDTH 1 /* ROUT1EN */
125#define WM8985_LOUT1EN 0x0080 /* LOUT1EN */
126#define WM8985_LOUT1EN_MASK 0x0080 /* LOUT1EN */
127#define WM8985_LOUT1EN_SHIFT 7 /* LOUT1EN */
128#define WM8985_LOUT1EN_WIDTH 1 /* LOUT1EN */
129#define WM8985_SLEEP 0x0040 /* SLEEP */
130#define WM8985_SLEEP_MASK 0x0040 /* SLEEP */
131#define WM8985_SLEEP_SHIFT 6 /* SLEEP */
132#define WM8985_SLEEP_WIDTH 1 /* SLEEP */
133#define WM8985_BOOSTENR 0x0020 /* BOOSTENR */
134#define WM8985_BOOSTENR_MASK 0x0020 /* BOOSTENR */
135#define WM8985_BOOSTENR_SHIFT 5 /* BOOSTENR */
136#define WM8985_BOOSTENR_WIDTH 1 /* BOOSTENR */
137#define WM8985_BOOSTENL 0x0010 /* BOOSTENL */
138#define WM8985_BOOSTENL_MASK 0x0010 /* BOOSTENL */
139#define WM8985_BOOSTENL_SHIFT 4 /* BOOSTENL */
140#define WM8985_BOOSTENL_WIDTH 1 /* BOOSTENL */
141#define WM8985_INPGAENR 0x0008 /* INPGAENR */
142#define WM8985_INPGAENR_MASK 0x0008 /* INPGAENR */
143#define WM8985_INPGAENR_SHIFT 3 /* INPGAENR */
144#define WM8985_INPGAENR_WIDTH 1 /* INPGAENR */
145#define WM8985_INPPGAENL 0x0004 /* INPPGAENL */
146#define WM8985_INPPGAENL_MASK 0x0004 /* INPPGAENL */
147#define WM8985_INPPGAENL_SHIFT 2 /* INPPGAENL */
148#define WM8985_INPPGAENL_WIDTH 1 /* INPPGAENL */
149#define WM8985_ADCENR 0x0002 /* ADCENR */
150#define WM8985_ADCENR_MASK 0x0002 /* ADCENR */
151#define WM8985_ADCENR_SHIFT 1 /* ADCENR */
152#define WM8985_ADCENR_WIDTH 1 /* ADCENR */
153#define WM8985_ADCENL 0x0001 /* ADCENL */
154#define WM8985_ADCENL_MASK 0x0001 /* ADCENL */
155#define WM8985_ADCENL_SHIFT 0 /* ADCENL */
156#define WM8985_ADCENL_WIDTH 1 /* ADCENL */
157
158/*
159 * R3 (0x03) - Power management 3
160 */
161#define WM8985_OUT4EN 0x0100 /* OUT4EN */
162#define WM8985_OUT4EN_MASK 0x0100 /* OUT4EN */
163#define WM8985_OUT4EN_SHIFT 8 /* OUT4EN */
164#define WM8985_OUT4EN_WIDTH 1 /* OUT4EN */
165#define WM8985_OUT3EN 0x0080 /* OUT3EN */
166#define WM8985_OUT3EN_MASK 0x0080 /* OUT3EN */
167#define WM8985_OUT3EN_SHIFT 7 /* OUT3EN */
168#define WM8985_OUT3EN_WIDTH 1 /* OUT3EN */
169#define WM8985_ROUT2EN 0x0040 /* ROUT2EN */
170#define WM8985_ROUT2EN_MASK 0x0040 /* ROUT2EN */
171#define WM8985_ROUT2EN_SHIFT 6 /* ROUT2EN */
172#define WM8985_ROUT2EN_WIDTH 1 /* ROUT2EN */
173#define WM8985_LOUT2EN 0x0020 /* LOUT2EN */
174#define WM8985_LOUT2EN_MASK 0x0020 /* LOUT2EN */
175#define WM8985_LOUT2EN_SHIFT 5 /* LOUT2EN */
176#define WM8985_LOUT2EN_WIDTH 1 /* LOUT2EN */
177#define WM8985_RMIXEN 0x0008 /* RMIXEN */
178#define WM8985_RMIXEN_MASK 0x0008 /* RMIXEN */
179#define WM8985_RMIXEN_SHIFT 3 /* RMIXEN */
180#define WM8985_RMIXEN_WIDTH 1 /* RMIXEN */
181#define WM8985_LMIXEN 0x0004 /* LMIXEN */
182#define WM8985_LMIXEN_MASK 0x0004 /* LMIXEN */
183#define WM8985_LMIXEN_SHIFT 2 /* LMIXEN */
184#define WM8985_LMIXEN_WIDTH 1 /* LMIXEN */
185#define WM8985_DACENR 0x0002 /* DACENR */
186#define WM8985_DACENR_MASK 0x0002 /* DACENR */
187#define WM8985_DACENR_SHIFT 1 /* DACENR */
188#define WM8985_DACENR_WIDTH 1 /* DACENR */
189#define WM8985_DACENL 0x0001 /* DACENL */
190#define WM8985_DACENL_MASK 0x0001 /* DACENL */
191#define WM8985_DACENL_SHIFT 0 /* DACENL */
192#define WM8985_DACENL_WIDTH 1 /* DACENL */
193
194/*
195 * R4 (0x04) - Audio Interface
196 */
197#define WM8985_BCP 0x0100 /* BCP */
198#define WM8985_BCP_MASK 0x0100 /* BCP */
199#define WM8985_BCP_SHIFT 8 /* BCP */
200#define WM8985_BCP_WIDTH 1 /* BCP */
201#define WM8985_LRP 0x0080 /* LRP */
202#define WM8985_LRP_MASK 0x0080 /* LRP */
203#define WM8985_LRP_SHIFT 7 /* LRP */
204#define WM8985_LRP_WIDTH 1 /* LRP */
205#define WM8985_WL_MASK 0x0060 /* WL - [6:5] */
206#define WM8985_WL_SHIFT 5 /* WL - [6:5] */
207#define WM8985_WL_WIDTH 2 /* WL - [6:5] */
208#define WM8985_FMT_MASK 0x0018 /* FMT - [4:3] */
209#define WM8985_FMT_SHIFT 3 /* FMT - [4:3] */
210#define WM8985_FMT_WIDTH 2 /* FMT - [4:3] */
211#define WM8985_DLRSWAP 0x0004 /* DLRSWAP */
212#define WM8985_DLRSWAP_MASK 0x0004 /* DLRSWAP */
213#define WM8985_DLRSWAP_SHIFT 2 /* DLRSWAP */
214#define WM8985_DLRSWAP_WIDTH 1 /* DLRSWAP */
215#define WM8985_ALRSWAP 0x0002 /* ALRSWAP */
216#define WM8985_ALRSWAP_MASK 0x0002 /* ALRSWAP */
217#define WM8985_ALRSWAP_SHIFT 1 /* ALRSWAP */
218#define WM8985_ALRSWAP_WIDTH 1 /* ALRSWAP */
219#define WM8985_MONO 0x0001 /* MONO */
220#define WM8985_MONO_MASK 0x0001 /* MONO */
221#define WM8985_MONO_SHIFT 0 /* MONO */
222#define WM8985_MONO_WIDTH 1 /* MONO */
223
224/*
225 * R5 (0x05) - Companding control
226 */
227#define WM8985_WL8 0x0020 /* WL8 */
228#define WM8985_WL8_MASK 0x0020 /* WL8 */
229#define WM8985_WL8_SHIFT 5 /* WL8 */
230#define WM8985_WL8_WIDTH 1 /* WL8 */
231#define WM8985_DAC_COMP_MASK 0x0018 /* DAC_COMP - [4:3] */
232#define WM8985_DAC_COMP_SHIFT 3 /* DAC_COMP - [4:3] */
233#define WM8985_DAC_COMP_WIDTH 2 /* DAC_COMP - [4:3] */
234#define WM8985_ADC_COMP_MASK 0x0006 /* ADC_COMP - [2:1] */
235#define WM8985_ADC_COMP_SHIFT 1 /* ADC_COMP - [2:1] */
236#define WM8985_ADC_COMP_WIDTH 2 /* ADC_COMP - [2:1] */
237#define WM8985_LOOPBACK 0x0001 /* LOOPBACK */
238#define WM8985_LOOPBACK_MASK 0x0001 /* LOOPBACK */
239#define WM8985_LOOPBACK_SHIFT 0 /* LOOPBACK */
240#define WM8985_LOOPBACK_WIDTH 1 /* LOOPBACK */
241
242/*
243 * R6 (0x06) - Clock Gen control
244 */
245#define WM8985_CLKSEL 0x0100 /* CLKSEL */
246#define WM8985_CLKSEL_MASK 0x0100 /* CLKSEL */
247#define WM8985_CLKSEL_SHIFT 8 /* CLKSEL */
248#define WM8985_CLKSEL_WIDTH 1 /* CLKSEL */
249#define WM8985_MCLKDIV_MASK 0x00E0 /* MCLKDIV - [7:5] */
250#define WM8985_MCLKDIV_SHIFT 5 /* MCLKDIV - [7:5] */
251#define WM8985_MCLKDIV_WIDTH 3 /* MCLKDIV - [7:5] */
252#define WM8985_BCLKDIV_MASK 0x001C /* BCLKDIV - [4:2] */
253#define WM8985_BCLKDIV_SHIFT 2 /* BCLKDIV - [4:2] */
254#define WM8985_BCLKDIV_WIDTH 3 /* BCLKDIV - [4:2] */
255#define WM8985_MS 0x0001 /* MS */
256#define WM8985_MS_MASK 0x0001 /* MS */
257#define WM8985_MS_SHIFT 0 /* MS */
258#define WM8985_MS_WIDTH 1 /* MS */
259
260/*
261 * R7 (0x07) - Additional control
262 */
263#define WM8985_M128ENB 0x0100 /* M128ENB */
264#define WM8985_M128ENB_MASK 0x0100 /* M128ENB */
265#define WM8985_M128ENB_SHIFT 8 /* M128ENB */
266#define WM8985_M128ENB_WIDTH 1 /* M128ENB */
267#define WM8985_DCLKDIV_MASK 0x00F0 /* DCLKDIV - [7:4] */
268#define WM8985_DCLKDIV_SHIFT 4 /* DCLKDIV - [7:4] */
269#define WM8985_DCLKDIV_WIDTH 4 /* DCLKDIV - [7:4] */
270#define WM8985_SR_MASK 0x000E /* SR - [3:1] */
271#define WM8985_SR_SHIFT 1 /* SR - [3:1] */
272#define WM8985_SR_WIDTH 3 /* SR - [3:1] */
273#define WM8985_SLOWCLKEN 0x0001 /* SLOWCLKEN */
274#define WM8985_SLOWCLKEN_MASK 0x0001 /* SLOWCLKEN */
275#define WM8985_SLOWCLKEN_SHIFT 0 /* SLOWCLKEN */
276#define WM8985_SLOWCLKEN_WIDTH 1 /* SLOWCLKEN */
277
278/*
279 * R8 (0x08) - GPIO Control
280 */
281#define WM8985_GPIO1GP 0x0100 /* GPIO1GP */
282#define WM8985_GPIO1GP_MASK 0x0100 /* GPIO1GP */
283#define WM8985_GPIO1GP_SHIFT 8 /* GPIO1GP */
284#define WM8985_GPIO1GP_WIDTH 1 /* GPIO1GP */
285#define WM8985_GPIO1GPU 0x0080 /* GPIO1GPU */
286#define WM8985_GPIO1GPU_MASK 0x0080 /* GPIO1GPU */
287#define WM8985_GPIO1GPU_SHIFT 7 /* GPIO1GPU */
288#define WM8985_GPIO1GPU_WIDTH 1 /* GPIO1GPU */
289#define WM8985_GPIO1GPD 0x0040 /* GPIO1GPD */
290#define WM8985_GPIO1GPD_MASK 0x0040 /* GPIO1GPD */
291#define WM8985_GPIO1GPD_SHIFT 6 /* GPIO1GPD */
292#define WM8985_GPIO1GPD_WIDTH 1 /* GPIO1GPD */
293#define WM8985_GPIO1POL 0x0008 /* GPIO1POL */
294#define WM8985_GPIO1POL_MASK 0x0008 /* GPIO1POL */
295#define WM8985_GPIO1POL_SHIFT 3 /* GPIO1POL */
296#define WM8985_GPIO1POL_WIDTH 1 /* GPIO1POL */
297#define WM8985_GPIO1SEL_MASK 0x0007 /* GPIO1SEL - [2:0] */
298#define WM8985_GPIO1SEL_SHIFT 0 /* GPIO1SEL - [2:0] */
299#define WM8985_GPIO1SEL_WIDTH 3 /* GPIO1SEL - [2:0] */
300
301/*
302 * R9 (0x09) - Jack Detect Control 1
303 */
304#define WM8985_JD_EN 0x0040 /* JD_EN */
305#define WM8985_JD_EN_MASK 0x0040 /* JD_EN */
306#define WM8985_JD_EN_SHIFT 6 /* JD_EN */
307#define WM8985_JD_EN_WIDTH 1 /* JD_EN */
308#define WM8985_JD_SEL_MASK 0x0030 /* JD_SEL - [5:4] */
309#define WM8985_JD_SEL_SHIFT 4 /* JD_SEL - [5:4] */
310#define WM8985_JD_SEL_WIDTH 2 /* JD_SEL - [5:4] */
311
312/*
313 * R10 (0x0A) - DAC Control
314 */
315#define WM8985_SOFTMUTE 0x0040 /* SOFTMUTE */
316#define WM8985_SOFTMUTE_MASK 0x0040 /* SOFTMUTE */
317#define WM8985_SOFTMUTE_SHIFT 6 /* SOFTMUTE */
318#define WM8985_SOFTMUTE_WIDTH 1 /* SOFTMUTE */
319#define WM8985_DACOSR128 0x0008 /* DACOSR128 */
320#define WM8985_DACOSR128_MASK 0x0008 /* DACOSR128 */
321#define WM8985_DACOSR128_SHIFT 3 /* DACOSR128 */
322#define WM8985_DACOSR128_WIDTH 1 /* DACOSR128 */
323#define WM8985_AMUTE 0x0004 /* AMUTE */
324#define WM8985_AMUTE_MASK 0x0004 /* AMUTE */
325#define WM8985_AMUTE_SHIFT 2 /* AMUTE */
326#define WM8985_AMUTE_WIDTH 1 /* AMUTE */
327#define WM8985_DACPOLR 0x0002 /* DACPOLR */
328#define WM8985_DACPOLR_MASK 0x0002 /* DACPOLR */
329#define WM8985_DACPOLR_SHIFT 1 /* DACPOLR */
330#define WM8985_DACPOLR_WIDTH 1 /* DACPOLR */
331#define WM8985_DACPOLL 0x0001 /* DACPOLL */
332#define WM8985_DACPOLL_MASK 0x0001 /* DACPOLL */
333#define WM8985_DACPOLL_SHIFT 0 /* DACPOLL */
334#define WM8985_DACPOLL_WIDTH 1 /* DACPOLL */
335
336/*
337 * R11 (0x0B) - Left DAC digital Vol
338 */
339#define WM8985_DACVU 0x0100 /* DACVU */
340#define WM8985_DACVU_MASK 0x0100 /* DACVU */
341#define WM8985_DACVU_SHIFT 8 /* DACVU */
342#define WM8985_DACVU_WIDTH 1 /* DACVU */
343#define WM8985_DACVOLL_MASK 0x00FF /* DACVOLL - [7:0] */
344#define WM8985_DACVOLL_SHIFT 0 /* DACVOLL - [7:0] */
345#define WM8985_DACVOLL_WIDTH 8 /* DACVOLL - [7:0] */
346
347/*
348 * R12 (0x0C) - Right DAC digital vol
349 */
350#define WM8985_DACVU 0x0100 /* DACVU */
351#define WM8985_DACVU_MASK 0x0100 /* DACVU */
352#define WM8985_DACVU_SHIFT 8 /* DACVU */
353#define WM8985_DACVU_WIDTH 1 /* DACVU */
354#define WM8985_DACVOLR_MASK 0x00FF /* DACVOLR - [7:0] */
355#define WM8985_DACVOLR_SHIFT 0 /* DACVOLR - [7:0] */
356#define WM8985_DACVOLR_WIDTH 8 /* DACVOLR - [7:0] */
357
358/*
359 * R13 (0x0D) - Jack Detect Control 2
360 */
361#define WM8985_JD_EN1_MASK 0x00F0 /* JD_EN1 - [7:4] */
362#define WM8985_JD_EN1_SHIFT 4 /* JD_EN1 - [7:4] */
363#define WM8985_JD_EN1_WIDTH 4 /* JD_EN1 - [7:4] */
364#define WM8985_JD_EN0_MASK 0x000F /* JD_EN0 - [3:0] */
365#define WM8985_JD_EN0_SHIFT 0 /* JD_EN0 - [3:0] */
366#define WM8985_JD_EN0_WIDTH 4 /* JD_EN0 - [3:0] */
367
368/*
369 * R14 (0x0E) - ADC Control
370 */
371#define WM8985_HPFEN 0x0100 /* HPFEN */
372#define WM8985_HPFEN_MASK 0x0100 /* HPFEN */
373#define WM8985_HPFEN_SHIFT 8 /* HPFEN */
374#define WM8985_HPFEN_WIDTH 1 /* HPFEN */
375#define WM8985_HPFAPP 0x0080 /* HPFAPP */
376#define WM8985_HPFAPP_MASK 0x0080 /* HPFAPP */
377#define WM8985_HPFAPP_SHIFT 7 /* HPFAPP */
378#define WM8985_HPFAPP_WIDTH 1 /* HPFAPP */
379#define WM8985_HPFCUT_MASK 0x0070 /* HPFCUT - [6:4] */
380#define WM8985_HPFCUT_SHIFT 4 /* HPFCUT - [6:4] */
381#define WM8985_HPFCUT_WIDTH 3 /* HPFCUT - [6:4] */
382#define WM8985_ADCOSR128 0x0008 /* ADCOSR128 */
383#define WM8985_ADCOSR128_MASK 0x0008 /* ADCOSR128 */
384#define WM8985_ADCOSR128_SHIFT 3 /* ADCOSR128 */
385#define WM8985_ADCOSR128_WIDTH 1 /* ADCOSR128 */
386#define WM8985_ADCRPOL 0x0002 /* ADCRPOL */
387#define WM8985_ADCRPOL_MASK 0x0002 /* ADCRPOL */
388#define WM8985_ADCRPOL_SHIFT 1 /* ADCRPOL */
389#define WM8985_ADCRPOL_WIDTH 1 /* ADCRPOL */
390#define WM8985_ADCLPOL 0x0001 /* ADCLPOL */
391#define WM8985_ADCLPOL_MASK 0x0001 /* ADCLPOL */
392#define WM8985_ADCLPOL_SHIFT 0 /* ADCLPOL */
393#define WM8985_ADCLPOL_WIDTH 1 /* ADCLPOL */
394
395/*
396 * R15 (0x0F) - Left ADC Digital Vol
397 */
398#define WM8985_ADCVU 0x0100 /* ADCVU */
399#define WM8985_ADCVU_MASK 0x0100 /* ADCVU */
400#define WM8985_ADCVU_SHIFT 8 /* ADCVU */
401#define WM8985_ADCVU_WIDTH 1 /* ADCVU */
402#define WM8985_ADCVOLL_MASK 0x00FF /* ADCVOLL - [7:0] */
403#define WM8985_ADCVOLL_SHIFT 0 /* ADCVOLL - [7:0] */
404#define WM8985_ADCVOLL_WIDTH 8 /* ADCVOLL - [7:0] */
405
406/*
407 * R16 (0x10) - Right ADC Digital Vol
408 */
409#define WM8985_ADCVU 0x0100 /* ADCVU */
410#define WM8985_ADCVU_MASK 0x0100 /* ADCVU */
411#define WM8985_ADCVU_SHIFT 8 /* ADCVU */
412#define WM8985_ADCVU_WIDTH 1 /* ADCVU */
413#define WM8985_ADCVOLR_MASK 0x00FF /* ADCVOLR - [7:0] */
414#define WM8985_ADCVOLR_SHIFT 0 /* ADCVOLR - [7:0] */
415#define WM8985_ADCVOLR_WIDTH 8 /* ADCVOLR - [7:0] */
416
417/*
418 * R18 (0x12) - EQ1 - low shelf
419 */
420#define WM8985_EQ3DMODE 0x0100 /* EQ3DMODE */
421#define WM8985_EQ3DMODE_MASK 0x0100 /* EQ3DMODE */
422#define WM8985_EQ3DMODE_SHIFT 8 /* EQ3DMODE */
423#define WM8985_EQ3DMODE_WIDTH 1 /* EQ3DMODE */
424#define WM8985_EQ1C_MASK 0x0060 /* EQ1C - [6:5] */
425#define WM8985_EQ1C_SHIFT 5 /* EQ1C - [6:5] */
426#define WM8985_EQ1C_WIDTH 2 /* EQ1C - [6:5] */
427#define WM8985_EQ1G_MASK 0x001F /* EQ1G - [4:0] */
428#define WM8985_EQ1G_SHIFT 0 /* EQ1G - [4:0] */
429#define WM8985_EQ1G_WIDTH 5 /* EQ1G - [4:0] */
430
431/*
432 * R19 (0x13) - EQ2 - peak 1
433 */
434#define WM8985_EQ2BW 0x0100 /* EQ2BW */
435#define WM8985_EQ2BW_MASK 0x0100 /* EQ2BW */
436#define WM8985_EQ2BW_SHIFT 8 /* EQ2BW */
437#define WM8985_EQ2BW_WIDTH 1 /* EQ2BW */
438#define WM8985_EQ2C_MASK 0x0060 /* EQ2C - [6:5] */
439#define WM8985_EQ2C_SHIFT 5 /* EQ2C - [6:5] */
440#define WM8985_EQ2C_WIDTH 2 /* EQ2C - [6:5] */
441#define WM8985_EQ2G_MASK 0x001F /* EQ2G - [4:0] */
442#define WM8985_EQ2G_SHIFT 0 /* EQ2G - [4:0] */
443#define WM8985_EQ2G_WIDTH 5 /* EQ2G - [4:0] */
444
445/*
446 * R20 (0x14) - EQ3 - peak 2
447 */
448#define WM8985_EQ3BW 0x0100 /* EQ3BW */
449#define WM8985_EQ3BW_MASK 0x0100 /* EQ3BW */
450#define WM8985_EQ3BW_SHIFT 8 /* EQ3BW */
451#define WM8985_EQ3BW_WIDTH 1 /* EQ3BW */
452#define WM8985_EQ3C_MASK 0x0060 /* EQ3C - [6:5] */
453#define WM8985_EQ3C_SHIFT 5 /* EQ3C - [6:5] */
454#define WM8985_EQ3C_WIDTH 2 /* EQ3C - [6:5] */
455#define WM8985_EQ3G_MASK 0x001F /* EQ3G - [4:0] */
456#define WM8985_EQ3G_SHIFT 0 /* EQ3G - [4:0] */
457#define WM8985_EQ3G_WIDTH 5 /* EQ3G - [4:0] */
458
459/*
460 * R21 (0x15) - EQ4 - peak 3
461 */
462#define WM8985_EQ4BW 0x0100 /* EQ4BW */
463#define WM8985_EQ4BW_MASK 0x0100 /* EQ4BW */
464#define WM8985_EQ4BW_SHIFT 8 /* EQ4BW */
465#define WM8985_EQ4BW_WIDTH 1 /* EQ4BW */
466#define WM8985_EQ4C_MASK 0x0060 /* EQ4C - [6:5] */
467#define WM8985_EQ4C_SHIFT 5 /* EQ4C - [6:5] */
468#define WM8985_EQ4C_WIDTH 2 /* EQ4C - [6:5] */
469#define WM8985_EQ4G_MASK 0x001F /* EQ4G - [4:0] */
470#define WM8985_EQ4G_SHIFT 0 /* EQ4G - [4:0] */
471#define WM8985_EQ4G_WIDTH 5 /* EQ4G - [4:0] */
472
473/*
474 * R22 (0x16) - EQ5 - high shelf
475 */
476#define WM8985_EQ5C_MASK 0x0060 /* EQ5C - [6:5] */
477#define WM8985_EQ5C_SHIFT 5 /* EQ5C - [6:5] */
478#define WM8985_EQ5C_WIDTH 2 /* EQ5C - [6:5] */
479#define WM8985_EQ5G_MASK 0x001F /* EQ5G - [4:0] */
480#define WM8985_EQ5G_SHIFT 0 /* EQ5G - [4:0] */
481#define WM8985_EQ5G_WIDTH 5 /* EQ5G - [4:0] */
482
483/*
484 * R24 (0x18) - DAC Limiter 1
485 */
486#define WM8985_LIMEN 0x0100 /* LIMEN */
487#define WM8985_LIMEN_MASK 0x0100 /* LIMEN */
488#define WM8985_LIMEN_SHIFT 8 /* LIMEN */
489#define WM8985_LIMEN_WIDTH 1 /* LIMEN */
490#define WM8985_LIMDCY_MASK 0x00F0 /* LIMDCY - [7:4] */
491#define WM8985_LIMDCY_SHIFT 4 /* LIMDCY - [7:4] */
492#define WM8985_LIMDCY_WIDTH 4 /* LIMDCY - [7:4] */
493#define WM8985_LIMATK_MASK 0x000F /* LIMATK - [3:0] */
494#define WM8985_LIMATK_SHIFT 0 /* LIMATK - [3:0] */
495#define WM8985_LIMATK_WIDTH 4 /* LIMATK - [3:0] */
496
497/*
498 * R25 (0x19) - DAC Limiter 2
499 */
500#define WM8985_LIMLVL_MASK 0x0070 /* LIMLVL - [6:4] */
501#define WM8985_LIMLVL_SHIFT 4 /* LIMLVL - [6:4] */
502#define WM8985_LIMLVL_WIDTH 3 /* LIMLVL - [6:4] */
503#define WM8985_LIMBOOST_MASK 0x000F /* LIMBOOST - [3:0] */
504#define WM8985_LIMBOOST_SHIFT 0 /* LIMBOOST - [3:0] */
505#define WM8985_LIMBOOST_WIDTH 4 /* LIMBOOST - [3:0] */
506
507/*
508 * R27 (0x1B) - Notch Filter 1
509 */
510#define WM8985_NFU 0x0100 /* NFU */
511#define WM8985_NFU_MASK 0x0100 /* NFU */
512#define WM8985_NFU_SHIFT 8 /* NFU */
513#define WM8985_NFU_WIDTH 1 /* NFU */
514#define WM8985_NFEN 0x0080 /* NFEN */
515#define WM8985_NFEN_MASK 0x0080 /* NFEN */
516#define WM8985_NFEN_SHIFT 7 /* NFEN */
517#define WM8985_NFEN_WIDTH 1 /* NFEN */
518#define WM8985_NFA0_13_7_MASK 0x007F /* NFA0(13:7) - [6:0] */
519#define WM8985_NFA0_13_7_SHIFT 0 /* NFA0(13:7) - [6:0] */
520#define WM8985_NFA0_13_7_WIDTH 7 /* NFA0(13:7) - [6:0] */
521
522/*
523 * R28 (0x1C) - Notch Filter 2
524 */
525#define WM8985_NFU 0x0100 /* NFU */
526#define WM8985_NFU_MASK 0x0100 /* NFU */
527#define WM8985_NFU_SHIFT 8 /* NFU */
528#define WM8985_NFU_WIDTH 1 /* NFU */
529#define WM8985_NFA0_6_0_MASK 0x007F /* NFA0(6:0) - [6:0] */
530#define WM8985_NFA0_6_0_SHIFT 0 /* NFA0(6:0) - [6:0] */
531#define WM8985_NFA0_6_0_WIDTH 7 /* NFA0(6:0) - [6:0] */
532
533/*
534 * R29 (0x1D) - Notch Filter 3
535 */
536#define WM8985_NFU 0x0100 /* NFU */
537#define WM8985_NFU_MASK 0x0100 /* NFU */
538#define WM8985_NFU_SHIFT 8 /* NFU */
539#define WM8985_NFU_WIDTH 1 /* NFU */
540#define WM8985_NFA1_13_7_MASK 0x007F /* NFA1(13:7) - [6:0] */
541#define WM8985_NFA1_13_7_SHIFT 0 /* NFA1(13:7) - [6:0] */
542#define WM8985_NFA1_13_7_WIDTH 7 /* NFA1(13:7) - [6:0] */
543
544/*
545 * R30 (0x1E) - Notch Filter 4
546 */
547#define WM8985_NFU 0x0100 /* NFU */
548#define WM8985_NFU_MASK 0x0100 /* NFU */
549#define WM8985_NFU_SHIFT 8 /* NFU */
550#define WM8985_NFU_WIDTH 1 /* NFU */
551#define WM8985_NFA1_6_0_MASK 0x007F /* NFA1(6:0) - [6:0] */
552#define WM8985_NFA1_6_0_SHIFT 0 /* NFA1(6:0) - [6:0] */
553#define WM8985_NFA1_6_0_WIDTH 7 /* NFA1(6:0) - [6:0] */
554
555/*
556 * R32 (0x20) - ALC control 1
557 */
558#define WM8985_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */
559#define WM8985_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */
560#define WM8985_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */
561#define WM8985_ALCMAX_MASK 0x0038 /* ALCMAX - [5:3] */
562#define WM8985_ALCMAX_SHIFT 3 /* ALCMAX - [5:3] */
563#define WM8985_ALCMAX_WIDTH 3 /* ALCMAX - [5:3] */
564#define WM8985_ALCMIN_MASK 0x0007 /* ALCMIN - [2:0] */
565#define WM8985_ALCMIN_SHIFT 0 /* ALCMIN - [2:0] */
566#define WM8985_ALCMIN_WIDTH 3 /* ALCMIN - [2:0] */
567
568/*
569 * R33 (0x21) - ALC control 2
570 */
571#define WM8985_ALCHLD_MASK 0x00F0 /* ALCHLD - [7:4] */
572#define WM8985_ALCHLD_SHIFT 4 /* ALCHLD - [7:4] */
573#define WM8985_ALCHLD_WIDTH 4 /* ALCHLD - [7:4] */
574#define WM8985_ALCLVL_MASK 0x000F /* ALCLVL - [3:0] */
575#define WM8985_ALCLVL_SHIFT 0 /* ALCLVL - [3:0] */
576#define WM8985_ALCLVL_WIDTH 4 /* ALCLVL - [3:0] */
577
578/*
579 * R34 (0x22) - ALC control 3
580 */
581#define WM8985_ALCMODE 0x0100 /* ALCMODE */
582#define WM8985_ALCMODE_MASK 0x0100 /* ALCMODE */
583#define WM8985_ALCMODE_SHIFT 8 /* ALCMODE */
584#define WM8985_ALCMODE_WIDTH 1 /* ALCMODE */
585#define WM8985_ALCDCY_MASK 0x00F0 /* ALCDCY - [7:4] */
586#define WM8985_ALCDCY_SHIFT 4 /* ALCDCY - [7:4] */
587#define WM8985_ALCDCY_WIDTH 4 /* ALCDCY - [7:4] */
588#define WM8985_ALCATK_MASK 0x000F /* ALCATK - [3:0] */
589#define WM8985_ALCATK_SHIFT 0 /* ALCATK - [3:0] */
590#define WM8985_ALCATK_WIDTH 4 /* ALCATK - [3:0] */
591
592/*
593 * R35 (0x23) - Noise Gate
594 */
595#define WM8985_NGEN 0x0008 /* NGEN */
596#define WM8985_NGEN_MASK 0x0008 /* NGEN */
597#define WM8985_NGEN_SHIFT 3 /* NGEN */
598#define WM8985_NGEN_WIDTH 1 /* NGEN */
599#define WM8985_NGTH_MASK 0x0007 /* NGTH - [2:0] */
600#define WM8985_NGTH_SHIFT 0 /* NGTH - [2:0] */
601#define WM8985_NGTH_WIDTH 3 /* NGTH - [2:0] */
602
603/*
604 * R36 (0x24) - PLL N
605 */
606#define WM8985_PLL_PRESCALE 0x0010 /* PLL_PRESCALE */
607#define WM8985_PLL_PRESCALE_MASK 0x0010 /* PLL_PRESCALE */
608#define WM8985_PLL_PRESCALE_SHIFT 4 /* PLL_PRESCALE */
609#define WM8985_PLL_PRESCALE_WIDTH 1 /* PLL_PRESCALE */
610#define WM8985_PLLN_MASK 0x000F /* PLLN - [3:0] */
611#define WM8985_PLLN_SHIFT 0 /* PLLN - [3:0] */
612#define WM8985_PLLN_WIDTH 4 /* PLLN - [3:0] */
613
614/*
615 * R37 (0x25) - PLL K 1
616 */
617#define WM8985_PLLK_23_18_MASK 0x003F /* PLLK(23:18) - [5:0] */
618#define WM8985_PLLK_23_18_SHIFT 0 /* PLLK(23:18) - [5:0] */
619#define WM8985_PLLK_23_18_WIDTH 6 /* PLLK(23:18) - [5:0] */
620
621/*
622 * R38 (0x26) - PLL K 2
623 */
624#define WM8985_PLLK_17_9_MASK 0x01FF /* PLLK(17:9) - [8:0] */
625#define WM8985_PLLK_17_9_SHIFT 0 /* PLLK(17:9) - [8:0] */
626#define WM8985_PLLK_17_9_WIDTH 9 /* PLLK(17:9) - [8:0] */
627
628/*
629 * R39 (0x27) - PLL K 3
630 */
631#define WM8985_PLLK_8_0_MASK 0x01FF /* PLLK(8:0) - [8:0] */
632#define WM8985_PLLK_8_0_SHIFT 0 /* PLLK(8:0) - [8:0] */
633#define WM8985_PLLK_8_0_WIDTH 9 /* PLLK(8:0) - [8:0] */
634
635/*
636 * R41 (0x29) - 3D control
637 */
638#define WM8985_DEPTH3D_MASK 0x000F /* DEPTH3D - [3:0] */
639#define WM8985_DEPTH3D_SHIFT 0 /* DEPTH3D - [3:0] */
640#define WM8985_DEPTH3D_WIDTH 4 /* DEPTH3D - [3:0] */
641
642/*
643 * R42 (0x2A) - OUT4 to ADC
644 */
645#define WM8985_OUT4_2ADCVOL_MASK 0x01C0 /* OUT4_2ADCVOL - [8:6] */
646#define WM8985_OUT4_2ADCVOL_SHIFT 6 /* OUT4_2ADCVOL - [8:6] */
647#define WM8985_OUT4_2ADCVOL_WIDTH 3 /* OUT4_2ADCVOL - [8:6] */
648#define WM8985_OUT4_2LNR 0x0020 /* OUT4_2LNR */
649#define WM8985_OUT4_2LNR_MASK 0x0020 /* OUT4_2LNR */
650#define WM8985_OUT4_2LNR_SHIFT 5 /* OUT4_2LNR */
651#define WM8985_OUT4_2LNR_WIDTH 1 /* OUT4_2LNR */
652#define WM8985_POBCTRL 0x0004 /* POBCTRL */
653#define WM8985_POBCTRL_MASK 0x0004 /* POBCTRL */
654#define WM8985_POBCTRL_SHIFT 2 /* POBCTRL */
655#define WM8985_POBCTRL_WIDTH 1 /* POBCTRL */
656#define WM8985_DELEN 0x0002 /* DELEN */
657#define WM8985_DELEN_MASK 0x0002 /* DELEN */
658#define WM8985_DELEN_SHIFT 1 /* DELEN */
659#define WM8985_DELEN_WIDTH 1 /* DELEN */
660#define WM8985_OUT1DEL 0x0001 /* OUT1DEL */
661#define WM8985_OUT1DEL_MASK 0x0001 /* OUT1DEL */
662#define WM8985_OUT1DEL_SHIFT 0 /* OUT1DEL */
663#define WM8985_OUT1DEL_WIDTH 1 /* OUT1DEL */
664
665/*
666 * R43 (0x2B) - Beep control
667 */
668#define WM8985_BYPL2RMIX 0x0100 /* BYPL2RMIX */
669#define WM8985_BYPL2RMIX_MASK 0x0100 /* BYPL2RMIX */
670#define WM8985_BYPL2RMIX_SHIFT 8 /* BYPL2RMIX */
671#define WM8985_BYPL2RMIX_WIDTH 1 /* BYPL2RMIX */
672#define WM8985_BYPR2LMIX 0x0080 /* BYPR2LMIX */
673#define WM8985_BYPR2LMIX_MASK 0x0080 /* BYPR2LMIX */
674#define WM8985_BYPR2LMIX_SHIFT 7 /* BYPR2LMIX */
675#define WM8985_BYPR2LMIX_WIDTH 1 /* BYPR2LMIX */
676#define WM8985_MUTERPGA2INV 0x0020 /* MUTERPGA2INV */
677#define WM8985_MUTERPGA2INV_MASK 0x0020 /* MUTERPGA2INV */
678#define WM8985_MUTERPGA2INV_SHIFT 5 /* MUTERPGA2INV */
679#define WM8985_MUTERPGA2INV_WIDTH 1 /* MUTERPGA2INV */
680#define WM8985_INVROUT2 0x0010 /* INVROUT2 */
681#define WM8985_INVROUT2_MASK 0x0010 /* INVROUT2 */
682#define WM8985_INVROUT2_SHIFT 4 /* INVROUT2 */
683#define WM8985_INVROUT2_WIDTH 1 /* INVROUT2 */
684#define WM8985_BEEPVOL_MASK 0x000E /* BEEPVOL - [3:1] */
685#define WM8985_BEEPVOL_SHIFT 1 /* BEEPVOL - [3:1] */
686#define WM8985_BEEPVOL_WIDTH 3 /* BEEPVOL - [3:1] */
687#define WM8985_BEEPEN 0x0001 /* BEEPEN */
688#define WM8985_BEEPEN_MASK 0x0001 /* BEEPEN */
689#define WM8985_BEEPEN_SHIFT 0 /* BEEPEN */
690#define WM8985_BEEPEN_WIDTH 1 /* BEEPEN */
691
692/*
693 * R44 (0x2C) - Input ctrl
694 */
695#define WM8985_MBVSEL 0x0100 /* MBVSEL */
696#define WM8985_MBVSEL_MASK 0x0100 /* MBVSEL */
697#define WM8985_MBVSEL_SHIFT 8 /* MBVSEL */
698#define WM8985_MBVSEL_WIDTH 1 /* MBVSEL */
699#define WM8985_R2_2INPPGA 0x0040 /* R2_2INPPGA */
700#define WM8985_R2_2INPPGA_MASK 0x0040 /* R2_2INPPGA */
701#define WM8985_R2_2INPPGA_SHIFT 6 /* R2_2INPPGA */
702#define WM8985_R2_2INPPGA_WIDTH 1 /* R2_2INPPGA */
703#define WM8985_RIN2INPPGA 0x0020 /* RIN2INPPGA */
704#define WM8985_RIN2INPPGA_MASK 0x0020 /* RIN2INPPGA */
705#define WM8985_RIN2INPPGA_SHIFT 5 /* RIN2INPPGA */
706#define WM8985_RIN2INPPGA_WIDTH 1 /* RIN2INPPGA */
707#define WM8985_RIP2INPPGA 0x0010 /* RIP2INPPGA */
708#define WM8985_RIP2INPPGA_MASK 0x0010 /* RIP2INPPGA */
709#define WM8985_RIP2INPPGA_SHIFT 4 /* RIP2INPPGA */
710#define WM8985_RIP2INPPGA_WIDTH 1 /* RIP2INPPGA */
711#define WM8985_L2_2INPPGA 0x0004 /* L2_2INPPGA */
712#define WM8985_L2_2INPPGA_MASK 0x0004 /* L2_2INPPGA */
713#define WM8985_L2_2INPPGA_SHIFT 2 /* L2_2INPPGA */
714#define WM8985_L2_2INPPGA_WIDTH 1 /* L2_2INPPGA */
715#define WM8985_LIN2INPPGA 0x0002 /* LIN2INPPGA */
716#define WM8985_LIN2INPPGA_MASK 0x0002 /* LIN2INPPGA */
717#define WM8985_LIN2INPPGA_SHIFT 1 /* LIN2INPPGA */
718#define WM8985_LIN2INPPGA_WIDTH 1 /* LIN2INPPGA */
719#define WM8985_LIP2INPPGA 0x0001 /* LIP2INPPGA */
720#define WM8985_LIP2INPPGA_MASK 0x0001 /* LIP2INPPGA */
721#define WM8985_LIP2INPPGA_SHIFT 0 /* LIP2INPPGA */
722#define WM8985_LIP2INPPGA_WIDTH 1 /* LIP2INPPGA */
723
724/*
725 * R45 (0x2D) - Left INP PGA gain ctrl
726 */
727#define WM8985_INPGAVU 0x0100 /* INPGAVU */
728#define WM8985_INPGAVU_MASK 0x0100 /* INPGAVU */
729#define WM8985_INPGAVU_SHIFT 8 /* INPGAVU */
730#define WM8985_INPGAVU_WIDTH 1 /* INPGAVU */
731#define WM8985_INPPGAZCL 0x0080 /* INPPGAZCL */
732#define WM8985_INPPGAZCL_MASK 0x0080 /* INPPGAZCL */
733#define WM8985_INPPGAZCL_SHIFT 7 /* INPPGAZCL */
734#define WM8985_INPPGAZCL_WIDTH 1 /* INPPGAZCL */
735#define WM8985_INPPGAMUTEL 0x0040 /* INPPGAMUTEL */
736#define WM8985_INPPGAMUTEL_MASK 0x0040 /* INPPGAMUTEL */
737#define WM8985_INPPGAMUTEL_SHIFT 6 /* INPPGAMUTEL */
738#define WM8985_INPPGAMUTEL_WIDTH 1 /* INPPGAMUTEL */
739#define WM8985_INPPGAVOLL_MASK 0x003F /* INPPGAVOLL - [5:0] */
740#define WM8985_INPPGAVOLL_SHIFT 0 /* INPPGAVOLL - [5:0] */
741#define WM8985_INPPGAVOLL_WIDTH 6 /* INPPGAVOLL - [5:0] */
742
743/*
744 * R46 (0x2E) - Right INP PGA gain ctrl
745 */
746#define WM8985_INPGAVU 0x0100 /* INPGAVU */
747#define WM8985_INPGAVU_MASK 0x0100 /* INPGAVU */
748#define WM8985_INPGAVU_SHIFT 8 /* INPGAVU */
749#define WM8985_INPGAVU_WIDTH 1 /* INPGAVU */
750#define WM8985_INPPGAZCR 0x0080 /* INPPGAZCR */
751#define WM8985_INPPGAZCR_MASK 0x0080 /* INPPGAZCR */
752#define WM8985_INPPGAZCR_SHIFT 7 /* INPPGAZCR */
753#define WM8985_INPPGAZCR_WIDTH 1 /* INPPGAZCR */
754#define WM8985_INPPGAMUTER 0x0040 /* INPPGAMUTER */
755#define WM8985_INPPGAMUTER_MASK 0x0040 /* INPPGAMUTER */
756#define WM8985_INPPGAMUTER_SHIFT 6 /* INPPGAMUTER */
757#define WM8985_INPPGAMUTER_WIDTH 1 /* INPPGAMUTER */
758#define WM8985_INPPGAVOLR_MASK 0x003F /* INPPGAVOLR - [5:0] */
759#define WM8985_INPPGAVOLR_SHIFT 0 /* INPPGAVOLR - [5:0] */
760#define WM8985_INPPGAVOLR_WIDTH 6 /* INPPGAVOLR - [5:0] */
761
762/*
763 * R47 (0x2F) - Left ADC BOOST ctrl
764 */
765#define WM8985_PGABOOSTL 0x0100 /* PGABOOSTL */
766#define WM8985_PGABOOSTL_MASK 0x0100 /* PGABOOSTL */
767#define WM8985_PGABOOSTL_SHIFT 8 /* PGABOOSTL */
768#define WM8985_PGABOOSTL_WIDTH 1 /* PGABOOSTL */
769#define WM8985_L2_2BOOSTVOL_MASK 0x0070 /* L2_2BOOSTVOL - [6:4] */
770#define WM8985_L2_2BOOSTVOL_SHIFT 4 /* L2_2BOOSTVOL - [6:4] */
771#define WM8985_L2_2BOOSTVOL_WIDTH 3 /* L2_2BOOSTVOL - [6:4] */
772#define WM8985_AUXL2BOOSTVOL_MASK 0x0007 /* AUXL2BOOSTVOL - [2:0] */
773#define WM8985_AUXL2BOOSTVOL_SHIFT 0 /* AUXL2BOOSTVOL - [2:0] */
774#define WM8985_AUXL2BOOSTVOL_WIDTH 3 /* AUXL2BOOSTVOL - [2:0] */
775
776/*
777 * R48 (0x30) - Right ADC BOOST ctrl
778 */
779#define WM8985_PGABOOSTR 0x0100 /* PGABOOSTR */
780#define WM8985_PGABOOSTR_MASK 0x0100 /* PGABOOSTR */
781#define WM8985_PGABOOSTR_SHIFT 8 /* PGABOOSTR */
782#define WM8985_PGABOOSTR_WIDTH 1 /* PGABOOSTR */
783#define WM8985_R2_2BOOSTVOL_MASK 0x0070 /* R2_2BOOSTVOL - [6:4] */
784#define WM8985_R2_2BOOSTVOL_SHIFT 4 /* R2_2BOOSTVOL - [6:4] */
785#define WM8985_R2_2BOOSTVOL_WIDTH 3 /* R2_2BOOSTVOL - [6:4] */
786#define WM8985_AUXR2BOOSTVOL_MASK 0x0007 /* AUXR2BOOSTVOL - [2:0] */
787#define WM8985_AUXR2BOOSTVOL_SHIFT 0 /* AUXR2BOOSTVOL - [2:0] */
788#define WM8985_AUXR2BOOSTVOL_WIDTH 3 /* AUXR2BOOSTVOL - [2:0] */
789
790/*
791 * R49 (0x31) - Output ctrl
792 */
793#define WM8985_DACL2RMIX 0x0040 /* DACL2RMIX */
794#define WM8985_DACL2RMIX_MASK 0x0040 /* DACL2RMIX */
795#define WM8985_DACL2RMIX_SHIFT 6 /* DACL2RMIX */
796#define WM8985_DACL2RMIX_WIDTH 1 /* DACL2RMIX */
797#define WM8985_DACR2LMIX 0x0020 /* DACR2LMIX */
798#define WM8985_DACR2LMIX_MASK 0x0020 /* DACR2LMIX */
799#define WM8985_DACR2LMIX_SHIFT 5 /* DACR2LMIX */
800#define WM8985_DACR2LMIX_WIDTH 1 /* DACR2LMIX */
801#define WM8985_OUT4BOOST 0x0010 /* OUT4BOOST */
802#define WM8985_OUT4BOOST_MASK 0x0010 /* OUT4BOOST */
803#define WM8985_OUT4BOOST_SHIFT 4 /* OUT4BOOST */
804#define WM8985_OUT4BOOST_WIDTH 1 /* OUT4BOOST */
805#define WM8985_OUT3BOOST 0x0008 /* OUT3BOOST */
806#define WM8985_OUT3BOOST_MASK 0x0008 /* OUT3BOOST */
807#define WM8985_OUT3BOOST_SHIFT 3 /* OUT3BOOST */
808#define WM8985_OUT3BOOST_WIDTH 1 /* OUT3BOOST */
809#define WM8985_TSOPCTRL 0x0004 /* TSOPCTRL */
810#define WM8985_TSOPCTRL_MASK 0x0004 /* TSOPCTRL */
811#define WM8985_TSOPCTRL_SHIFT 2 /* TSOPCTRL */
812#define WM8985_TSOPCTRL_WIDTH 1 /* TSOPCTRL */
813#define WM8985_TSDEN 0x0002 /* TSDEN */
814#define WM8985_TSDEN_MASK 0x0002 /* TSDEN */
815#define WM8985_TSDEN_SHIFT 1 /* TSDEN */
816#define WM8985_TSDEN_WIDTH 1 /* TSDEN */
817#define WM8985_VROI 0x0001 /* VROI */
818#define WM8985_VROI_MASK 0x0001 /* VROI */
819#define WM8985_VROI_SHIFT 0 /* VROI */
820#define WM8985_VROI_WIDTH 1 /* VROI */
821
822/*
823 * R50 (0x32) - Left mixer ctrl
824 */
825#define WM8985_AUXLMIXVOL_MASK 0x01C0 /* AUXLMIXVOL - [8:6] */
826#define WM8985_AUXLMIXVOL_SHIFT 6 /* AUXLMIXVOL - [8:6] */
827#define WM8985_AUXLMIXVOL_WIDTH 3 /* AUXLMIXVOL - [8:6] */
828#define WM8985_AUXL2LMIX 0x0020 /* AUXL2LMIX */
829#define WM8985_AUXL2LMIX_MASK 0x0020 /* AUXL2LMIX */
830#define WM8985_AUXL2LMIX_SHIFT 5 /* AUXL2LMIX */
831#define WM8985_AUXL2LMIX_WIDTH 1 /* AUXL2LMIX */
832#define WM8985_BYPLMIXVOL_MASK 0x001C /* BYPLMIXVOL - [4:2] */
833#define WM8985_BYPLMIXVOL_SHIFT 2 /* BYPLMIXVOL - [4:2] */
834#define WM8985_BYPLMIXVOL_WIDTH 3 /* BYPLMIXVOL - [4:2] */
835#define WM8985_BYPL2LMIX 0x0002 /* BYPL2LMIX */
836#define WM8985_BYPL2LMIX_MASK 0x0002 /* BYPL2LMIX */
837#define WM8985_BYPL2LMIX_SHIFT 1 /* BYPL2LMIX */
838#define WM8985_BYPL2LMIX_WIDTH 1 /* BYPL2LMIX */
839#define WM8985_DACL2LMIX 0x0001 /* DACL2LMIX */
840#define WM8985_DACL2LMIX_MASK 0x0001 /* DACL2LMIX */
841#define WM8985_DACL2LMIX_SHIFT 0 /* DACL2LMIX */
842#define WM8985_DACL2LMIX_WIDTH 1 /* DACL2LMIX */
843
844/*
845 * R51 (0x33) - Right mixer ctrl
846 */
847#define WM8985_AUXRMIXVOL_MASK 0x01C0 /* AUXRMIXVOL - [8:6] */
848#define WM8985_AUXRMIXVOL_SHIFT 6 /* AUXRMIXVOL - [8:6] */
849#define WM8985_AUXRMIXVOL_WIDTH 3 /* AUXRMIXVOL - [8:6] */
850#define WM8985_AUXR2RMIX 0x0020 /* AUXR2RMIX */
851#define WM8985_AUXR2RMIX_MASK 0x0020 /* AUXR2RMIX */
852#define WM8985_AUXR2RMIX_SHIFT 5 /* AUXR2RMIX */
853#define WM8985_AUXR2RMIX_WIDTH 1 /* AUXR2RMIX */
854#define WM8985_BYPRMIXVOL_MASK 0x001C /* BYPRMIXVOL - [4:2] */
855#define WM8985_BYPRMIXVOL_SHIFT 2 /* BYPRMIXVOL - [4:2] */
856#define WM8985_BYPRMIXVOL_WIDTH 3 /* BYPRMIXVOL - [4:2] */
857#define WM8985_BYPR2RMIX 0x0002 /* BYPR2RMIX */
858#define WM8985_BYPR2RMIX_MASK 0x0002 /* BYPR2RMIX */
859#define WM8985_BYPR2RMIX_SHIFT 1 /* BYPR2RMIX */
860#define WM8985_BYPR2RMIX_WIDTH 1 /* BYPR2RMIX */
861#define WM8985_DACR2RMIX 0x0001 /* DACR2RMIX */
862#define WM8985_DACR2RMIX_MASK 0x0001 /* DACR2RMIX */
863#define WM8985_DACR2RMIX_SHIFT 0 /* DACR2RMIX */
864#define WM8985_DACR2RMIX_WIDTH 1 /* DACR2RMIX */
865
866/*
867 * R52 (0x34) - LOUT1 (HP) volume ctrl
868 */
869#define WM8985_OUT1VU 0x0100 /* OUT1VU */
870#define WM8985_OUT1VU_MASK 0x0100 /* OUT1VU */
871#define WM8985_OUT1VU_SHIFT 8 /* OUT1VU */
872#define WM8985_OUT1VU_WIDTH 1 /* OUT1VU */
873#define WM8985_LOUT1ZC 0x0080 /* LOUT1ZC */
874#define WM8985_LOUT1ZC_MASK 0x0080 /* LOUT1ZC */
875#define WM8985_LOUT1ZC_SHIFT 7 /* LOUT1ZC */
876#define WM8985_LOUT1ZC_WIDTH 1 /* LOUT1ZC */
877#define WM8985_LOUT1MUTE 0x0040 /* LOUT1MUTE */
878#define WM8985_LOUT1MUTE_MASK 0x0040 /* LOUT1MUTE */
879#define WM8985_LOUT1MUTE_SHIFT 6 /* LOUT1MUTE */
880#define WM8985_LOUT1MUTE_WIDTH 1 /* LOUT1MUTE */
881#define WM8985_LOUT1VOL_MASK 0x003F /* LOUT1VOL - [5:0] */
882#define WM8985_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [5:0] */
883#define WM8985_LOUT1VOL_WIDTH 6 /* LOUT1VOL - [5:0] */
884
885/*
886 * R53 (0x35) - ROUT1 (HP) volume ctrl
887 */
888#define WM8985_OUT1VU 0x0100 /* OUT1VU */
889#define WM8985_OUT1VU_MASK 0x0100 /* OUT1VU */
890#define WM8985_OUT1VU_SHIFT 8 /* OUT1VU */
891#define WM8985_OUT1VU_WIDTH 1 /* OUT1VU */
892#define WM8985_ROUT1ZC 0x0080 /* ROUT1ZC */
893#define WM8985_ROUT1ZC_MASK 0x0080 /* ROUT1ZC */
894#define WM8985_ROUT1ZC_SHIFT 7 /* ROUT1ZC */
895#define WM8985_ROUT1ZC_WIDTH 1 /* ROUT1ZC */
896#define WM8985_ROUT1MUTE 0x0040 /* ROUT1MUTE */
897#define WM8985_ROUT1MUTE_MASK 0x0040 /* ROUT1MUTE */
898#define WM8985_ROUT1MUTE_SHIFT 6 /* ROUT1MUTE */
899#define WM8985_ROUT1MUTE_WIDTH 1 /* ROUT1MUTE */
900#define WM8985_ROUT1VOL_MASK 0x003F /* ROUT1VOL - [5:0] */
901#define WM8985_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [5:0] */
902#define WM8985_ROUT1VOL_WIDTH 6 /* ROUT1VOL - [5:0] */
903
904/*
905 * R54 (0x36) - LOUT2 (SPK) volume ctrl
906 */
907#define WM8985_OUT2VU 0x0100 /* OUT2VU */
908#define WM8985_OUT2VU_MASK 0x0100 /* OUT2VU */
909#define WM8985_OUT2VU_SHIFT 8 /* OUT2VU */
910#define WM8985_OUT2VU_WIDTH 1 /* OUT2VU */
911#define WM8985_LOUT2ZC 0x0080 /* LOUT2ZC */
912#define WM8985_LOUT2ZC_MASK 0x0080 /* LOUT2ZC */
913#define WM8985_LOUT2ZC_SHIFT 7 /* LOUT2ZC */
914#define WM8985_LOUT2ZC_WIDTH 1 /* LOUT2ZC */
915#define WM8985_LOUT2MUTE 0x0040 /* LOUT2MUTE */
916#define WM8985_LOUT2MUTE_MASK 0x0040 /* LOUT2MUTE */
917#define WM8985_LOUT2MUTE_SHIFT 6 /* LOUT2MUTE */
918#define WM8985_LOUT2MUTE_WIDTH 1 /* LOUT2MUTE */
919#define WM8985_LOUT2VOL_MASK 0x003F /* LOUT2VOL - [5:0] */
920#define WM8985_LOUT2VOL_SHIFT 0 /* LOUT2VOL - [5:0] */
921#define WM8985_LOUT2VOL_WIDTH 6 /* LOUT2VOL - [5:0] */
922
923/*
924 * R55 (0x37) - ROUT2 (SPK) volume ctrl
925 */
926#define WM8985_OUT2VU 0x0100 /* OUT2VU */
927#define WM8985_OUT2VU_MASK 0x0100 /* OUT2VU */
928#define WM8985_OUT2VU_SHIFT 8 /* OUT2VU */
929#define WM8985_OUT2VU_WIDTH 1 /* OUT2VU */
930#define WM8985_ROUT2ZC 0x0080 /* ROUT2ZC */
931#define WM8985_ROUT2ZC_MASK 0x0080 /* ROUT2ZC */
932#define WM8985_ROUT2ZC_SHIFT 7 /* ROUT2ZC */
933#define WM8985_ROUT2ZC_WIDTH 1 /* ROUT2ZC */
934#define WM8985_ROUT2MUTE 0x0040 /* ROUT2MUTE */
935#define WM8985_ROUT2MUTE_MASK 0x0040 /* ROUT2MUTE */
936#define WM8985_ROUT2MUTE_SHIFT 6 /* ROUT2MUTE */
937#define WM8985_ROUT2MUTE_WIDTH 1 /* ROUT2MUTE */
938#define WM8985_ROUT2VOL_MASK 0x003F /* ROUT2VOL - [5:0] */
939#define WM8985_ROUT2VOL_SHIFT 0 /* ROUT2VOL - [5:0] */
940#define WM8985_ROUT2VOL_WIDTH 6 /* ROUT2VOL - [5:0] */
941
942/*
943 * R56 (0x38) - OUT3 mixer ctrl
944 */
945#define WM8985_OUT3MUTE 0x0040 /* OUT3MUTE */
946#define WM8985_OUT3MUTE_MASK 0x0040 /* OUT3MUTE */
947#define WM8985_OUT3MUTE_SHIFT 6 /* OUT3MUTE */
948#define WM8985_OUT3MUTE_WIDTH 1 /* OUT3MUTE */
949#define WM8985_OUT4_2OUT3 0x0008 /* OUT4_2OUT3 */
950#define WM8985_OUT4_2OUT3_MASK 0x0008 /* OUT4_2OUT3 */
951#define WM8985_OUT4_2OUT3_SHIFT 3 /* OUT4_2OUT3 */
952#define WM8985_OUT4_2OUT3_WIDTH 1 /* OUT4_2OUT3 */
953#define WM8985_BYPL2OUT3 0x0004 /* BYPL2OUT3 */
954#define WM8985_BYPL2OUT3_MASK 0x0004 /* BYPL2OUT3 */
955#define WM8985_BYPL2OUT3_SHIFT 2 /* BYPL2OUT3 */
956#define WM8985_BYPL2OUT3_WIDTH 1 /* BYPL2OUT3 */
957#define WM8985_LMIX2OUT3 0x0002 /* LMIX2OUT3 */
958#define WM8985_LMIX2OUT3_MASK 0x0002 /* LMIX2OUT3 */
959#define WM8985_LMIX2OUT3_SHIFT 1 /* LMIX2OUT3 */
960#define WM8985_LMIX2OUT3_WIDTH 1 /* LMIX2OUT3 */
961#define WM8985_LDAC2OUT3 0x0001 /* LDAC2OUT3 */
962#define WM8985_LDAC2OUT3_MASK 0x0001 /* LDAC2OUT3 */
963#define WM8985_LDAC2OUT3_SHIFT 0 /* LDAC2OUT3 */
964#define WM8985_LDAC2OUT3_WIDTH 1 /* LDAC2OUT3 */
965
966/*
967 * R57 (0x39) - OUT4 (MONO) mix ctrl
968 */
969#define WM8985_OUT3_2OUT4 0x0080 /* OUT3_2OUT4 */
970#define WM8985_OUT3_2OUT4_MASK 0x0080 /* OUT3_2OUT4 */
971#define WM8985_OUT3_2OUT4_SHIFT 7 /* OUT3_2OUT4 */
972#define WM8985_OUT3_2OUT4_WIDTH 1 /* OUT3_2OUT4 */
973#define WM8985_OUT4MUTE 0x0040 /* OUT4MUTE */
974#define WM8985_OUT4MUTE_MASK 0x0040 /* OUT4MUTE */
975#define WM8985_OUT4MUTE_SHIFT 6 /* OUT4MUTE */
976#define WM8985_OUT4MUTE_WIDTH 1 /* OUT4MUTE */
977#define WM8985_OUT4ATTN 0x0020 /* OUT4ATTN */
978#define WM8985_OUT4ATTN_MASK 0x0020 /* OUT4ATTN */
979#define WM8985_OUT4ATTN_SHIFT 5 /* OUT4ATTN */
980#define WM8985_OUT4ATTN_WIDTH 1 /* OUT4ATTN */
981#define WM8985_LMIX2OUT4 0x0010 /* LMIX2OUT4 */
982#define WM8985_LMIX2OUT4_MASK 0x0010 /* LMIX2OUT4 */
983#define WM8985_LMIX2OUT4_SHIFT 4 /* LMIX2OUT4 */
984#define WM8985_LMIX2OUT4_WIDTH 1 /* LMIX2OUT4 */
985#define WM8985_LDAC2OUT4 0x0008 /* LDAC2OUT4 */
986#define WM8985_LDAC2OUT4_MASK 0x0008 /* LDAC2OUT4 */
987#define WM8985_LDAC2OUT4_SHIFT 3 /* LDAC2OUT4 */
988#define WM8985_LDAC2OUT4_WIDTH 1 /* LDAC2OUT4 */
989#define WM8985_BYPR2OUT4 0x0004 /* BYPR2OUT4 */
990#define WM8985_BYPR2OUT4_MASK 0x0004 /* BYPR2OUT4 */
991#define WM8985_BYPR2OUT4_SHIFT 2 /* BYPR2OUT4 */
992#define WM8985_BYPR2OUT4_WIDTH 1 /* BYPR2OUT4 */
993#define WM8985_RMIX2OUT4 0x0002 /* RMIX2OUT4 */
994#define WM8985_RMIX2OUT4_MASK 0x0002 /* RMIX2OUT4 */
995#define WM8985_RMIX2OUT4_SHIFT 1 /* RMIX2OUT4 */
996#define WM8985_RMIX2OUT4_WIDTH 1 /* RMIX2OUT4 */
997#define WM8985_RDAC2OUT4 0x0001 /* RDAC2OUT4 */
998#define WM8985_RDAC2OUT4_MASK 0x0001 /* RDAC2OUT4 */
999#define WM8985_RDAC2OUT4_SHIFT 0 /* RDAC2OUT4 */
1000#define WM8985_RDAC2OUT4_WIDTH 1 /* RDAC2OUT4 */
1001
1002/*
1003 * R60 (0x3C) - OUTPUT ctrl
1004 */
1005#define WM8985_VIDBUFFTST_MASK 0x01E0 /* VIDBUFFTST - [8:5] */
1006#define WM8985_VIDBUFFTST_SHIFT 5 /* VIDBUFFTST - [8:5] */
1007#define WM8985_VIDBUFFTST_WIDTH 4 /* VIDBUFFTST - [8:5] */
1008#define WM8985_HPTOG 0x0008 /* HPTOG */
1009#define WM8985_HPTOG_MASK 0x0008 /* HPTOG */
1010#define WM8985_HPTOG_SHIFT 3 /* HPTOG */
1011#define WM8985_HPTOG_WIDTH 1 /* HPTOG */
1012
1013/*
1014 * R61 (0x3D) - BIAS CTRL
1015 */
1016#define WM8985_BIASCUT 0x0100 /* BIASCUT */
1017#define WM8985_BIASCUT_MASK 0x0100 /* BIASCUT */
1018#define WM8985_BIASCUT_SHIFT 8 /* BIASCUT */
1019#define WM8985_BIASCUT_WIDTH 1 /* BIASCUT */
1020#define WM8985_HALFIPBIAS 0x0080 /* HALFIPBIAS */
1021#define WM8985_HALFIPBIAS_MASK 0x0080 /* HALFIPBIAS */
1022#define WM8985_HALFIPBIAS_SHIFT 7 /* HALFIPBIAS */
1023#define WM8985_HALFIPBIAS_WIDTH 1 /* HALFIPBIAS */
1024#define WM8985_VBBIASTST_MASK 0x0060 /* VBBIASTST - [6:5] */
1025#define WM8985_VBBIASTST_SHIFT 5 /* VBBIASTST - [6:5] */
1026#define WM8985_VBBIASTST_WIDTH 2 /* VBBIASTST - [6:5] */
1027#define WM8985_BUFBIAS_MASK 0x0018 /* BUFBIAS - [4:3] */
1028#define WM8985_BUFBIAS_SHIFT 3 /* BUFBIAS - [4:3] */
1029#define WM8985_BUFBIAS_WIDTH 2 /* BUFBIAS - [4:3] */
1030#define WM8985_ADCBIAS_MASK 0x0006 /* ADCBIAS - [2:1] */
1031#define WM8985_ADCBIAS_SHIFT 1 /* ADCBIAS - [2:1] */
1032#define WM8985_ADCBIAS_WIDTH 2 /* ADCBIAS - [2:1] */
1033#define WM8985_HALFOPBIAS 0x0001 /* HALFOPBIAS */
1034#define WM8985_HALFOPBIAS_MASK 0x0001 /* HALFOPBIAS */
1035#define WM8985_HALFOPBIAS_SHIFT 0 /* HALFOPBIAS */
1036#define WM8985_HALFOPBIAS_WIDTH 1 /* HALFOPBIAS */
1037
1038enum clk_src {
1039 WM8985_CLKSRC_MCLK,
1040 WM8985_CLKSRC_PLL
1041};
1042
1043#define WM8985_PLL 0
1044
1045#endif
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 19ad590ca0b3..d7f259711970 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -52,7 +52,7 @@ static const u16 wm8988_reg[] = {
52/* codec private data */ 52/* codec private data */
53struct wm8988_priv { 53struct wm8988_priv {
54 unsigned int sysclk; 54 unsigned int sysclk;
55 struct snd_soc_codec codec; 55 enum snd_soc_control_type control_type;
56 struct snd_pcm_hw_constraint_list *sysclk_constraints; 56 struct snd_pcm_hw_constraint_list *sysclk_constraints;
57 u16 reg_cache[WM8988_NUM_REG]; 57 u16 reg_cache[WM8988_NUM_REG];
58}; 58};
@@ -608,8 +608,7 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
608 struct snd_soc_dai *dai) 608 struct snd_soc_dai *dai)
609{ 609{
610 struct snd_soc_pcm_runtime *rtd = substream->private_data; 610 struct snd_soc_pcm_runtime *rtd = substream->private_data;
611 struct snd_soc_device *socdev = rtd->socdev; 611 struct snd_soc_codec *codec = rtd->codec;
612 struct snd_soc_codec *codec = socdev->card->codec;
613 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec); 612 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
614 u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; 613 u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
615 u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; 614 u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
@@ -711,8 +710,8 @@ static struct snd_soc_dai_ops wm8988_ops = {
711 .digital_mute = wm8988_mute, 710 .digital_mute = wm8988_mute,
712}; 711};
713 712
714struct snd_soc_dai wm8988_dai = { 713static struct snd_soc_dai_driver wm8988_dai = {
715 .name = "WM8988", 714 .name = "wm8988-hifi",
716 .playback = { 715 .playback = {
717 .stream_name = "Playback", 716 .stream_name = "Playback",
718 .channels_min = 1, 717 .channels_min = 1,
@@ -730,21 +729,15 @@ struct snd_soc_dai wm8988_dai = {
730 .ops = &wm8988_ops, 729 .ops = &wm8988_ops,
731 .symmetric_rates = 1, 730 .symmetric_rates = 1,
732}; 731};
733EXPORT_SYMBOL_GPL(wm8988_dai);
734 732
735static int wm8988_suspend(struct platform_device *pdev, pm_message_t state) 733static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
736{ 734{
737 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
738 struct snd_soc_codec *codec = socdev->card->codec;
739
740 wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF); 735 wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
741 return 0; 736 return 0;
742} 737}
743 738
744static int wm8988_resume(struct platform_device *pdev) 739static int wm8988_resume(struct snd_soc_codec *codec)
745{ 740{
746 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
747 struct snd_soc_codec *codec = socdev->card->codec;
748 int i; 741 int i;
749 u8 data[2]; 742 u8 data[2];
750 u16 *cache = codec->reg_cache; 743 u16 *cache = codec->reg_cache;
@@ -763,99 +756,22 @@ static int wm8988_resume(struct platform_device *pdev)
763 return 0; 756 return 0;
764} 757}
765 758
766static struct snd_soc_codec *wm8988_codec; 759static int wm8988_probe(struct snd_soc_codec *codec)
767
768static int wm8988_probe(struct platform_device *pdev)
769{ 760{
770 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 761 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
771 struct snd_soc_codec *codec;
772 int ret = 0; 762 int ret = 0;
773
774 if (wm8988_codec == NULL) {
775 dev_err(&pdev->dev, "Codec device not registered\n");
776 return -ENODEV;
777 }
778
779 socdev->card->codec = wm8988_codec;
780 codec = wm8988_codec;
781
782 /* register pcms */
783 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
784 if (ret < 0) {
785 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
786 goto pcm_err;
787 }
788
789 snd_soc_add_controls(codec, wm8988_snd_controls,
790 ARRAY_SIZE(wm8988_snd_controls));
791 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
792 ARRAY_SIZE(wm8988_dapm_widgets));
793 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
794
795 return ret;
796
797pcm_err:
798 return ret;
799}
800
801static int wm8988_remove(struct platform_device *pdev)
802{
803 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
804
805 snd_soc_free_pcms(socdev);
806 snd_soc_dapm_free(socdev);
807
808 return 0;
809}
810
811struct snd_soc_codec_device soc_codec_dev_wm8988 = {
812 .probe = wm8988_probe,
813 .remove = wm8988_remove,
814 .suspend = wm8988_suspend,
815 .resume = wm8988_resume,
816};
817EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988);
818
819static int wm8988_register(struct wm8988_priv *wm8988,
820 enum snd_soc_control_type control)
821{
822 struct snd_soc_codec *codec = &wm8988->codec;
823 int ret;
824 u16 reg; 763 u16 reg;
825 764
826 if (wm8988_codec) { 765 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
827 dev_err(codec->dev, "Another WM8988 is registered\n");
828 ret = -EINVAL;
829 goto err;
830 }
831
832 mutex_init(&codec->mutex);
833 INIT_LIST_HEAD(&codec->dapm_widgets);
834 INIT_LIST_HEAD(&codec->dapm_paths);
835
836 snd_soc_codec_set_drvdata(codec, wm8988);
837 codec->name = "WM8988";
838 codec->owner = THIS_MODULE;
839 codec->dai = &wm8988_dai;
840 codec->num_dai = 1;
841 codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
842 codec->reg_cache = &wm8988->reg_cache;
843 codec->bias_level = SND_SOC_BIAS_OFF;
844 codec->set_bias_level = wm8988_set_bias_level;
845
846 memcpy(codec->reg_cache, wm8988_reg,
847 sizeof(wm8988_reg));
848
849 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
850 if (ret < 0) { 766 if (ret < 0) {
851 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 767 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
852 goto err; 768 return ret;
853 } 769 }
854 770
855 ret = wm8988_reset(codec); 771 ret = wm8988_reset(codec);
856 if (ret < 0) { 772 if (ret < 0) {
857 dev_err(codec->dev, "Failed to issue reset\n"); 773 dev_err(codec->dev, "Failed to issue reset\n");
858 goto err; 774 return ret;
859 } 775 }
860 776
861 /* set the update bits (we always update left then right) */ 777 /* set the update bits (we always update left then right) */
@@ -870,139 +786,132 @@ static int wm8988_register(struct wm8988_priv *wm8988,
870 reg = snd_soc_read(codec, WM8988_RINVOL); 786 reg = snd_soc_read(codec, WM8988_RINVOL);
871 snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); 787 snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
872 788
873 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); 789 wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
874
875 wm8988_dai.dev = codec->dev;
876
877 wm8988_codec = codec;
878
879 ret = snd_soc_register_codec(codec);
880 if (ret != 0) {
881 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
882 goto err;
883 }
884 790
885 ret = snd_soc_register_dai(&wm8988_dai); 791 snd_soc_add_controls(codec, wm8988_snd_controls,
886 if (ret != 0) { 792 ARRAY_SIZE(wm8988_snd_controls));
887 dev_err(codec->dev, "Failed to register DAI: %d\n", ret); 793 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
888 goto err_codec; 794 ARRAY_SIZE(wm8988_dapm_widgets));
889 } 795 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
890 796
891 return 0; 797 return 0;
892
893err_codec:
894 snd_soc_unregister_codec(codec);
895err:
896 kfree(wm8988);
897 return ret;
898} 798}
899 799
900static void wm8988_unregister(struct wm8988_priv *wm8988) 800static int wm8988_remove(struct snd_soc_codec *codec)
901{ 801{
902 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_OFF); 802 wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
903 snd_soc_unregister_dai(&wm8988_dai); 803 return 0;
904 snd_soc_unregister_codec(&wm8988->codec);
905 kfree(wm8988);
906 wm8988_codec = NULL;
907} 804}
908 805
909#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 806static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
910static int wm8988_i2c_probe(struct i2c_client *i2c, 807 .probe = wm8988_probe,
911 const struct i2c_device_id *id) 808 .remove = wm8988_remove,
809 .suspend = wm8988_suspend,
810 .resume = wm8988_resume,
811 .set_bias_level = wm8988_set_bias_level,
812 .reg_cache_size = ARRAY_SIZE(wm8988_reg),
813 .reg_word_size = sizeof(u16),
814 .reg_cache_default = wm8988_reg,
815};
816
817#if defined(CONFIG_SPI_MASTER)
818static int __devinit wm8988_spi_probe(struct spi_device *spi)
912{ 819{
913 struct wm8988_priv *wm8988; 820 struct wm8988_priv *wm8988;
914 struct snd_soc_codec *codec; 821 int ret;
915 822
916 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); 823 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
917 if (wm8988 == NULL) 824 if (wm8988 == NULL)
918 return -ENOMEM; 825 return -ENOMEM;
919 826
920 codec = &wm8988->codec; 827 wm8988->control_type = SND_SOC_SPI;
921 828 spi_set_drvdata(spi, wm8988);
922 i2c_set_clientdata(i2c, wm8988);
923 codec->control_data = i2c;
924
925 codec->dev = &i2c->dev;
926 829
927 return wm8988_register(wm8988, SND_SOC_I2C); 830 ret = snd_soc_register_codec(&spi->dev,
831 &soc_codec_dev_wm8988, &wm8988_dai, 1);
832 if (ret < 0)
833 kfree(wm8988);
834 return ret;
928} 835}
929 836
930static int wm8988_i2c_remove(struct i2c_client *client) 837static int __devexit wm8988_spi_remove(struct spi_device *spi)
931{ 838{
932 struct wm8988_priv *wm8988 = i2c_get_clientdata(client); 839 snd_soc_unregister_codec(&spi->dev);
933 wm8988_unregister(wm8988); 840 kfree(spi_get_drvdata(spi));
934 return 0; 841 return 0;
935} 842}
936 843
937static const struct i2c_device_id wm8988_i2c_id[] = { 844static struct spi_driver wm8988_spi_driver = {
938 { "wm8988", 0 },
939 { }
940};
941MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
942
943static struct i2c_driver wm8988_i2c_driver = {
944 .driver = { 845 .driver = {
945 .name = "WM8988", 846 .name = "wm8988-codec",
946 .owner = THIS_MODULE, 847 .owner = THIS_MODULE,
947 }, 848 },
948 .probe = wm8988_i2c_probe, 849 .probe = wm8988_spi_probe,
949 .remove = wm8988_i2c_remove, 850 .remove = __devexit_p(wm8988_spi_remove),
950 .id_table = wm8988_i2c_id,
951}; 851};
952#endif 852#endif /* CONFIG_SPI_MASTER */
953 853
954#if defined(CONFIG_SPI_MASTER) 854#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
955static int __devinit wm8988_spi_probe(struct spi_device *spi) 855static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
856 const struct i2c_device_id *id)
956{ 857{
957 struct wm8988_priv *wm8988; 858 struct wm8988_priv *wm8988;
958 struct snd_soc_codec *codec; 859 int ret;
959 860
960 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL); 861 wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
961 if (wm8988 == NULL) 862 if (wm8988 == NULL)
962 return -ENOMEM; 863 return -ENOMEM;
963 864
964 codec = &wm8988->codec; 865 i2c_set_clientdata(i2c, wm8988);
965 codec->control_data = spi; 866 wm8988->control_type = SND_SOC_I2C;
966 codec->dev = &spi->dev;
967
968 dev_set_drvdata(&spi->dev, wm8988);
969 867
970 return wm8988_register(wm8988, SND_SOC_SPI); 868 ret = snd_soc_register_codec(&i2c->dev,
869 &soc_codec_dev_wm8988, &wm8988_dai, 1);
870 if (ret < 0)
871 kfree(wm8988);
872 return ret;
971} 873}
972 874
973static int __devexit wm8988_spi_remove(struct spi_device *spi) 875static __devexit int wm8988_i2c_remove(struct i2c_client *client)
974{ 876{
975 struct wm8988_priv *wm8988 = dev_get_drvdata(&spi->dev); 877 snd_soc_unregister_codec(&client->dev);
976 878 kfree(i2c_get_clientdata(client));
977 wm8988_unregister(wm8988);
978
979 return 0; 879 return 0;
980} 880}
981 881
982static struct spi_driver wm8988_spi_driver = { 882static const struct i2c_device_id wm8988_i2c_id[] = {
883 { "wm8988", 0 },
884 { }
885};
886MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
887
888static struct i2c_driver wm8988_i2c_driver = {
983 .driver = { 889 .driver = {
984 .name = "wm8988", 890 .name = "wm8988-codec",
985 .bus = &spi_bus_type, 891 .owner = THIS_MODULE,
986 .owner = THIS_MODULE,
987 }, 892 },
988 .probe = wm8988_spi_probe, 893 .probe = wm8988_i2c_probe,
989 .remove = __devexit_p(wm8988_spi_remove), 894 .remove = __devexit_p(wm8988_i2c_remove),
895 .id_table = wm8988_i2c_id,
990}; 896};
991#endif 897#endif
992 898
993static int __init wm8988_modinit(void) 899static int __init wm8988_modinit(void)
994{ 900{
995 int ret; 901 int ret = 0;
996
997#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 902#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
998 ret = i2c_add_driver(&wm8988_i2c_driver); 903 ret = i2c_add_driver(&wm8988_i2c_driver);
999 if (ret != 0) 904 if (ret != 0) {
1000 pr_err("WM8988: Unable to register I2C driver: %d\n", ret); 905 printk(KERN_ERR "Failed to register WM8988 I2C driver: %d\n",
906 ret);
907 }
1001#endif 908#endif
1002#if defined(CONFIG_SPI_MASTER) 909#if defined(CONFIG_SPI_MASTER)
1003 ret = spi_register_driver(&wm8988_spi_driver); 910 ret = spi_register_driver(&wm8988_spi_driver);
1004 if (ret != 0) 911 if (ret != 0) {
1005 pr_err("WM8988: Unable to register SPI driver: %d\n", ret); 912 printk(KERN_ERR "Failed to register WM8988 SPI driver: %d\n",
913 ret);
914 }
1006#endif 915#endif
1007 return ret; 916 return ret;
1008} 917}
diff --git a/sound/soc/codecs/wm8988.h b/sound/soc/codecs/wm8988.h
index 4552d37fdd41..5c04024e5f9f 100644
--- a/sound/soc/codecs/wm8988.h
+++ b/sound/soc/codecs/wm8988.h
@@ -54,7 +54,4 @@
54 54
55#define WM8988_SYSCLK 0 55#define WM8988_SYSCLK 0
56 56
57extern struct snd_soc_dai wm8988_dai;
58extern struct snd_soc_codec_device soc_codec_dev_wm8988;
59
60#endif 57#endif
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index dd8d909788c1..264828e4e67c 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -32,6 +32,7 @@
32 32
33/* codec private data */ 33/* codec private data */
34struct wm8990_priv { 34struct wm8990_priv {
35 enum snd_soc_control_type control_type;
35 unsigned int sysclk; 36 unsigned int sysclk;
36 unsigned int pcmclk; 37 unsigned int pcmclk;
37}; 38};
@@ -1114,8 +1115,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
1114 struct snd_soc_dai *dai) 1115 struct snd_soc_dai *dai)
1115{ 1116{
1116 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1117 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1117 struct snd_soc_device *socdev = rtd->socdev; 1118 struct snd_soc_codec *codec = rtd->codec;
1118 struct snd_soc_codec *codec = socdev->card->codec;
1119 u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); 1119 u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1);
1120 1120
1121 audio1 &= ~WM8990_AIF_WL_MASK; 1121 audio1 &= ~WM8990_AIF_WL_MASK;
@@ -1293,10 +1293,9 @@ static struct snd_soc_dai_ops wm8990_dai_ops = {
1293 .set_sysclk = wm8990_set_dai_sysclk, 1293 .set_sysclk = wm8990_set_dai_sysclk,
1294}; 1294};
1295 1295
1296struct snd_soc_dai wm8990_dai = { 1296static struct snd_soc_dai_driver wm8990_dai = {
1297/* ADC/DAC on primary */ 1297/* ADC/DAC on primary */
1298 .name = "WM8990 ADC/DAC Primary", 1298 .name = "wm8990-hifi",
1299 .id = 1,
1300 .playback = { 1299 .playback = {
1301 .stream_name = "Playback", 1300 .stream_name = "Playback",
1302 .channels_min = 1, 1301 .channels_min = 1,
@@ -1311,21 +1310,15 @@ struct snd_soc_dai wm8990_dai = {
1311 .formats = WM8990_FORMATS,}, 1310 .formats = WM8990_FORMATS,},
1312 .ops = &wm8990_dai_ops, 1311 .ops = &wm8990_dai_ops,
1313}; 1312};
1314EXPORT_SYMBOL_GPL(wm8990_dai);
1315 1313
1316static int wm8990_suspend(struct platform_device *pdev, pm_message_t state) 1314static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
1317{ 1315{
1318 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1319 struct snd_soc_codec *codec = socdev->card->codec;
1320
1321 wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF); 1316 wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
1322 return 0; 1317 return 0;
1323} 1318}
1324 1319
1325static int wm8990_resume(struct platform_device *pdev) 1320static int wm8990_resume(struct snd_soc_codec *codec)
1326{ 1321{
1327 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1328 struct snd_soc_codec *codec = socdev->card->codec;
1329 int i; 1322 int i;
1330 u8 data[2]; 1323 u8 data[2];
1331 u16 *cache = codec->reg_cache; 1324 u16 *cache = codec->reg_cache;
@@ -1347,40 +1340,20 @@ static int wm8990_resume(struct platform_device *pdev)
1347 * initialise the WM8990 driver 1340 * initialise the WM8990 driver
1348 * register the mixer and dsp interfaces with the kernel 1341 * register the mixer and dsp interfaces with the kernel
1349 */ 1342 */
1350static int wm8990_init(struct snd_soc_device *socdev) 1343static int wm8990_probe(struct snd_soc_codec *codec)
1351{ 1344{
1352 struct snd_soc_codec *codec = socdev->card->codec; 1345 int ret;
1353 u16 reg; 1346 u16 reg;
1354 int ret = 0;
1355
1356 codec->name = "WM8990";
1357 codec->owner = THIS_MODULE;
1358 codec->set_bias_level = wm8990_set_bias_level;
1359 codec->dai = &wm8990_dai;
1360 codec->num_dai = 2;
1361 codec->reg_cache_size = ARRAY_SIZE(wm8990_reg);
1362 codec->reg_cache = kmemdup(wm8990_reg, sizeof(wm8990_reg), GFP_KERNEL);
1363
1364 if (codec->reg_cache == NULL)
1365 return -ENOMEM;
1366 1347
1367 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); 1348 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1368 if (ret < 0) { 1349 if (ret < 0) {
1369 printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); 1350 printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret);
1370 goto pcm_err; 1351 return ret;
1371 } 1352 }
1372 1353
1373 wm8990_reset(codec); 1354 wm8990_reset(codec);
1374 1355
1375 /* register pcms */
1376 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1377 if (ret < 0) {
1378 printk(KERN_ERR "wm8990: failed to create pcms\n");
1379 goto pcm_err;
1380 }
1381
1382 /* charge output caps */ 1356 /* charge output caps */
1383 codec->bias_level = SND_SOC_BIAS_OFF;
1384 wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1357 wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1385 1358
1386 reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4); 1359 reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
@@ -1400,47 +1373,51 @@ static int wm8990_init(struct snd_soc_device *socdev)
1400 ARRAY_SIZE(wm8990_snd_controls)); 1373 ARRAY_SIZE(wm8990_snd_controls));
1401 wm8990_add_widgets(codec); 1374 wm8990_add_widgets(codec);
1402 1375
1403 return ret; 1376 return 0;
1377}
1404 1378
1405pcm_err: 1379/* power down chip */
1406 kfree(codec->reg_cache); 1380static int wm8990_remove(struct snd_soc_codec *codec)
1407 return ret; 1381{
1382 wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
1383 return 0;
1408} 1384}
1409 1385
1410/* If the i2c layer weren't so broken, we could pass this kind of data 1386static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
1411 around */ 1387 .probe = wm8990_probe,
1412static struct snd_soc_device *wm8990_socdev; 1388 .remove = wm8990_remove,
1389 .suspend = wm8990_suspend,
1390 .resume = wm8990_resume,
1391 .set_bias_level = wm8990_set_bias_level,
1392 .reg_cache_size = ARRAY_SIZE(wm8990_reg),
1393 .reg_word_size = sizeof(u16),
1394 .reg_cache_default = wm8990_reg,
1395};
1413 1396
1414#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1397#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1415 1398static __devinit int wm8990_i2c_probe(struct i2c_client *i2c,
1416/* 1399 const struct i2c_device_id *id)
1417 * WM891 2 wire address is determined by GPIO5
1418 * state during powerup.
1419 * low = 0x34
1420 * high = 0x36
1421 */
1422
1423static int wm8990_i2c_probe(struct i2c_client *i2c,
1424 const struct i2c_device_id *id)
1425{ 1400{
1426 struct snd_soc_device *socdev = wm8990_socdev; 1401 struct wm8990_priv *wm8990;
1427 struct snd_soc_codec *codec = socdev->card->codec;
1428 int ret; 1402 int ret;
1429 1403
1430 i2c_set_clientdata(i2c, codec); 1404 wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
1431 codec->control_data = i2c; 1405 if (wm8990 == NULL)
1406 return -ENOMEM;
1432 1407
1433 ret = wm8990_init(socdev); 1408 i2c_set_clientdata(i2c, wm8990);
1434 if (ret < 0)
1435 pr_err("failed to initialise WM8990\n");
1436 1409
1410 ret = snd_soc_register_codec(&i2c->dev,
1411 &soc_codec_dev_wm8990, &wm8990_dai, 1);
1412 if (ret < 0)
1413 kfree(wm8990);
1437 return ret; 1414 return ret;
1438} 1415}
1439 1416
1440static int wm8990_i2c_remove(struct i2c_client *client) 1417static __devexit int wm8990_i2c_remove(struct i2c_client *client)
1441{ 1418{
1442 struct snd_soc_codec *codec = i2c_get_clientdata(client); 1419 snd_soc_unregister_codec(&client->dev);
1443 kfree(codec->reg_cache); 1420 kfree(i2c_get_clientdata(client));
1444 return 0; 1421 return 0;
1445} 1422}
1446 1423
@@ -1452,134 +1429,34 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
1452 1429
1453static struct i2c_driver wm8990_i2c_driver = { 1430static struct i2c_driver wm8990_i2c_driver = {
1454 .driver = { 1431 .driver = {
1455 .name = "WM8990 I2C Codec", 1432 .name = "wm8990-codec",
1456 .owner = THIS_MODULE, 1433 .owner = THIS_MODULE,
1457 }, 1434 },
1458 .probe = wm8990_i2c_probe, 1435 .probe = wm8990_i2c_probe,
1459 .remove = wm8990_i2c_remove, 1436 .remove = __devexit_p(wm8990_i2c_remove),
1460 .id_table = wm8990_i2c_id, 1437 .id_table = wm8990_i2c_id,
1461}; 1438};
1462
1463static int wm8990_add_i2c_device(struct platform_device *pdev,
1464 const struct wm8990_setup_data *setup)
1465{
1466 struct i2c_board_info info;
1467 struct i2c_adapter *adapter;
1468 struct i2c_client *client;
1469 int ret;
1470
1471 ret = i2c_add_driver(&wm8990_i2c_driver);
1472 if (ret != 0) {
1473 dev_err(&pdev->dev, "can't add i2c driver\n");
1474 return ret;
1475 }
1476
1477 memset(&info, 0, sizeof(struct i2c_board_info));
1478 info.addr = setup->i2c_address;
1479 strlcpy(info.type, "wm8990", I2C_NAME_SIZE);
1480
1481 adapter = i2c_get_adapter(setup->i2c_bus);
1482 if (!adapter) {
1483 dev_err(&pdev->dev, "can't get i2c adapter %d\n",
1484 setup->i2c_bus);
1485 goto err_driver;
1486 }
1487
1488 client = i2c_new_device(adapter, &info);
1489 i2c_put_adapter(adapter);
1490 if (!client) {
1491 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
1492 (unsigned int)info.addr);
1493 goto err_driver;
1494 }
1495
1496 return 0;
1497
1498err_driver:
1499 i2c_del_driver(&wm8990_i2c_driver);
1500 return -ENODEV;
1501}
1502#endif 1439#endif
1503 1440
1504static int wm8990_probe(struct platform_device *pdev) 1441static int __init wm8990_modinit(void)
1505{ 1442{
1506 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1443 int ret = 0;
1507 struct wm8990_setup_data *setup;
1508 struct snd_soc_codec *codec;
1509 struct wm8990_priv *wm8990;
1510 int ret;
1511
1512 setup = socdev->codec_data;
1513 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
1514 if (codec == NULL)
1515 return -ENOMEM;
1516
1517 wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL);
1518 if (wm8990 == NULL) {
1519 kfree(codec);
1520 return -ENOMEM;
1521 }
1522
1523 snd_soc_codec_set_drvdata(codec, wm8990);
1524 socdev->card->codec = codec;
1525 mutex_init(&codec->mutex);
1526 INIT_LIST_HEAD(&codec->dapm_widgets);
1527 INIT_LIST_HEAD(&codec->dapm_paths);
1528 wm8990_socdev = socdev;
1529
1530 ret = -ENODEV;
1531
1532#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1444#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1533 if (setup->i2c_address) { 1445 ret = i2c_add_driver(&wm8990_i2c_driver);
1534 codec->hw_write = (hw_write_t)i2c_master_send;
1535 ret = wm8990_add_i2c_device(pdev, setup);
1536 }
1537#endif
1538
1539 if (ret != 0) { 1446 if (ret != 0) {
1540 kfree(snd_soc_codec_get_drvdata(codec)); 1447 printk(KERN_ERR "Failed to register wm8990 I2C driver: %d\n",
1541 kfree(codec); 1448 ret);
1542 } 1449 }
1450#endif
1543 return ret; 1451 return ret;
1544} 1452}
1453module_init(wm8990_modinit);
1545 1454
1546/* power down chip */ 1455static void __exit wm8990_exit(void)
1547static int wm8990_remove(struct platform_device *pdev)
1548{ 1456{
1549 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1550 struct snd_soc_codec *codec = socdev->card->codec;
1551
1552 if (codec->control_data)
1553 wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
1554 snd_soc_free_pcms(socdev);
1555 snd_soc_dapm_free(socdev);
1556#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1457#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1557 i2c_unregister_device(codec->control_data);
1558 i2c_del_driver(&wm8990_i2c_driver); 1458 i2c_del_driver(&wm8990_i2c_driver);
1559#endif 1459#endif
1560 kfree(snd_soc_codec_get_drvdata(codec));
1561 kfree(codec);
1562
1563 return 0;
1564}
1565
1566struct snd_soc_codec_device soc_codec_dev_wm8990 = {
1567 .probe = wm8990_probe,
1568 .remove = wm8990_remove,
1569 .suspend = wm8990_suspend,
1570 .resume = wm8990_resume,
1571};
1572EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
1573
1574static int __init wm8990_modinit(void)
1575{
1576 return snd_soc_register_dai(&wm8990_dai);
1577}
1578module_init(wm8990_modinit);
1579
1580static void __exit wm8990_exit(void)
1581{
1582 snd_soc_unregister_dai(&wm8990_dai);
1583} 1460}
1584module_exit(wm8990_exit); 1461module_exit(wm8990_exit);
1585 1462
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h
index 7114ddc88b4b..77c98a4bfe9c 100644
--- a/sound/soc/codecs/wm8990.h
+++ b/sound/soc/codecs/wm8990.h
@@ -826,18 +826,10 @@
826#define WM8990_INMIXR_PWR_BIT 2 826#define WM8990_INMIXR_PWR_BIT 2
827#define WM8990_AINRMUX_PWR_BIT 3 827#define WM8990_AINRMUX_PWR_BIT 3
828 828
829struct wm8990_setup_data {
830 unsigned i2c_bus;
831 unsigned short i2c_address;
832};
833
834#define WM8990_MCLK_DIV 0 829#define WM8990_MCLK_DIV 0
835#define WM8990_DACCLK_DIV 1 830#define WM8990_DACCLK_DIV 1
836#define WM8990_ADCCLK_DIV 2 831#define WM8990_ADCCLK_DIV 2
837#define WM8990_BCLK_DIV 3 832#define WM8990_BCLK_DIV 3
838 833
839extern struct snd_soc_dai wm8990_dai;
840extern struct snd_soc_codec_device soc_codec_dev_wm8990;
841
842#endif /* __WM8990REGISTERDEFS_H__ */ 834#endif /* __WM8990REGISTERDEFS_H__ */
843/*------------------------------ END OF FILE ---------------------------------*/ 835/*------------------------------ END OF FILE ---------------------------------*/
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index d8d300c6175f..589e3fa24734 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -229,7 +229,7 @@ struct wm8993_priv {
229 u16 reg_cache[WM8993_REGISTER_COUNT]; 229 u16 reg_cache[WM8993_REGISTER_COUNT];
230 struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES]; 230 struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES];
231 struct wm8993_platform_data pdata; 231 struct wm8993_platform_data pdata;
232 struct snd_soc_codec codec; 232 enum snd_soc_control_type control_type;
233 int master; 233 int master;
234 int sysclk_source; 234 int sysclk_source;
235 int tdm_slots; 235 int tdm_slots;
@@ -367,10 +367,9 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
367 return 0; 367 return 0;
368} 368}
369 369
370static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, 370static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
371 unsigned int Fref, unsigned int Fout) 371 unsigned int Fref, unsigned int Fout)
372{ 372{
373 struct snd_soc_codec *codec = dai->codec;
374 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); 373 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
375 u16 reg1, reg4, reg5; 374 u16 reg1, reg4, reg5;
376 struct _fll_div fll_div; 375 struct _fll_div fll_div;
@@ -456,6 +455,12 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
456 return 0; 455 return 0;
457} 456}
458 457
458static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
459 unsigned int Fref, unsigned int Fout)
460{
461 return _wm8993_set_fll(dai->codec, fll_id, source, Fref, Fout);
462}
463
459static int configure_clock(struct snd_soc_codec *codec) 464static int configure_clock(struct snd_soc_codec *codec)
460{ 465{
461 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); 466 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
@@ -1394,8 +1399,8 @@ static struct snd_soc_dai_ops wm8993_ops = {
1394 SNDRV_PCM_FMTBIT_S24_LE |\ 1399 SNDRV_PCM_FMTBIT_S24_LE |\
1395 SNDRV_PCM_FMTBIT_S32_LE) 1400 SNDRV_PCM_FMTBIT_S32_LE)
1396 1401
1397struct snd_soc_dai wm8993_dai = { 1402static struct snd_soc_dai_driver wm8993_dai = {
1398 .name = "WM8993", 1403 .name = "wm8993-hifi",
1399 .playback = { 1404 .playback = {
1400 .stream_name = "Playback", 1405 .stream_name = "Playback",
1401 .channels_min = 1, 1406 .channels_min = 1,
@@ -1413,32 +1418,81 @@ struct snd_soc_dai wm8993_dai = {
1413 .ops = &wm8993_ops, 1418 .ops = &wm8993_ops,
1414 .symmetric_rates = 1, 1419 .symmetric_rates = 1,
1415}; 1420};
1416EXPORT_SYMBOL_GPL(wm8993_dai);
1417
1418static struct snd_soc_codec *wm8993_codec;
1419 1421
1420static int wm8993_probe(struct platform_device *pdev) 1422static int wm8993_probe(struct snd_soc_codec *codec)
1421{ 1423{
1422 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1424 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
1423 struct snd_soc_codec *codec; 1425 int ret, i, val;
1424 struct wm8993_priv *wm8993; 1426
1425 int ret = 0; 1427 wm8993->hubs_data.hp_startup_mode = 1;
1428 wm8993->hubs_data.dcs_codes = -2;
1429
1430 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1431 if (ret != 0) {
1432 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1433 return ret;
1434 }
1435
1436 for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
1437 wm8993->supplies[i].supply = wm8993_supply_names[i];
1426 1438
1427 if (!wm8993_codec) { 1439 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
1428 dev_err(&pdev->dev, "I2C device not yet probed\n"); 1440 wm8993->supplies);
1429 goto err; 1441 if (ret != 0) {
1442 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1443 return ret;
1430 } 1444 }
1431 1445
1432 socdev->card->codec = wm8993_codec; 1446 ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
1433 codec = wm8993_codec; 1447 wm8993->supplies);
1434 wm8993 = snd_soc_codec_get_drvdata(codec); 1448 if (ret != 0) {
1449 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1450 goto err_get;
1451 }
1435 1452
1436 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 1453 val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
1437 if (ret < 0) { 1454 if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
1438 dev_err(codec->dev, "failed to create pcms\n"); 1455 dev_err(codec->dev, "Invalid ID register value %x\n", val);
1439 goto err; 1456 ret = -EINVAL;
1457 goto err_enable;
1440 } 1458 }
1441 1459
1460 ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
1461 if (ret != 0)
1462 goto err_enable;
1463
1464 codec->cache_only = 1;
1465
1466 /* By default we're using the output mixers */
1467 wm8993->class_w_users = 2;
1468
1469 /* Latch volume update bits and default ZC on */
1470 snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
1471 WM8993_DAC_VU, WM8993_DAC_VU);
1472 snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
1473 WM8993_ADC_VU, WM8993_ADC_VU);
1474
1475 /* Manualy manage the HPOUT sequencing for independent stereo
1476 * control. */
1477 snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0,
1478 WM8993_HPOUT1_AUTO_PU, 0);
1479
1480 /* Use automatic clock configuration */
1481 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
1482
1483 wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
1484 wm8993->pdata.lineout2_diff,
1485 wm8993->pdata.lineout1fb,
1486 wm8993->pdata.lineout2fb,
1487 wm8993->pdata.jd_scthr,
1488 wm8993->pdata.jd_thr,
1489 wm8993->pdata.micbias1_lvl,
1490 wm8993->pdata.micbias2_lvl);
1491
1492 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1493 if (ret != 0)
1494 goto err_enable;
1495
1442 snd_soc_add_controls(codec, wm8993_snd_controls, 1496 snd_soc_add_controls(codec, wm8993_snd_controls,
1443 ARRAY_SIZE(wm8993_snd_controls)); 1497 ARRAY_SIZE(wm8993_snd_controls));
1444 if (wm8993->pdata.num_retune_configs != 0) { 1498 if (wm8993->pdata.num_retune_configs != 0) {
@@ -1457,36 +1511,36 @@ static int wm8993_probe(struct platform_device *pdev)
1457 wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, 1511 wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
1458 wm8993->pdata.lineout2_diff); 1512 wm8993->pdata.lineout2_diff);
1459 1513
1460 return ret; 1514 return 0;
1461 1515
1462err: 1516err_enable:
1517 regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
1518err_get:
1519 regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
1463 return ret; 1520 return ret;
1464} 1521}
1465 1522
1466static int wm8993_remove(struct platform_device *pdev) 1523static int wm8993_remove(struct snd_soc_codec *codec)
1467{ 1524{
1468 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1525 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
1469
1470 snd_soc_free_pcms(socdev);
1471 snd_soc_dapm_free(socdev);
1472 1526
1527 wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
1528 regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
1473 return 0; 1529 return 0;
1474} 1530}
1475 1531
1476#ifdef CONFIG_PM 1532#ifdef CONFIG_PM
1477static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) 1533static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state)
1478{ 1534{
1479 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1480 struct snd_soc_codec *codec = socdev->card->codec;
1481 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); 1535 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
1482 int fll_fout = wm8993->fll_fout; 1536 int fll_fout = wm8993->fll_fout;
1483 int fll_fref = wm8993->fll_fref; 1537 int fll_fref = wm8993->fll_fref;
1484 int ret; 1538 int ret;
1485 1539
1486 /* Stop the FLL in an orderly fashion */ 1540 /* Stop the FLL in an orderly fashion */
1487 ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0); 1541 ret = _wm8993_set_fll(codec, 0, 0, 0, 0);
1488 if (ret != 0) { 1542 if (ret != 0) {
1489 dev_err(&pdev->dev, "Failed to stop FLL\n"); 1543 dev_err(codec->dev, "Failed to stop FLL\n");
1490 return ret; 1544 return ret;
1491 } 1545 }
1492 1546
@@ -1498,10 +1552,8 @@ static int wm8993_suspend(struct platform_device *pdev, pm_message_t state)
1498 return 0; 1552 return 0;
1499} 1553}
1500 1554
1501static int wm8993_resume(struct platform_device *pdev) 1555static int wm8993_resume(struct snd_soc_codec *codec)
1502{ 1556{
1503 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1504 struct snd_soc_codec *codec = socdev->card->codec;
1505 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec); 1557 struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
1506 int ret; 1558 int ret;
1507 1559
@@ -1515,7 +1567,7 @@ static int wm8993_resume(struct platform_device *pdev)
1515 wm8993->fll_fref = 0; 1567 wm8993->fll_fref = 0;
1516 wm8993->fll_fout = 0; 1568 wm8993->fll_fout = 0;
1517 1569
1518 ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src, 1570 ret = _wm8993_set_fll(codec, 0, wm8993->fll_src,
1519 fll_fref, fll_fout); 1571 fll_fref, fll_fout);
1520 if (ret != 0) 1572 if (ret != 0)
1521 dev_err(codec->dev, "Failed to restart FLL\n"); 1573 dev_err(codec->dev, "Failed to restart FLL\n");
@@ -1528,162 +1580,42 @@ static int wm8993_resume(struct platform_device *pdev)
1528#define wm8993_resume NULL 1580#define wm8993_resume NULL
1529#endif 1581#endif
1530 1582
1531struct snd_soc_codec_device soc_codec_dev_wm8993 = { 1583static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
1532 .probe = wm8993_probe, 1584 .probe = wm8993_probe,
1533 .remove = wm8993_remove, 1585 .remove = wm8993_remove,
1534 .suspend = wm8993_suspend, 1586 .suspend = wm8993_suspend,
1535 .resume = wm8993_resume, 1587 .resume = wm8993_resume,
1588 .set_bias_level = wm8993_set_bias_level,
1589 .reg_cache_size = ARRAY_SIZE(wm8993_reg_defaults),
1590 .reg_word_size = sizeof(u16),
1591 .reg_cache_default = wm8993_reg_defaults,
1592 .volatile_register = wm8993_volatile,
1536}; 1593};
1537EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993);
1538 1594
1539static int wm8993_i2c_probe(struct i2c_client *i2c, 1595#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1540 const struct i2c_device_id *id) 1596static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
1597 const struct i2c_device_id *id)
1541{ 1598{
1542 struct wm8993_priv *wm8993; 1599 struct wm8993_priv *wm8993;
1543 struct snd_soc_codec *codec;
1544 unsigned int val;
1545 int ret; 1600 int ret;
1546 int i;
1547
1548 if (wm8993_codec) {
1549 dev_err(&i2c->dev, "A WM8993 is already registered\n");
1550 return -EINVAL;
1551 }
1552 1601
1553 wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); 1602 wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);
1554 if (wm8993 == NULL) 1603 if (wm8993 == NULL)
1555 return -ENOMEM; 1604 return -ENOMEM;
1556 1605
1557 codec = &wm8993->codec;
1558 if (i2c->dev.platform_data)
1559 memcpy(&wm8993->pdata, i2c->dev.platform_data,
1560 sizeof(wm8993->pdata));
1561
1562 mutex_init(&codec->mutex);
1563 INIT_LIST_HEAD(&codec->dapm_widgets);
1564 INIT_LIST_HEAD(&codec->dapm_paths);
1565
1566 codec->name = "WM8993";
1567 codec->volatile_register = wm8993_volatile;
1568 codec->reg_cache = wm8993->reg_cache;
1569 codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache);
1570 codec->bias_level = SND_SOC_BIAS_OFF;
1571 codec->set_bias_level = wm8993_set_bias_level;
1572 codec->dai = &wm8993_dai;
1573 codec->num_dai = 1;
1574 snd_soc_codec_set_drvdata(codec, wm8993);
1575
1576 wm8993->hubs_data.hp_startup_mode = 1;
1577 wm8993->hubs_data.dcs_codes = -2;
1578
1579 memcpy(wm8993->reg_cache, wm8993_reg_defaults,
1580 sizeof(wm8993->reg_cache));
1581
1582 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
1583 if (ret != 0) {
1584 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1585 goto err;
1586 }
1587
1588 i2c_set_clientdata(i2c, wm8993); 1606 i2c_set_clientdata(i2c, wm8993);
1589 codec->control_data = i2c;
1590 wm8993_codec = codec;
1591
1592 codec->dev = &i2c->dev;
1593
1594 for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
1595 wm8993->supplies[i].supply = wm8993_supply_names[i];
1596
1597 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
1598 wm8993->supplies);
1599 if (ret != 0) {
1600 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1601 goto err;
1602 }
1603
1604 ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
1605 wm8993->supplies);
1606 if (ret != 0) {
1607 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
1608 goto err_get;
1609 }
1610
1611 val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
1612 if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
1613 dev_err(codec->dev, "Invalid ID register value %x\n", val);
1614 ret = -EINVAL;
1615 goto err_enable;
1616 }
1617
1618 ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
1619 if (ret != 0)
1620 goto err_enable;
1621
1622 codec->cache_only = 1;
1623
1624 /* By default we're using the output mixers */
1625 wm8993->class_w_users = 2;
1626
1627 /* Latch volume update bits and default ZC on */
1628 snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME,
1629 WM8993_DAC_VU, WM8993_DAC_VU);
1630 snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME,
1631 WM8993_ADC_VU, WM8993_ADC_VU);
1632 1607
1633 /* Manualy manage the HPOUT sequencing for independent stereo 1608 ret = snd_soc_register_codec(&i2c->dev,
1634 * control. */ 1609 &soc_codec_dev_wm8993, &wm8993_dai, 1);
1635 snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, 1610 if (ret < 0)
1636 WM8993_HPOUT1_AUTO_PU, 0); 1611 kfree(wm8993);
1637
1638 /* Use automatic clock configuration */
1639 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
1640
1641 wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
1642 wm8993->pdata.lineout2_diff,
1643 wm8993->pdata.lineout1fb,
1644 wm8993->pdata.lineout2fb,
1645 wm8993->pdata.jd_scthr,
1646 wm8993->pdata.jd_thr,
1647 wm8993->pdata.micbias1_lvl,
1648 wm8993->pdata.micbias2_lvl);
1649
1650 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1651 if (ret != 0)
1652 goto err_enable;
1653
1654 wm8993_dai.dev = codec->dev;
1655
1656 ret = snd_soc_register_dai(&wm8993_dai);
1657 if (ret != 0)
1658 goto err_bias;
1659
1660 ret = snd_soc_register_codec(codec);
1661
1662 return 0;
1663
1664err_bias:
1665 wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF);
1666err_enable:
1667 regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
1668err_get:
1669 regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
1670err:
1671 wm8993_codec = NULL;
1672 kfree(wm8993);
1673 return ret; 1612 return ret;
1674} 1613}
1675 1614
1676static int wm8993_i2c_remove(struct i2c_client *client) 1615static __devexit int wm8993_i2c_remove(struct i2c_client *client)
1677{ 1616{
1678 struct wm8993_priv *wm8993 = i2c_get_clientdata(client); 1617 snd_soc_unregister_codec(&client->dev);
1679 1618 kfree(i2c_get_clientdata(client));
1680 snd_soc_unregister_codec(&wm8993->codec);
1681 snd_soc_unregister_dai(&wm8993_dai);
1682
1683 wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF);
1684 regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
1685 kfree(wm8993);
1686
1687 return 0; 1619 return 0;
1688} 1620}
1689 1621
@@ -1695,30 +1627,34 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
1695 1627
1696static struct i2c_driver wm8993_i2c_driver = { 1628static struct i2c_driver wm8993_i2c_driver = {
1697 .driver = { 1629 .driver = {
1698 .name = "WM8993", 1630 .name = "wm8993-codec",
1699 .owner = THIS_MODULE, 1631 .owner = THIS_MODULE,
1700 }, 1632 },
1701 .probe = wm8993_i2c_probe, 1633 .probe = wm8993_i2c_probe,
1702 .remove = wm8993_i2c_remove, 1634 .remove = __devexit_p(wm8993_i2c_remove),
1703 .id_table = wm8993_i2c_id, 1635 .id_table = wm8993_i2c_id,
1704}; 1636};
1705 1637#endif
1706 1638
1707static int __init wm8993_modinit(void) 1639static int __init wm8993_modinit(void)
1708{ 1640{
1709 int ret; 1641 int ret = 0;
1710 1642#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1711 ret = i2c_add_driver(&wm8993_i2c_driver); 1643 ret = i2c_add_driver(&wm8993_i2c_driver);
1712 if (ret != 0) 1644 if (ret != 0) {
1713 pr_err("WM8993: Unable to register I2C driver: %d\n", ret); 1645 pr_err("WM8993: Unable to register I2C driver: %d\n",
1714 1646 ret);
1647 }
1648#endif
1715 return ret; 1649 return ret;
1716} 1650}
1717module_init(wm8993_modinit); 1651module_init(wm8993_modinit);
1718 1652
1719static void __exit wm8993_exit(void) 1653static void __exit wm8993_exit(void)
1720{ 1654{
1655#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1721 i2c_del_driver(&wm8993_i2c_driver); 1656 i2c_del_driver(&wm8993_i2c_driver);
1657#endif
1722} 1658}
1723module_exit(wm8993_exit); 1659module_exit(wm8993_exit);
1724 1660
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
index 30e71ca88dad..2184617b9611 100644
--- a/sound/soc/codecs/wm8993.h
+++ b/sound/soc/codecs/wm8993.h
@@ -1,9 +1,6 @@
1#ifndef WM8993_H 1#ifndef WM8993_H
2#define WM8993_H 2#define WM8993_H
3 3
4extern struct snd_soc_dai wm8993_dai;
5extern struct snd_soc_codec_device soc_codec_dev_wm8993;
6
7#define WM8993_SYSCLK_MCLK 1 4#define WM8993_SYSCLK_MCLK 1
8#define WM8993_SYSCLK_FLL 2 5#define WM8993_SYSCLK_FLL 2
9 6
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 522249d5c2b4..0db59c3aa5d4 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -36,9 +36,6 @@
36#include "wm8994.h" 36#include "wm8994.h"
37#include "wm_hubs.h" 37#include "wm_hubs.h"
38 38
39static struct snd_soc_codec *wm8994_codec;
40struct snd_soc_codec_device soc_codec_dev_wm8994;
41
42struct fll_config { 39struct fll_config {
43 int src; 40 int src;
44 int in; 41 int in;
@@ -71,7 +68,9 @@ struct wm8994_micdet {
71/* codec private data */ 68/* codec private data */
72struct wm8994_priv { 69struct wm8994_priv {
73 struct wm_hubs_data hubs; 70 struct wm_hubs_data hubs;
74 struct snd_soc_codec codec; 71 enum snd_soc_control_type control_type;
72 void *control_data;
73 struct snd_soc_codec *codec;
75 u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; 74 u16 reg_cache[WM8994_REG_CACHE_SIZE + 1];
76 int sysclk[2]; 75 int sysclk[2];
77 int sysclk_rate[2]; 76 int sysclk_rate[2];
@@ -99,1581 +98,1580 @@ struct wm8994_priv {
99 struct wm8994_pdata *pdata; 98 struct wm8994_pdata *pdata;
100}; 99};
101 100
102static struct { 101static const struct {
103 unsigned short readable; /* Mask of readable bits */ 102 unsigned short readable; /* Mask of readable bits */
104 unsigned short writable; /* Mask of writable bits */ 103 unsigned short writable; /* Mask of writable bits */
105 unsigned short vol; /* Mask of volatile bits */
106} access_masks[] = { 104} access_masks[] = {
107 { 0xFFFF, 0xFFFF, 0x0000 }, /* R0 - Software Reset */ 105 { 0xFFFF, 0xFFFF }, /* R0 - Software Reset */
108 { 0x3B37, 0x3B37, 0x0000 }, /* R1 - Power Management (1) */ 106 { 0x3B37, 0x3B37 }, /* R1 - Power Management (1) */
109 { 0x6BF0, 0x6BF0, 0x0000 }, /* R2 - Power Management (2) */ 107 { 0x6BF0, 0x6BF0 }, /* R2 - Power Management (2) */
110 { 0x3FF0, 0x3FF0, 0x0000 }, /* R3 - Power Management (3) */ 108 { 0x3FF0, 0x3FF0 }, /* R3 - Power Management (3) */
111 { 0x3F3F, 0x3F3F, 0x0000 }, /* R4 - Power Management (4) */ 109 { 0x3F3F, 0x3F3F }, /* R4 - Power Management (4) */
112 { 0x3F0F, 0x3F0F, 0x0000 }, /* R5 - Power Management (5) */ 110 { 0x3F0F, 0x3F0F }, /* R5 - Power Management (5) */
113 { 0x003F, 0x003F, 0x0000 }, /* R6 - Power Management (6) */ 111 { 0x003F, 0x003F }, /* R6 - Power Management (6) */
114 { 0x0000, 0x0000, 0x0000 }, /* R7 */ 112 { 0x0000, 0x0000 }, /* R7 */
115 { 0x0000, 0x0000, 0x0000 }, /* R8 */ 113 { 0x0000, 0x0000 }, /* R8 */
116 { 0x0000, 0x0000, 0x0000 }, /* R9 */ 114 { 0x0000, 0x0000 }, /* R9 */
117 { 0x0000, 0x0000, 0x0000 }, /* R10 */ 115 { 0x0000, 0x0000 }, /* R10 */
118 { 0x0000, 0x0000, 0x0000 }, /* R11 */ 116 { 0x0000, 0x0000 }, /* R11 */
119 { 0x0000, 0x0000, 0x0000 }, /* R12 */ 117 { 0x0000, 0x0000 }, /* R12 */
120 { 0x0000, 0x0000, 0x0000 }, /* R13 */ 118 { 0x0000, 0x0000 }, /* R13 */
121 { 0x0000, 0x0000, 0x0000 }, /* R14 */ 119 { 0x0000, 0x0000 }, /* R14 */
122 { 0x0000, 0x0000, 0x0000 }, /* R15 */ 120 { 0x0000, 0x0000 }, /* R15 */
123 { 0x0000, 0x0000, 0x0000 }, /* R16 */ 121 { 0x0000, 0x0000 }, /* R16 */
124 { 0x0000, 0x0000, 0x0000 }, /* R17 */ 122 { 0x0000, 0x0000 }, /* R17 */
125 { 0x0000, 0x0000, 0x0000 }, /* R18 */ 123 { 0x0000, 0x0000 }, /* R18 */
126 { 0x0000, 0x0000, 0x0000 }, /* R19 */ 124 { 0x0000, 0x0000 }, /* R19 */
127 { 0x0000, 0x0000, 0x0000 }, /* R20 */ 125 { 0x0000, 0x0000 }, /* R20 */
128 { 0x01C0, 0x01C0, 0x0000 }, /* R21 - Input Mixer (1) */ 126 { 0x01C0, 0x01C0 }, /* R21 - Input Mixer (1) */
129 { 0x0000, 0x0000, 0x0000 }, /* R22 */ 127 { 0x0000, 0x0000 }, /* R22 */
130 { 0x0000, 0x0000, 0x0000 }, /* R23 */ 128 { 0x0000, 0x0000 }, /* R23 */
131 { 0x00DF, 0x01DF, 0x0000 }, /* R24 - Left Line Input 1&2 Volume */ 129 { 0x00DF, 0x01DF }, /* R24 - Left Line Input 1&2 Volume */
132 { 0x00DF, 0x01DF, 0x0000 }, /* R25 - Left Line Input 3&4 Volume */ 130 { 0x00DF, 0x01DF }, /* R25 - Left Line Input 3&4 Volume */
133 { 0x00DF, 0x01DF, 0x0000 }, /* R26 - Right Line Input 1&2 Volume */ 131 { 0x00DF, 0x01DF }, /* R26 - Right Line Input 1&2 Volume */
134 { 0x00DF, 0x01DF, 0x0000 }, /* R27 - Right Line Input 3&4 Volume */ 132 { 0x00DF, 0x01DF }, /* R27 - Right Line Input 3&4 Volume */
135 { 0x00FF, 0x01FF, 0x0000 }, /* R28 - Left Output Volume */ 133 { 0x00FF, 0x01FF }, /* R28 - Left Output Volume */
136 { 0x00FF, 0x01FF, 0x0000 }, /* R29 - Right Output Volume */ 134 { 0x00FF, 0x01FF }, /* R29 - Right Output Volume */
137 { 0x0077, 0x0077, 0x0000 }, /* R30 - Line Outputs Volume */ 135 { 0x0077, 0x0077 }, /* R30 - Line Outputs Volume */
138 { 0x0030, 0x0030, 0x0000 }, /* R31 - HPOUT2 Volume */ 136 { 0x0030, 0x0030 }, /* R31 - HPOUT2 Volume */
139 { 0x00FF, 0x01FF, 0x0000 }, /* R32 - Left OPGA Volume */ 137 { 0x00FF, 0x01FF }, /* R32 - Left OPGA Volume */
140 { 0x00FF, 0x01FF, 0x0000 }, /* R33 - Right OPGA Volume */ 138 { 0x00FF, 0x01FF }, /* R33 - Right OPGA Volume */
141 { 0x007F, 0x007F, 0x0000 }, /* R34 - SPKMIXL Attenuation */ 139 { 0x007F, 0x007F }, /* R34 - SPKMIXL Attenuation */
142 { 0x017F, 0x017F, 0x0000 }, /* R35 - SPKMIXR Attenuation */ 140 { 0x017F, 0x017F }, /* R35 - SPKMIXR Attenuation */
143 { 0x003F, 0x003F, 0x0000 }, /* R36 - SPKOUT Mixers */ 141 { 0x003F, 0x003F }, /* R36 - SPKOUT Mixers */
144 { 0x003F, 0x003F, 0x0000 }, /* R37 - ClassD */ 142 { 0x003F, 0x003F }, /* R37 - ClassD */
145 { 0x00FF, 0x01FF, 0x0000 }, /* R38 - Speaker Volume Left */ 143 { 0x00FF, 0x01FF }, /* R38 - Speaker Volume Left */
146 { 0x00FF, 0x01FF, 0x0000 }, /* R39 - Speaker Volume Right */ 144 { 0x00FF, 0x01FF }, /* R39 - Speaker Volume Right */
147 { 0x00FF, 0x00FF, 0x0000 }, /* R40 - Input Mixer (2) */ 145 { 0x00FF, 0x00FF }, /* R40 - Input Mixer (2) */
148 { 0x01B7, 0x01B7, 0x0000 }, /* R41 - Input Mixer (3) */ 146 { 0x01B7, 0x01B7 }, /* R41 - Input Mixer (3) */
149 { 0x01B7, 0x01B7, 0x0000 }, /* R42 - Input Mixer (4) */ 147 { 0x01B7, 0x01B7 }, /* R42 - Input Mixer (4) */
150 { 0x01C7, 0x01C7, 0x0000 }, /* R43 - Input Mixer (5) */ 148 { 0x01C7, 0x01C7 }, /* R43 - Input Mixer (5) */
151 { 0x01C7, 0x01C7, 0x0000 }, /* R44 - Input Mixer (6) */ 149 { 0x01C7, 0x01C7 }, /* R44 - Input Mixer (6) */
152 { 0x01FF, 0x01FF, 0x0000 }, /* R45 - Output Mixer (1) */ 150 { 0x01FF, 0x01FF }, /* R45 - Output Mixer (1) */
153 { 0x01FF, 0x01FF, 0x0000 }, /* R46 - Output Mixer (2) */ 151 { 0x01FF, 0x01FF }, /* R46 - Output Mixer (2) */
154 { 0x0FFF, 0x0FFF, 0x0000 }, /* R47 - Output Mixer (3) */ 152 { 0x0FFF, 0x0FFF }, /* R47 - Output Mixer (3) */
155 { 0x0FFF, 0x0FFF, 0x0000 }, /* R48 - Output Mixer (4) */ 153 { 0x0FFF, 0x0FFF }, /* R48 - Output Mixer (4) */
156 { 0x0FFF, 0x0FFF, 0x0000 }, /* R49 - Output Mixer (5) */ 154 { 0x0FFF, 0x0FFF }, /* R49 - Output Mixer (5) */
157 { 0x0FFF, 0x0FFF, 0x0000 }, /* R50 - Output Mixer (6) */ 155 { 0x0FFF, 0x0FFF }, /* R50 - Output Mixer (6) */
158 { 0x0038, 0x0038, 0x0000 }, /* R51 - HPOUT2 Mixer */ 156 { 0x0038, 0x0038 }, /* R51 - HPOUT2 Mixer */
159 { 0x0077, 0x0077, 0x0000 }, /* R52 - Line Mixer (1) */ 157 { 0x0077, 0x0077 }, /* R52 - Line Mixer (1) */
160 { 0x0077, 0x0077, 0x0000 }, /* R53 - Line Mixer (2) */ 158 { 0x0077, 0x0077 }, /* R53 - Line Mixer (2) */
161 { 0x03FF, 0x03FF, 0x0000 }, /* R54 - Speaker Mixer */ 159 { 0x03FF, 0x03FF }, /* R54 - Speaker Mixer */
162 { 0x00C1, 0x00C1, 0x0000 }, /* R55 - Additional Control */ 160 { 0x00C1, 0x00C1 }, /* R55 - Additional Control */
163 { 0x00F0, 0x00F0, 0x0000 }, /* R56 - AntiPOP (1) */ 161 { 0x00F0, 0x00F0 }, /* R56 - AntiPOP (1) */
164 { 0x01EF, 0x01EF, 0x0000 }, /* R57 - AntiPOP (2) */ 162 { 0x01EF, 0x01EF }, /* R57 - AntiPOP (2) */
165 { 0x00FF, 0x00FF, 0x0000 }, /* R58 - MICBIAS */ 163 { 0x00FF, 0x00FF }, /* R58 - MICBIAS */
166 { 0x000F, 0x000F, 0x0000 }, /* R59 - LDO 1 */ 164 { 0x000F, 0x000F }, /* R59 - LDO 1 */
167 { 0x0007, 0x0007, 0x0000 }, /* R60 - LDO 2 */ 165 { 0x0007, 0x0007 }, /* R60 - LDO 2 */
168 { 0x0000, 0x0000, 0x0000 }, /* R61 */ 166 { 0x0000, 0x0000 }, /* R61 */
169 { 0x0000, 0x0000, 0x0000 }, /* R62 */ 167 { 0x0000, 0x0000 }, /* R62 */
170 { 0x0000, 0x0000, 0x0000 }, /* R63 */ 168 { 0x0000, 0x0000 }, /* R63 */
171 { 0x0000, 0x0000, 0x0000 }, /* R64 */ 169 { 0x0000, 0x0000 }, /* R64 */
172 { 0x0000, 0x0000, 0x0000 }, /* R65 */ 170 { 0x0000, 0x0000 }, /* R65 */
173 { 0x0000, 0x0000, 0x0000 }, /* R66 */ 171 { 0x0000, 0x0000 }, /* R66 */
174 { 0x0000, 0x0000, 0x0000 }, /* R67 */ 172 { 0x0000, 0x0000 }, /* R67 */
175 { 0x0000, 0x0000, 0x0000 }, /* R68 */ 173 { 0x0000, 0x0000 }, /* R68 */
176 { 0x0000, 0x0000, 0x0000 }, /* R69 */ 174 { 0x0000, 0x0000 }, /* R69 */
177 { 0x0000, 0x0000, 0x0000 }, /* R70 */ 175 { 0x0000, 0x0000 }, /* R70 */
178 { 0x0000, 0x0000, 0x0000 }, /* R71 */ 176 { 0x0000, 0x0000 }, /* R71 */
179 { 0x0000, 0x0000, 0x0000 }, /* R72 */ 177 { 0x0000, 0x0000 }, /* R72 */
180 { 0x0000, 0x0000, 0x0000 }, /* R73 */ 178 { 0x0000, 0x0000 }, /* R73 */
181 { 0x0000, 0x0000, 0x0000 }, /* R74 */ 179 { 0x0000, 0x0000 }, /* R74 */
182 { 0x0000, 0x0000, 0x0000 }, /* R75 */ 180 { 0x0000, 0x0000 }, /* R75 */
183 { 0x8000, 0x8000, 0x0000 }, /* R76 - Charge Pump (1) */ 181 { 0x8000, 0x8000 }, /* R76 - Charge Pump (1) */
184 { 0x0000, 0x0000, 0x0000 }, /* R77 */ 182 { 0x0000, 0x0000 }, /* R77 */
185 { 0x0000, 0x0000, 0x0000 }, /* R78 */ 183 { 0x0000, 0x0000 }, /* R78 */
186 { 0x0000, 0x0000, 0x0000 }, /* R79 */ 184 { 0x0000, 0x0000 }, /* R79 */
187 { 0x0000, 0x0000, 0x0000 }, /* R80 */ 185 { 0x0000, 0x0000 }, /* R80 */
188 { 0x0301, 0x0301, 0x0000 }, /* R81 - Class W (1) */ 186 { 0x0301, 0x0301 }, /* R81 - Class W (1) */
189 { 0x0000, 0x0000, 0x0000 }, /* R82 */ 187 { 0x0000, 0x0000 }, /* R82 */
190 { 0x0000, 0x0000, 0x0000 }, /* R83 */ 188 { 0x0000, 0x0000 }, /* R83 */
191 { 0x333F, 0x333F, 0x0000 }, /* R84 - DC Servo (1) */ 189 { 0x333F, 0x333F }, /* R84 - DC Servo (1) */
192 { 0x0FEF, 0x0FEF, 0x0000 }, /* R85 - DC Servo (2) */ 190 { 0x0FEF, 0x0FEF }, /* R85 - DC Servo (2) */
193 { 0x0000, 0x0000, 0x0000 }, /* R86 */ 191 { 0x0000, 0x0000 }, /* R86 */
194 { 0xFFFF, 0xFFFF, 0x0000 }, /* R87 - DC Servo (4) */ 192 { 0xFFFF, 0xFFFF }, /* R87 - DC Servo (4) */
195 { 0x0333, 0x0000, 0x0000 }, /* R88 - DC Servo Readback */ 193 { 0x0333, 0x0000 }, /* R88 - DC Servo Readback */
196 { 0x0000, 0x0000, 0x0000 }, /* R89 */ 194 { 0x0000, 0x0000 }, /* R89 */
197 { 0x0000, 0x0000, 0x0000 }, /* R90 */ 195 { 0x0000, 0x0000 }, /* R90 */
198 { 0x0000, 0x0000, 0x0000 }, /* R91 */ 196 { 0x0000, 0x0000 }, /* R91 */
199 { 0x0000, 0x0000, 0x0000 }, /* R92 */ 197 { 0x0000, 0x0000 }, /* R92 */
200 { 0x0000, 0x0000, 0x0000 }, /* R93 */ 198 { 0x0000, 0x0000 }, /* R93 */
201 { 0x0000, 0x0000, 0x0000 }, /* R94 */ 199 { 0x0000, 0x0000 }, /* R94 */
202 { 0x0000, 0x0000, 0x0000 }, /* R95 */ 200 { 0x0000, 0x0000 }, /* R95 */
203 { 0x00EE, 0x00EE, 0x0000 }, /* R96 - Analogue HP (1) */ 201 { 0x00EE, 0x00EE }, /* R96 - Analogue HP (1) */
204 { 0x0000, 0x0000, 0x0000 }, /* R97 */ 202 { 0x0000, 0x0000 }, /* R97 */
205 { 0x0000, 0x0000, 0x0000 }, /* R98 */ 203 { 0x0000, 0x0000 }, /* R98 */
206 { 0x0000, 0x0000, 0x0000 }, /* R99 */ 204 { 0x0000, 0x0000 }, /* R99 */
207 { 0x0000, 0x0000, 0x0000 }, /* R100 */ 205 { 0x0000, 0x0000 }, /* R100 */
208 { 0x0000, 0x0000, 0x0000 }, /* R101 */ 206 { 0x0000, 0x0000 }, /* R101 */
209 { 0x0000, 0x0000, 0x0000 }, /* R102 */ 207 { 0x0000, 0x0000 }, /* R102 */
210 { 0x0000, 0x0000, 0x0000 }, /* R103 */ 208 { 0x0000, 0x0000 }, /* R103 */
211 { 0x0000, 0x0000, 0x0000 }, /* R104 */ 209 { 0x0000, 0x0000 }, /* R104 */
212 { 0x0000, 0x0000, 0x0000 }, /* R105 */ 210 { 0x0000, 0x0000 }, /* R105 */
213 { 0x0000, 0x0000, 0x0000 }, /* R106 */ 211 { 0x0000, 0x0000 }, /* R106 */
214 { 0x0000, 0x0000, 0x0000 }, /* R107 */ 212 { 0x0000, 0x0000 }, /* R107 */
215 { 0x0000, 0x0000, 0x0000 }, /* R108 */ 213 { 0x0000, 0x0000 }, /* R108 */
216 { 0x0000, 0x0000, 0x0000 }, /* R109 */ 214 { 0x0000, 0x0000 }, /* R109 */
217 { 0x0000, 0x0000, 0x0000 }, /* R110 */ 215 { 0x0000, 0x0000 }, /* R110 */
218 { 0x0000, 0x0000, 0x0000 }, /* R111 */ 216 { 0x0000, 0x0000 }, /* R111 */
219 { 0x0000, 0x0000, 0x0000 }, /* R112 */ 217 { 0x0000, 0x0000 }, /* R112 */
220 { 0x0000, 0x0000, 0x0000 }, /* R113 */ 218 { 0x0000, 0x0000 }, /* R113 */
221 { 0x0000, 0x0000, 0x0000 }, /* R114 */ 219 { 0x0000, 0x0000 }, /* R114 */
222 { 0x0000, 0x0000, 0x0000 }, /* R115 */ 220 { 0x0000, 0x0000 }, /* R115 */
223 { 0x0000, 0x0000, 0x0000 }, /* R116 */ 221 { 0x0000, 0x0000 }, /* R116 */
224 { 0x0000, 0x0000, 0x0000 }, /* R117 */ 222 { 0x0000, 0x0000 }, /* R117 */
225 { 0x0000, 0x0000, 0x0000 }, /* R118 */ 223 { 0x0000, 0x0000 }, /* R118 */
226 { 0x0000, 0x0000, 0x0000 }, /* R119 */ 224 { 0x0000, 0x0000 }, /* R119 */
227 { 0x0000, 0x0000, 0x0000 }, /* R120 */ 225 { 0x0000, 0x0000 }, /* R120 */
228 { 0x0000, 0x0000, 0x0000 }, /* R121 */ 226 { 0x0000, 0x0000 }, /* R121 */
229 { 0x0000, 0x0000, 0x0000 }, /* R122 */ 227 { 0x0000, 0x0000 }, /* R122 */
230 { 0x0000, 0x0000, 0x0000 }, /* R123 */ 228 { 0x0000, 0x0000 }, /* R123 */
231 { 0x0000, 0x0000, 0x0000 }, /* R124 */ 229 { 0x0000, 0x0000 }, /* R124 */
232 { 0x0000, 0x0000, 0x0000 }, /* R125 */ 230 { 0x0000, 0x0000 }, /* R125 */
233 { 0x0000, 0x0000, 0x0000 }, /* R126 */ 231 { 0x0000, 0x0000 }, /* R126 */
234 { 0x0000, 0x0000, 0x0000 }, /* R127 */ 232 { 0x0000, 0x0000 }, /* R127 */
235 { 0x0000, 0x0000, 0x0000 }, /* R128 */ 233 { 0x0000, 0x0000 }, /* R128 */
236 { 0x0000, 0x0000, 0x0000 }, /* R129 */ 234 { 0x0000, 0x0000 }, /* R129 */
237 { 0x0000, 0x0000, 0x0000 }, /* R130 */ 235 { 0x0000, 0x0000 }, /* R130 */
238 { 0x0000, 0x0000, 0x0000 }, /* R131 */ 236 { 0x0000, 0x0000 }, /* R131 */
239 { 0x0000, 0x0000, 0x0000 }, /* R132 */ 237 { 0x0000, 0x0000 }, /* R132 */
240 { 0x0000, 0x0000, 0x0000 }, /* R133 */ 238 { 0x0000, 0x0000 }, /* R133 */
241 { 0x0000, 0x0000, 0x0000 }, /* R134 */ 239 { 0x0000, 0x0000 }, /* R134 */
242 { 0x0000, 0x0000, 0x0000 }, /* R135 */ 240 { 0x0000, 0x0000 }, /* R135 */
243 { 0x0000, 0x0000, 0x0000 }, /* R136 */ 241 { 0x0000, 0x0000 }, /* R136 */
244 { 0x0000, 0x0000, 0x0000 }, /* R137 */ 242 { 0x0000, 0x0000 }, /* R137 */
245 { 0x0000, 0x0000, 0x0000 }, /* R138 */ 243 { 0x0000, 0x0000 }, /* R138 */
246 { 0x0000, 0x0000, 0x0000 }, /* R139 */ 244 { 0x0000, 0x0000 }, /* R139 */
247 { 0x0000, 0x0000, 0x0000 }, /* R140 */ 245 { 0x0000, 0x0000 }, /* R140 */
248 { 0x0000, 0x0000, 0x0000 }, /* R141 */ 246 { 0x0000, 0x0000 }, /* R141 */
249 { 0x0000, 0x0000, 0x0000 }, /* R142 */ 247 { 0x0000, 0x0000 }, /* R142 */
250 { 0x0000, 0x0000, 0x0000 }, /* R143 */ 248 { 0x0000, 0x0000 }, /* R143 */
251 { 0x0000, 0x0000, 0x0000 }, /* R144 */ 249 { 0x0000, 0x0000 }, /* R144 */
252 { 0x0000, 0x0000, 0x0000 }, /* R145 */ 250 { 0x0000, 0x0000 }, /* R145 */
253 { 0x0000, 0x0000, 0x0000 }, /* R146 */ 251 { 0x0000, 0x0000 }, /* R146 */
254 { 0x0000, 0x0000, 0x0000 }, /* R147 */ 252 { 0x0000, 0x0000 }, /* R147 */
255 { 0x0000, 0x0000, 0x0000 }, /* R148 */ 253 { 0x0000, 0x0000 }, /* R148 */
256 { 0x0000, 0x0000, 0x0000 }, /* R149 */ 254 { 0x0000, 0x0000 }, /* R149 */
257 { 0x0000, 0x0000, 0x0000 }, /* R150 */ 255 { 0x0000, 0x0000 }, /* R150 */
258 { 0x0000, 0x0000, 0x0000 }, /* R151 */ 256 { 0x0000, 0x0000 }, /* R151 */
259 { 0x0000, 0x0000, 0x0000 }, /* R152 */ 257 { 0x0000, 0x0000 }, /* R152 */
260 { 0x0000, 0x0000, 0x0000 }, /* R153 */ 258 { 0x0000, 0x0000 }, /* R153 */
261 { 0x0000, 0x0000, 0x0000 }, /* R154 */ 259 { 0x0000, 0x0000 }, /* R154 */
262 { 0x0000, 0x0000, 0x0000 }, /* R155 */ 260 { 0x0000, 0x0000 }, /* R155 */
263 { 0x0000, 0x0000, 0x0000 }, /* R156 */ 261 { 0x0000, 0x0000 }, /* R156 */
264 { 0x0000, 0x0000, 0x0000 }, /* R157 */ 262 { 0x0000, 0x0000 }, /* R157 */
265 { 0x0000, 0x0000, 0x0000 }, /* R158 */ 263 { 0x0000, 0x0000 }, /* R158 */
266 { 0x0000, 0x0000, 0x0000 }, /* R159 */ 264 { 0x0000, 0x0000 }, /* R159 */
267 { 0x0000, 0x0000, 0x0000 }, /* R160 */ 265 { 0x0000, 0x0000 }, /* R160 */
268 { 0x0000, 0x0000, 0x0000 }, /* R161 */ 266 { 0x0000, 0x0000 }, /* R161 */
269 { 0x0000, 0x0000, 0x0000 }, /* R162 */ 267 { 0x0000, 0x0000 }, /* R162 */
270 { 0x0000, 0x0000, 0x0000 }, /* R163 */ 268 { 0x0000, 0x0000 }, /* R163 */
271 { 0x0000, 0x0000, 0x0000 }, /* R164 */ 269 { 0x0000, 0x0000 }, /* R164 */
272 { 0x0000, 0x0000, 0x0000 }, /* R165 */ 270 { 0x0000, 0x0000 }, /* R165 */
273 { 0x0000, 0x0000, 0x0000 }, /* R166 */ 271 { 0x0000, 0x0000 }, /* R166 */
274 { 0x0000, 0x0000, 0x0000 }, /* R167 */ 272 { 0x0000, 0x0000 }, /* R167 */
275 { 0x0000, 0x0000, 0x0000 }, /* R168 */ 273 { 0x0000, 0x0000 }, /* R168 */
276 { 0x0000, 0x0000, 0x0000 }, /* R169 */ 274 { 0x0000, 0x0000 }, /* R169 */
277 { 0x0000, 0x0000, 0x0000 }, /* R170 */ 275 { 0x0000, 0x0000 }, /* R170 */
278 { 0x0000, 0x0000, 0x0000 }, /* R171 */ 276 { 0x0000, 0x0000 }, /* R171 */
279 { 0x0000, 0x0000, 0x0000 }, /* R172 */ 277 { 0x0000, 0x0000 }, /* R172 */
280 { 0x0000, 0x0000, 0x0000 }, /* R173 */ 278 { 0x0000, 0x0000 }, /* R173 */
281 { 0x0000, 0x0000, 0x0000 }, /* R174 */ 279 { 0x0000, 0x0000 }, /* R174 */
282 { 0x0000, 0x0000, 0x0000 }, /* R175 */ 280 { 0x0000, 0x0000 }, /* R175 */
283 { 0x0000, 0x0000, 0x0000 }, /* R176 */ 281 { 0x0000, 0x0000 }, /* R176 */
284 { 0x0000, 0x0000, 0x0000 }, /* R177 */ 282 { 0x0000, 0x0000 }, /* R177 */
285 { 0x0000, 0x0000, 0x0000 }, /* R178 */ 283 { 0x0000, 0x0000 }, /* R178 */
286 { 0x0000, 0x0000, 0x0000 }, /* R179 */ 284 { 0x0000, 0x0000 }, /* R179 */
287 { 0x0000, 0x0000, 0x0000 }, /* R180 */ 285 { 0x0000, 0x0000 }, /* R180 */
288 { 0x0000, 0x0000, 0x0000 }, /* R181 */ 286 { 0x0000, 0x0000 }, /* R181 */
289 { 0x0000, 0x0000, 0x0000 }, /* R182 */ 287 { 0x0000, 0x0000 }, /* R182 */
290 { 0x0000, 0x0000, 0x0000 }, /* R183 */ 288 { 0x0000, 0x0000 }, /* R183 */
291 { 0x0000, 0x0000, 0x0000 }, /* R184 */ 289 { 0x0000, 0x0000 }, /* R184 */
292 { 0x0000, 0x0000, 0x0000 }, /* R185 */ 290 { 0x0000, 0x0000 }, /* R185 */
293 { 0x0000, 0x0000, 0x0000 }, /* R186 */ 291 { 0x0000, 0x0000 }, /* R186 */
294 { 0x0000, 0x0000, 0x0000 }, /* R187 */ 292 { 0x0000, 0x0000 }, /* R187 */
295 { 0x0000, 0x0000, 0x0000 }, /* R188 */ 293 { 0x0000, 0x0000 }, /* R188 */
296 { 0x0000, 0x0000, 0x0000 }, /* R189 */ 294 { 0x0000, 0x0000 }, /* R189 */
297 { 0x0000, 0x0000, 0x0000 }, /* R190 */ 295 { 0x0000, 0x0000 }, /* R190 */
298 { 0x0000, 0x0000, 0x0000 }, /* R191 */ 296 { 0x0000, 0x0000 }, /* R191 */
299 { 0x0000, 0x0000, 0x0000 }, /* R192 */ 297 { 0x0000, 0x0000 }, /* R192 */
300 { 0x0000, 0x0000, 0x0000 }, /* R193 */ 298 { 0x0000, 0x0000 }, /* R193 */
301 { 0x0000, 0x0000, 0x0000 }, /* R194 */ 299 { 0x0000, 0x0000 }, /* R194 */
302 { 0x0000, 0x0000, 0x0000 }, /* R195 */ 300 { 0x0000, 0x0000 }, /* R195 */
303 { 0x0000, 0x0000, 0x0000 }, /* R196 */ 301 { 0x0000, 0x0000 }, /* R196 */
304 { 0x0000, 0x0000, 0x0000 }, /* R197 */ 302 { 0x0000, 0x0000 }, /* R197 */
305 { 0x0000, 0x0000, 0x0000 }, /* R198 */ 303 { 0x0000, 0x0000 }, /* R198 */
306 { 0x0000, 0x0000, 0x0000 }, /* R199 */ 304 { 0x0000, 0x0000 }, /* R199 */
307 { 0x0000, 0x0000, 0x0000 }, /* R200 */ 305 { 0x0000, 0x0000 }, /* R200 */
308 { 0x0000, 0x0000, 0x0000 }, /* R201 */ 306 { 0x0000, 0x0000 }, /* R201 */
309 { 0x0000, 0x0000, 0x0000 }, /* R202 */ 307 { 0x0000, 0x0000 }, /* R202 */
310 { 0x0000, 0x0000, 0x0000 }, /* R203 */ 308 { 0x0000, 0x0000 }, /* R203 */
311 { 0x0000, 0x0000, 0x0000 }, /* R204 */ 309 { 0x0000, 0x0000 }, /* R204 */
312 { 0x0000, 0x0000, 0x0000 }, /* R205 */ 310 { 0x0000, 0x0000 }, /* R205 */
313 { 0x0000, 0x0000, 0x0000 }, /* R206 */ 311 { 0x0000, 0x0000 }, /* R206 */
314 { 0x0000, 0x0000, 0x0000 }, /* R207 */ 312 { 0x0000, 0x0000 }, /* R207 */
315 { 0x0000, 0x0000, 0x0000 }, /* R208 */ 313 { 0x0000, 0x0000 }, /* R208 */
316 { 0x0000, 0x0000, 0x0000 }, /* R209 */ 314 { 0x0000, 0x0000 }, /* R209 */
317 { 0x0000, 0x0000, 0x0000 }, /* R210 */ 315 { 0x0000, 0x0000 }, /* R210 */
318 { 0x0000, 0x0000, 0x0000 }, /* R211 */ 316 { 0x0000, 0x0000 }, /* R211 */
319 { 0x0000, 0x0000, 0x0000 }, /* R212 */ 317 { 0x0000, 0x0000 }, /* R212 */
320 { 0x0000, 0x0000, 0x0000 }, /* R213 */ 318 { 0x0000, 0x0000 }, /* R213 */
321 { 0x0000, 0x0000, 0x0000 }, /* R214 */ 319 { 0x0000, 0x0000 }, /* R214 */
322 { 0x0000, 0x0000, 0x0000 }, /* R215 */ 320 { 0x0000, 0x0000 }, /* R215 */
323 { 0x0000, 0x0000, 0x0000 }, /* R216 */ 321 { 0x0000, 0x0000 }, /* R216 */
324 { 0x0000, 0x0000, 0x0000 }, /* R217 */ 322 { 0x0000, 0x0000 }, /* R217 */
325 { 0x0000, 0x0000, 0x0000 }, /* R218 */ 323 { 0x0000, 0x0000 }, /* R218 */
326 { 0x0000, 0x0000, 0x0000 }, /* R219 */ 324 { 0x0000, 0x0000 }, /* R219 */
327 { 0x0000, 0x0000, 0x0000 }, /* R220 */ 325 { 0x0000, 0x0000 }, /* R220 */
328 { 0x0000, 0x0000, 0x0000 }, /* R221 */ 326 { 0x0000, 0x0000 }, /* R221 */
329 { 0x0000, 0x0000, 0x0000 }, /* R222 */ 327 { 0x0000, 0x0000 }, /* R222 */
330 { 0x0000, 0x0000, 0x0000 }, /* R223 */ 328 { 0x0000, 0x0000 }, /* R223 */
331 { 0x0000, 0x0000, 0x0000 }, /* R224 */ 329 { 0x0000, 0x0000 }, /* R224 */
332 { 0x0000, 0x0000, 0x0000 }, /* R225 */ 330 { 0x0000, 0x0000 }, /* R225 */
333 { 0x0000, 0x0000, 0x0000 }, /* R226 */ 331 { 0x0000, 0x0000 }, /* R226 */
334 { 0x0000, 0x0000, 0x0000 }, /* R227 */ 332 { 0x0000, 0x0000 }, /* R227 */
335 { 0x0000, 0x0000, 0x0000 }, /* R228 */ 333 { 0x0000, 0x0000 }, /* R228 */
336 { 0x0000, 0x0000, 0x0000 }, /* R229 */ 334 { 0x0000, 0x0000 }, /* R229 */
337 { 0x0000, 0x0000, 0x0000 }, /* R230 */ 335 { 0x0000, 0x0000 }, /* R230 */
338 { 0x0000, 0x0000, 0x0000 }, /* R231 */ 336 { 0x0000, 0x0000 }, /* R231 */
339 { 0x0000, 0x0000, 0x0000 }, /* R232 */ 337 { 0x0000, 0x0000 }, /* R232 */
340 { 0x0000, 0x0000, 0x0000 }, /* R233 */ 338 { 0x0000, 0x0000 }, /* R233 */
341 { 0x0000, 0x0000, 0x0000 }, /* R234 */ 339 { 0x0000, 0x0000 }, /* R234 */
342 { 0x0000, 0x0000, 0x0000 }, /* R235 */ 340 { 0x0000, 0x0000 }, /* R235 */
343 { 0x0000, 0x0000, 0x0000 }, /* R236 */ 341 { 0x0000, 0x0000 }, /* R236 */
344 { 0x0000, 0x0000, 0x0000 }, /* R237 */ 342 { 0x0000, 0x0000 }, /* R237 */
345 { 0x0000, 0x0000, 0x0000 }, /* R238 */ 343 { 0x0000, 0x0000 }, /* R238 */
346 { 0x0000, 0x0000, 0x0000 }, /* R239 */ 344 { 0x0000, 0x0000 }, /* R239 */
347 { 0x0000, 0x0000, 0x0000 }, /* R240 */ 345 { 0x0000, 0x0000 }, /* R240 */
348 { 0x0000, 0x0000, 0x0000 }, /* R241 */ 346 { 0x0000, 0x0000 }, /* R241 */
349 { 0x0000, 0x0000, 0x0000 }, /* R242 */ 347 { 0x0000, 0x0000 }, /* R242 */
350 { 0x0000, 0x0000, 0x0000 }, /* R243 */ 348 { 0x0000, 0x0000 }, /* R243 */
351 { 0x0000, 0x0000, 0x0000 }, /* R244 */ 349 { 0x0000, 0x0000 }, /* R244 */
352 { 0x0000, 0x0000, 0x0000 }, /* R245 */ 350 { 0x0000, 0x0000 }, /* R245 */
353 { 0x0000, 0x0000, 0x0000 }, /* R246 */ 351 { 0x0000, 0x0000 }, /* R246 */
354 { 0x0000, 0x0000, 0x0000 }, /* R247 */ 352 { 0x0000, 0x0000 }, /* R247 */
355 { 0x0000, 0x0000, 0x0000 }, /* R248 */ 353 { 0x0000, 0x0000 }, /* R248 */
356 { 0x0000, 0x0000, 0x0000 }, /* R249 */ 354 { 0x0000, 0x0000 }, /* R249 */
357 { 0x0000, 0x0000, 0x0000 }, /* R250 */ 355 { 0x0000, 0x0000 }, /* R250 */
358 { 0x0000, 0x0000, 0x0000 }, /* R251 */ 356 { 0x0000, 0x0000 }, /* R251 */
359 { 0x0000, 0x0000, 0x0000 }, /* R252 */ 357 { 0x0000, 0x0000 }, /* R252 */
360 { 0x0000, 0x0000, 0x0000 }, /* R253 */ 358 { 0x0000, 0x0000 }, /* R253 */
361 { 0x0000, 0x0000, 0x0000 }, /* R254 */ 359 { 0x0000, 0x0000 }, /* R254 */
362 { 0x0000, 0x0000, 0x0000 }, /* R255 */ 360 { 0x0000, 0x0000 }, /* R255 */
363 { 0x000F, 0x0000, 0x0000 }, /* R256 - Chip Revision */ 361 { 0x000F, 0x0000 }, /* R256 - Chip Revision */
364 { 0x0074, 0x0074, 0x0000 }, /* R257 - Control Interface */ 362 { 0x0074, 0x0074 }, /* R257 - Control Interface */
365 { 0x0000, 0x0000, 0x0000 }, /* R258 */ 363 { 0x0000, 0x0000 }, /* R258 */
366 { 0x0000, 0x0000, 0x0000 }, /* R259 */ 364 { 0x0000, 0x0000 }, /* R259 */
367 { 0x0000, 0x0000, 0x0000 }, /* R260 */ 365 { 0x0000, 0x0000 }, /* R260 */
368 { 0x0000, 0x0000, 0x0000 }, /* R261 */ 366 { 0x0000, 0x0000 }, /* R261 */
369 { 0x0000, 0x0000, 0x0000 }, /* R262 */ 367 { 0x0000, 0x0000 }, /* R262 */
370 { 0x0000, 0x0000, 0x0000 }, /* R263 */ 368 { 0x0000, 0x0000 }, /* R263 */
371 { 0x0000, 0x0000, 0x0000 }, /* R264 */ 369 { 0x0000, 0x0000 }, /* R264 */
372 { 0x0000, 0x0000, 0x0000 }, /* R265 */ 370 { 0x0000, 0x0000 }, /* R265 */
373 { 0x0000, 0x0000, 0x0000 }, /* R266 */ 371 { 0x0000, 0x0000 }, /* R266 */
374 { 0x0000, 0x0000, 0x0000 }, /* R267 */ 372 { 0x0000, 0x0000 }, /* R267 */
375 { 0x0000, 0x0000, 0x0000 }, /* R268 */ 373 { 0x0000, 0x0000 }, /* R268 */
376 { 0x0000, 0x0000, 0x0000 }, /* R269 */ 374 { 0x0000, 0x0000 }, /* R269 */
377 { 0x0000, 0x0000, 0x0000 }, /* R270 */ 375 { 0x0000, 0x0000 }, /* R270 */
378 { 0x0000, 0x0000, 0x0000 }, /* R271 */ 376 { 0x0000, 0x0000 }, /* R271 */
379 { 0x807F, 0x837F, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */ 377 { 0x807F, 0x837F }, /* R272 - Write Sequencer Ctrl (1) */
380 { 0x017F, 0x0000, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */ 378 { 0x017F, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
381 { 0x0000, 0x0000, 0x0000 }, /* R274 */ 379 { 0x0000, 0x0000 }, /* R274 */
382 { 0x0000, 0x0000, 0x0000 }, /* R275 */ 380 { 0x0000, 0x0000 }, /* R275 */
383 { 0x0000, 0x0000, 0x0000 }, /* R276 */ 381 { 0x0000, 0x0000 }, /* R276 */
384 { 0x0000, 0x0000, 0x0000 }, /* R277 */ 382 { 0x0000, 0x0000 }, /* R277 */
385 { 0x0000, 0x0000, 0x0000 }, /* R278 */ 383 { 0x0000, 0x0000 }, /* R278 */
386 { 0x0000, 0x0000, 0x0000 }, /* R279 */ 384 { 0x0000, 0x0000 }, /* R279 */
387 { 0x0000, 0x0000, 0x0000 }, /* R280 */ 385 { 0x0000, 0x0000 }, /* R280 */
388 { 0x0000, 0x0000, 0x0000 }, /* R281 */ 386 { 0x0000, 0x0000 }, /* R281 */
389 { 0x0000, 0x0000, 0x0000 }, /* R282 */ 387 { 0x0000, 0x0000 }, /* R282 */
390 { 0x0000, 0x0000, 0x0000 }, /* R283 */ 388 { 0x0000, 0x0000 }, /* R283 */
391 { 0x0000, 0x0000, 0x0000 }, /* R284 */ 389 { 0x0000, 0x0000 }, /* R284 */
392 { 0x0000, 0x0000, 0x0000 }, /* R285 */ 390 { 0x0000, 0x0000 }, /* R285 */
393 { 0x0000, 0x0000, 0x0000 }, /* R286 */ 391 { 0x0000, 0x0000 }, /* R286 */
394 { 0x0000, 0x0000, 0x0000 }, /* R287 */ 392 { 0x0000, 0x0000 }, /* R287 */
395 { 0x0000, 0x0000, 0x0000 }, /* R288 */ 393 { 0x0000, 0x0000 }, /* R288 */
396 { 0x0000, 0x0000, 0x0000 }, /* R289 */ 394 { 0x0000, 0x0000 }, /* R289 */
397 { 0x0000, 0x0000, 0x0000 }, /* R290 */ 395 { 0x0000, 0x0000 }, /* R290 */
398 { 0x0000, 0x0000, 0x0000 }, /* R291 */ 396 { 0x0000, 0x0000 }, /* R291 */
399 { 0x0000, 0x0000, 0x0000 }, /* R292 */ 397 { 0x0000, 0x0000 }, /* R292 */
400 { 0x0000, 0x0000, 0x0000 }, /* R293 */ 398 { 0x0000, 0x0000 }, /* R293 */
401 { 0x0000, 0x0000, 0x0000 }, /* R294 */ 399 { 0x0000, 0x0000 }, /* R294 */
402 { 0x0000, 0x0000, 0x0000 }, /* R295 */ 400 { 0x0000, 0x0000 }, /* R295 */
403 { 0x0000, 0x0000, 0x0000 }, /* R296 */ 401 { 0x0000, 0x0000 }, /* R296 */
404 { 0x0000, 0x0000, 0x0000 }, /* R297 */ 402 { 0x0000, 0x0000 }, /* R297 */
405 { 0x0000, 0x0000, 0x0000 }, /* R298 */ 403 { 0x0000, 0x0000 }, /* R298 */
406 { 0x0000, 0x0000, 0x0000 }, /* R299 */ 404 { 0x0000, 0x0000 }, /* R299 */
407 { 0x0000, 0x0000, 0x0000 }, /* R300 */ 405 { 0x0000, 0x0000 }, /* R300 */
408 { 0x0000, 0x0000, 0x0000 }, /* R301 */ 406 { 0x0000, 0x0000 }, /* R301 */
409 { 0x0000, 0x0000, 0x0000 }, /* R302 */ 407 { 0x0000, 0x0000 }, /* R302 */
410 { 0x0000, 0x0000, 0x0000 }, /* R303 */ 408 { 0x0000, 0x0000 }, /* R303 */
411 { 0x0000, 0x0000, 0x0000 }, /* R304 */ 409 { 0x0000, 0x0000 }, /* R304 */
412 { 0x0000, 0x0000, 0x0000 }, /* R305 */ 410 { 0x0000, 0x0000 }, /* R305 */
413 { 0x0000, 0x0000, 0x0000 }, /* R306 */ 411 { 0x0000, 0x0000 }, /* R306 */
414 { 0x0000, 0x0000, 0x0000 }, /* R307 */ 412 { 0x0000, 0x0000 }, /* R307 */
415 { 0x0000, 0x0000, 0x0000 }, /* R308 */ 413 { 0x0000, 0x0000 }, /* R308 */
416 { 0x0000, 0x0000, 0x0000 }, /* R309 */ 414 { 0x0000, 0x0000 }, /* R309 */
417 { 0x0000, 0x0000, 0x0000 }, /* R310 */ 415 { 0x0000, 0x0000 }, /* R310 */
418 { 0x0000, 0x0000, 0x0000 }, /* R311 */ 416 { 0x0000, 0x0000 }, /* R311 */
419 { 0x0000, 0x0000, 0x0000 }, /* R312 */ 417 { 0x0000, 0x0000 }, /* R312 */
420 { 0x0000, 0x0000, 0x0000 }, /* R313 */ 418 { 0x0000, 0x0000 }, /* R313 */
421 { 0x0000, 0x0000, 0x0000 }, /* R314 */ 419 { 0x0000, 0x0000 }, /* R314 */
422 { 0x0000, 0x0000, 0x0000 }, /* R315 */ 420 { 0x0000, 0x0000 }, /* R315 */
423 { 0x0000, 0x0000, 0x0000 }, /* R316 */ 421 { 0x0000, 0x0000 }, /* R316 */
424 { 0x0000, 0x0000, 0x0000 }, /* R317 */ 422 { 0x0000, 0x0000 }, /* R317 */
425 { 0x0000, 0x0000, 0x0000 }, /* R318 */ 423 { 0x0000, 0x0000 }, /* R318 */
426 { 0x0000, 0x0000, 0x0000 }, /* R319 */ 424 { 0x0000, 0x0000 }, /* R319 */
427 { 0x0000, 0x0000, 0x0000 }, /* R320 */ 425 { 0x0000, 0x0000 }, /* R320 */
428 { 0x0000, 0x0000, 0x0000 }, /* R321 */ 426 { 0x0000, 0x0000 }, /* R321 */
429 { 0x0000, 0x0000, 0x0000 }, /* R322 */ 427 { 0x0000, 0x0000 }, /* R322 */
430 { 0x0000, 0x0000, 0x0000 }, /* R323 */ 428 { 0x0000, 0x0000 }, /* R323 */
431 { 0x0000, 0x0000, 0x0000 }, /* R324 */ 429 { 0x0000, 0x0000 }, /* R324 */
432 { 0x0000, 0x0000, 0x0000 }, /* R325 */ 430 { 0x0000, 0x0000 }, /* R325 */
433 { 0x0000, 0x0000, 0x0000 }, /* R326 */ 431 { 0x0000, 0x0000 }, /* R326 */
434 { 0x0000, 0x0000, 0x0000 }, /* R327 */ 432 { 0x0000, 0x0000 }, /* R327 */
435 { 0x0000, 0x0000, 0x0000 }, /* R328 */ 433 { 0x0000, 0x0000 }, /* R328 */
436 { 0x0000, 0x0000, 0x0000 }, /* R329 */ 434 { 0x0000, 0x0000 }, /* R329 */
437 { 0x0000, 0x0000, 0x0000 }, /* R330 */ 435 { 0x0000, 0x0000 }, /* R330 */
438 { 0x0000, 0x0000, 0x0000 }, /* R331 */ 436 { 0x0000, 0x0000 }, /* R331 */
439 { 0x0000, 0x0000, 0x0000 }, /* R332 */ 437 { 0x0000, 0x0000 }, /* R332 */
440 { 0x0000, 0x0000, 0x0000 }, /* R333 */ 438 { 0x0000, 0x0000 }, /* R333 */
441 { 0x0000, 0x0000, 0x0000 }, /* R334 */ 439 { 0x0000, 0x0000 }, /* R334 */
442 { 0x0000, 0x0000, 0x0000 }, /* R335 */ 440 { 0x0000, 0x0000 }, /* R335 */
443 { 0x0000, 0x0000, 0x0000 }, /* R336 */ 441 { 0x0000, 0x0000 }, /* R336 */
444 { 0x0000, 0x0000, 0x0000 }, /* R337 */ 442 { 0x0000, 0x0000 }, /* R337 */
445 { 0x0000, 0x0000, 0x0000 }, /* R338 */ 443 { 0x0000, 0x0000 }, /* R338 */
446 { 0x0000, 0x0000, 0x0000 }, /* R339 */ 444 { 0x0000, 0x0000 }, /* R339 */
447 { 0x0000, 0x0000, 0x0000 }, /* R340 */ 445 { 0x0000, 0x0000 }, /* R340 */
448 { 0x0000, 0x0000, 0x0000 }, /* R341 */ 446 { 0x0000, 0x0000 }, /* R341 */
449 { 0x0000, 0x0000, 0x0000 }, /* R342 */ 447 { 0x0000, 0x0000 }, /* R342 */
450 { 0x0000, 0x0000, 0x0000 }, /* R343 */ 448 { 0x0000, 0x0000 }, /* R343 */
451 { 0x0000, 0x0000, 0x0000 }, /* R344 */ 449 { 0x0000, 0x0000 }, /* R344 */
452 { 0x0000, 0x0000, 0x0000 }, /* R345 */ 450 { 0x0000, 0x0000 }, /* R345 */
453 { 0x0000, 0x0000, 0x0000 }, /* R346 */ 451 { 0x0000, 0x0000 }, /* R346 */
454 { 0x0000, 0x0000, 0x0000 }, /* R347 */ 452 { 0x0000, 0x0000 }, /* R347 */
455 { 0x0000, 0x0000, 0x0000 }, /* R348 */ 453 { 0x0000, 0x0000 }, /* R348 */
456 { 0x0000, 0x0000, 0x0000 }, /* R349 */ 454 { 0x0000, 0x0000 }, /* R349 */
457 { 0x0000, 0x0000, 0x0000 }, /* R350 */ 455 { 0x0000, 0x0000 }, /* R350 */
458 { 0x0000, 0x0000, 0x0000 }, /* R351 */ 456 { 0x0000, 0x0000 }, /* R351 */
459 { 0x0000, 0x0000, 0x0000 }, /* R352 */ 457 { 0x0000, 0x0000 }, /* R352 */
460 { 0x0000, 0x0000, 0x0000 }, /* R353 */ 458 { 0x0000, 0x0000 }, /* R353 */
461 { 0x0000, 0x0000, 0x0000 }, /* R354 */ 459 { 0x0000, 0x0000 }, /* R354 */
462 { 0x0000, 0x0000, 0x0000 }, /* R355 */ 460 { 0x0000, 0x0000 }, /* R355 */
463 { 0x0000, 0x0000, 0x0000 }, /* R356 */ 461 { 0x0000, 0x0000 }, /* R356 */
464 { 0x0000, 0x0000, 0x0000 }, /* R357 */ 462 { 0x0000, 0x0000 }, /* R357 */
465 { 0x0000, 0x0000, 0x0000 }, /* R358 */ 463 { 0x0000, 0x0000 }, /* R358 */
466 { 0x0000, 0x0000, 0x0000 }, /* R359 */ 464 { 0x0000, 0x0000 }, /* R359 */
467 { 0x0000, 0x0000, 0x0000 }, /* R360 */ 465 { 0x0000, 0x0000 }, /* R360 */
468 { 0x0000, 0x0000, 0x0000 }, /* R361 */ 466 { 0x0000, 0x0000 }, /* R361 */
469 { 0x0000, 0x0000, 0x0000 }, /* R362 */ 467 { 0x0000, 0x0000 }, /* R362 */
470 { 0x0000, 0x0000, 0x0000 }, /* R363 */ 468 { 0x0000, 0x0000 }, /* R363 */
471 { 0x0000, 0x0000, 0x0000 }, /* R364 */ 469 { 0x0000, 0x0000 }, /* R364 */
472 { 0x0000, 0x0000, 0x0000 }, /* R365 */ 470 { 0x0000, 0x0000 }, /* R365 */
473 { 0x0000, 0x0000, 0x0000 }, /* R366 */ 471 { 0x0000, 0x0000 }, /* R366 */
474 { 0x0000, 0x0000, 0x0000 }, /* R367 */ 472 { 0x0000, 0x0000 }, /* R367 */
475 { 0x0000, 0x0000, 0x0000 }, /* R368 */ 473 { 0x0000, 0x0000 }, /* R368 */
476 { 0x0000, 0x0000, 0x0000 }, /* R369 */ 474 { 0x0000, 0x0000 }, /* R369 */
477 { 0x0000, 0x0000, 0x0000 }, /* R370 */ 475 { 0x0000, 0x0000 }, /* R370 */
478 { 0x0000, 0x0000, 0x0000 }, /* R371 */ 476 { 0x0000, 0x0000 }, /* R371 */
479 { 0x0000, 0x0000, 0x0000 }, /* R372 */ 477 { 0x0000, 0x0000 }, /* R372 */
480 { 0x0000, 0x0000, 0x0000 }, /* R373 */ 478 { 0x0000, 0x0000 }, /* R373 */
481 { 0x0000, 0x0000, 0x0000 }, /* R374 */ 479 { 0x0000, 0x0000 }, /* R374 */
482 { 0x0000, 0x0000, 0x0000 }, /* R375 */ 480 { 0x0000, 0x0000 }, /* R375 */
483 { 0x0000, 0x0000, 0x0000 }, /* R376 */ 481 { 0x0000, 0x0000 }, /* R376 */
484 { 0x0000, 0x0000, 0x0000 }, /* R377 */ 482 { 0x0000, 0x0000 }, /* R377 */
485 { 0x0000, 0x0000, 0x0000 }, /* R378 */ 483 { 0x0000, 0x0000 }, /* R378 */
486 { 0x0000, 0x0000, 0x0000 }, /* R379 */ 484 { 0x0000, 0x0000 }, /* R379 */
487 { 0x0000, 0x0000, 0x0000 }, /* R380 */ 485 { 0x0000, 0x0000 }, /* R380 */
488 { 0x0000, 0x0000, 0x0000 }, /* R381 */ 486 { 0x0000, 0x0000 }, /* R381 */
489 { 0x0000, 0x0000, 0x0000 }, /* R382 */ 487 { 0x0000, 0x0000 }, /* R382 */
490 { 0x0000, 0x0000, 0x0000 }, /* R383 */ 488 { 0x0000, 0x0000 }, /* R383 */
491 { 0x0000, 0x0000, 0x0000 }, /* R384 */ 489 { 0x0000, 0x0000 }, /* R384 */
492 { 0x0000, 0x0000, 0x0000 }, /* R385 */ 490 { 0x0000, 0x0000 }, /* R385 */
493 { 0x0000, 0x0000, 0x0000 }, /* R386 */ 491 { 0x0000, 0x0000 }, /* R386 */
494 { 0x0000, 0x0000, 0x0000 }, /* R387 */ 492 { 0x0000, 0x0000 }, /* R387 */
495 { 0x0000, 0x0000, 0x0000 }, /* R388 */ 493 { 0x0000, 0x0000 }, /* R388 */
496 { 0x0000, 0x0000, 0x0000 }, /* R389 */ 494 { 0x0000, 0x0000 }, /* R389 */
497 { 0x0000, 0x0000, 0x0000 }, /* R390 */ 495 { 0x0000, 0x0000 }, /* R390 */
498 { 0x0000, 0x0000, 0x0000 }, /* R391 */ 496 { 0x0000, 0x0000 }, /* R391 */
499 { 0x0000, 0x0000, 0x0000 }, /* R392 */ 497 { 0x0000, 0x0000 }, /* R392 */
500 { 0x0000, 0x0000, 0x0000 }, /* R393 */ 498 { 0x0000, 0x0000 }, /* R393 */
501 { 0x0000, 0x0000, 0x0000 }, /* R394 */ 499 { 0x0000, 0x0000 }, /* R394 */
502 { 0x0000, 0x0000, 0x0000 }, /* R395 */ 500 { 0x0000, 0x0000 }, /* R395 */
503 { 0x0000, 0x0000, 0x0000 }, /* R396 */ 501 { 0x0000, 0x0000 }, /* R396 */
504 { 0x0000, 0x0000, 0x0000 }, /* R397 */ 502 { 0x0000, 0x0000 }, /* R397 */
505 { 0x0000, 0x0000, 0x0000 }, /* R398 */ 503 { 0x0000, 0x0000 }, /* R398 */
506 { 0x0000, 0x0000, 0x0000 }, /* R399 */ 504 { 0x0000, 0x0000 }, /* R399 */
507 { 0x0000, 0x0000, 0x0000 }, /* R400 */ 505 { 0x0000, 0x0000 }, /* R400 */
508 { 0x0000, 0x0000, 0x0000 }, /* R401 */ 506 { 0x0000, 0x0000 }, /* R401 */
509 { 0x0000, 0x0000, 0x0000 }, /* R402 */ 507 { 0x0000, 0x0000 }, /* R402 */
510 { 0x0000, 0x0000, 0x0000 }, /* R403 */ 508 { 0x0000, 0x0000 }, /* R403 */
511 { 0x0000, 0x0000, 0x0000 }, /* R404 */ 509 { 0x0000, 0x0000 }, /* R404 */
512 { 0x0000, 0x0000, 0x0000 }, /* R405 */ 510 { 0x0000, 0x0000 }, /* R405 */
513 { 0x0000, 0x0000, 0x0000 }, /* R406 */ 511 { 0x0000, 0x0000 }, /* R406 */
514 { 0x0000, 0x0000, 0x0000 }, /* R407 */ 512 { 0x0000, 0x0000 }, /* R407 */
515 { 0x0000, 0x0000, 0x0000 }, /* R408 */ 513 { 0x0000, 0x0000 }, /* R408 */
516 { 0x0000, 0x0000, 0x0000 }, /* R409 */ 514 { 0x0000, 0x0000 }, /* R409 */
517 { 0x0000, 0x0000, 0x0000 }, /* R410 */ 515 { 0x0000, 0x0000 }, /* R410 */
518 { 0x0000, 0x0000, 0x0000 }, /* R411 */ 516 { 0x0000, 0x0000 }, /* R411 */
519 { 0x0000, 0x0000, 0x0000 }, /* R412 */ 517 { 0x0000, 0x0000 }, /* R412 */
520 { 0x0000, 0x0000, 0x0000 }, /* R413 */ 518 { 0x0000, 0x0000 }, /* R413 */
521 { 0x0000, 0x0000, 0x0000 }, /* R414 */ 519 { 0x0000, 0x0000 }, /* R414 */
522 { 0x0000, 0x0000, 0x0000 }, /* R415 */ 520 { 0x0000, 0x0000 }, /* R415 */
523 { 0x0000, 0x0000, 0x0000 }, /* R416 */ 521 { 0x0000, 0x0000 }, /* R416 */
524 { 0x0000, 0x0000, 0x0000 }, /* R417 */ 522 { 0x0000, 0x0000 }, /* R417 */
525 { 0x0000, 0x0000, 0x0000 }, /* R418 */ 523 { 0x0000, 0x0000 }, /* R418 */
526 { 0x0000, 0x0000, 0x0000 }, /* R419 */ 524 { 0x0000, 0x0000 }, /* R419 */
527 { 0x0000, 0x0000, 0x0000 }, /* R420 */ 525 { 0x0000, 0x0000 }, /* R420 */
528 { 0x0000, 0x0000, 0x0000 }, /* R421 */ 526 { 0x0000, 0x0000 }, /* R421 */
529 { 0x0000, 0x0000, 0x0000 }, /* R422 */ 527 { 0x0000, 0x0000 }, /* R422 */
530 { 0x0000, 0x0000, 0x0000 }, /* R423 */ 528 { 0x0000, 0x0000 }, /* R423 */
531 { 0x0000, 0x0000, 0x0000 }, /* R424 */ 529 { 0x0000, 0x0000 }, /* R424 */
532 { 0x0000, 0x0000, 0x0000 }, /* R425 */ 530 { 0x0000, 0x0000 }, /* R425 */
533 { 0x0000, 0x0000, 0x0000 }, /* R426 */ 531 { 0x0000, 0x0000 }, /* R426 */
534 { 0x0000, 0x0000, 0x0000 }, /* R427 */ 532 { 0x0000, 0x0000 }, /* R427 */
535 { 0x0000, 0x0000, 0x0000 }, /* R428 */ 533 { 0x0000, 0x0000 }, /* R428 */
536 { 0x0000, 0x0000, 0x0000 }, /* R429 */ 534 { 0x0000, 0x0000 }, /* R429 */
537 { 0x0000, 0x0000, 0x0000 }, /* R430 */ 535 { 0x0000, 0x0000 }, /* R430 */
538 { 0x0000, 0x0000, 0x0000 }, /* R431 */ 536 { 0x0000, 0x0000 }, /* R431 */
539 { 0x0000, 0x0000, 0x0000 }, /* R432 */ 537 { 0x0000, 0x0000 }, /* R432 */
540 { 0x0000, 0x0000, 0x0000 }, /* R433 */ 538 { 0x0000, 0x0000 }, /* R433 */
541 { 0x0000, 0x0000, 0x0000 }, /* R434 */ 539 { 0x0000, 0x0000 }, /* R434 */
542 { 0x0000, 0x0000, 0x0000 }, /* R435 */ 540 { 0x0000, 0x0000 }, /* R435 */
543 { 0x0000, 0x0000, 0x0000 }, /* R436 */ 541 { 0x0000, 0x0000 }, /* R436 */
544 { 0x0000, 0x0000, 0x0000 }, /* R437 */ 542 { 0x0000, 0x0000 }, /* R437 */
545 { 0x0000, 0x0000, 0x0000 }, /* R438 */ 543 { 0x0000, 0x0000 }, /* R438 */
546 { 0x0000, 0x0000, 0x0000 }, /* R439 */ 544 { 0x0000, 0x0000 }, /* R439 */
547 { 0x0000, 0x0000, 0x0000 }, /* R440 */ 545 { 0x0000, 0x0000 }, /* R440 */
548 { 0x0000, 0x0000, 0x0000 }, /* R441 */ 546 { 0x0000, 0x0000 }, /* R441 */
549 { 0x0000, 0x0000, 0x0000 }, /* R442 */ 547 { 0x0000, 0x0000 }, /* R442 */
550 { 0x0000, 0x0000, 0x0000 }, /* R443 */ 548 { 0x0000, 0x0000 }, /* R443 */
551 { 0x0000, 0x0000, 0x0000 }, /* R444 */ 549 { 0x0000, 0x0000 }, /* R444 */
552 { 0x0000, 0x0000, 0x0000 }, /* R445 */ 550 { 0x0000, 0x0000 }, /* R445 */
553 { 0x0000, 0x0000, 0x0000 }, /* R446 */ 551 { 0x0000, 0x0000 }, /* R446 */
554 { 0x0000, 0x0000, 0x0000 }, /* R447 */ 552 { 0x0000, 0x0000 }, /* R447 */
555 { 0x0000, 0x0000, 0x0000 }, /* R448 */ 553 { 0x0000, 0x0000 }, /* R448 */
556 { 0x0000, 0x0000, 0x0000 }, /* R449 */ 554 { 0x0000, 0x0000 }, /* R449 */
557 { 0x0000, 0x0000, 0x0000 }, /* R450 */ 555 { 0x0000, 0x0000 }, /* R450 */
558 { 0x0000, 0x0000, 0x0000 }, /* R451 */ 556 { 0x0000, 0x0000 }, /* R451 */
559 { 0x0000, 0x0000, 0x0000 }, /* R452 */ 557 { 0x0000, 0x0000 }, /* R452 */
560 { 0x0000, 0x0000, 0x0000 }, /* R453 */ 558 { 0x0000, 0x0000 }, /* R453 */
561 { 0x0000, 0x0000, 0x0000 }, /* R454 */ 559 { 0x0000, 0x0000 }, /* R454 */
562 { 0x0000, 0x0000, 0x0000 }, /* R455 */ 560 { 0x0000, 0x0000 }, /* R455 */
563 { 0x0000, 0x0000, 0x0000 }, /* R456 */ 561 { 0x0000, 0x0000 }, /* R456 */
564 { 0x0000, 0x0000, 0x0000 }, /* R457 */ 562 { 0x0000, 0x0000 }, /* R457 */
565 { 0x0000, 0x0000, 0x0000 }, /* R458 */ 563 { 0x0000, 0x0000 }, /* R458 */
566 { 0x0000, 0x0000, 0x0000 }, /* R459 */ 564 { 0x0000, 0x0000 }, /* R459 */
567 { 0x0000, 0x0000, 0x0000 }, /* R460 */ 565 { 0x0000, 0x0000 }, /* R460 */
568 { 0x0000, 0x0000, 0x0000 }, /* R461 */ 566 { 0x0000, 0x0000 }, /* R461 */
569 { 0x0000, 0x0000, 0x0000 }, /* R462 */ 567 { 0x0000, 0x0000 }, /* R462 */
570 { 0x0000, 0x0000, 0x0000 }, /* R463 */ 568 { 0x0000, 0x0000 }, /* R463 */
571 { 0x0000, 0x0000, 0x0000 }, /* R464 */ 569 { 0x0000, 0x0000 }, /* R464 */
572 { 0x0000, 0x0000, 0x0000 }, /* R465 */ 570 { 0x0000, 0x0000 }, /* R465 */
573 { 0x0000, 0x0000, 0x0000 }, /* R466 */ 571 { 0x0000, 0x0000 }, /* R466 */
574 { 0x0000, 0x0000, 0x0000 }, /* R467 */ 572 { 0x0000, 0x0000 }, /* R467 */
575 { 0x0000, 0x0000, 0x0000 }, /* R468 */ 573 { 0x0000, 0x0000 }, /* R468 */
576 { 0x0000, 0x0000, 0x0000 }, /* R469 */ 574 { 0x0000, 0x0000 }, /* R469 */
577 { 0x0000, 0x0000, 0x0000 }, /* R470 */ 575 { 0x0000, 0x0000 }, /* R470 */
578 { 0x0000, 0x0000, 0x0000 }, /* R471 */ 576 { 0x0000, 0x0000 }, /* R471 */
579 { 0x0000, 0x0000, 0x0000 }, /* R472 */ 577 { 0x0000, 0x0000 }, /* R472 */
580 { 0x0000, 0x0000, 0x0000 }, /* R473 */ 578 { 0x0000, 0x0000 }, /* R473 */
581 { 0x0000, 0x0000, 0x0000 }, /* R474 */ 579 { 0x0000, 0x0000 }, /* R474 */
582 { 0x0000, 0x0000, 0x0000 }, /* R475 */ 580 { 0x0000, 0x0000 }, /* R475 */
583 { 0x0000, 0x0000, 0x0000 }, /* R476 */ 581 { 0x0000, 0x0000 }, /* R476 */
584 { 0x0000, 0x0000, 0x0000 }, /* R477 */ 582 { 0x0000, 0x0000 }, /* R477 */
585 { 0x0000, 0x0000, 0x0000 }, /* R478 */ 583 { 0x0000, 0x0000 }, /* R478 */
586 { 0x0000, 0x0000, 0x0000 }, /* R479 */ 584 { 0x0000, 0x0000 }, /* R479 */
587 { 0x0000, 0x0000, 0x0000 }, /* R480 */ 585 { 0x0000, 0x0000 }, /* R480 */
588 { 0x0000, 0x0000, 0x0000 }, /* R481 */ 586 { 0x0000, 0x0000 }, /* R481 */
589 { 0x0000, 0x0000, 0x0000 }, /* R482 */ 587 { 0x0000, 0x0000 }, /* R482 */
590 { 0x0000, 0x0000, 0x0000 }, /* R483 */ 588 { 0x0000, 0x0000 }, /* R483 */
591 { 0x0000, 0x0000, 0x0000 }, /* R484 */ 589 { 0x0000, 0x0000 }, /* R484 */
592 { 0x0000, 0x0000, 0x0000 }, /* R485 */ 590 { 0x0000, 0x0000 }, /* R485 */
593 { 0x0000, 0x0000, 0x0000 }, /* R486 */ 591 { 0x0000, 0x0000 }, /* R486 */
594 { 0x0000, 0x0000, 0x0000 }, /* R487 */ 592 { 0x0000, 0x0000 }, /* R487 */
595 { 0x0000, 0x0000, 0x0000 }, /* R488 */ 593 { 0x0000, 0x0000 }, /* R488 */
596 { 0x0000, 0x0000, 0x0000 }, /* R489 */ 594 { 0x0000, 0x0000 }, /* R489 */
597 { 0x0000, 0x0000, 0x0000 }, /* R490 */ 595 { 0x0000, 0x0000 }, /* R490 */
598 { 0x0000, 0x0000, 0x0000 }, /* R491 */ 596 { 0x0000, 0x0000 }, /* R491 */
599 { 0x0000, 0x0000, 0x0000 }, /* R492 */ 597 { 0x0000, 0x0000 }, /* R492 */
600 { 0x0000, 0x0000, 0x0000 }, /* R493 */ 598 { 0x0000, 0x0000 }, /* R493 */
601 { 0x0000, 0x0000, 0x0000 }, /* R494 */ 599 { 0x0000, 0x0000 }, /* R494 */
602 { 0x0000, 0x0000, 0x0000 }, /* R495 */ 600 { 0x0000, 0x0000 }, /* R495 */
603 { 0x0000, 0x0000, 0x0000 }, /* R496 */ 601 { 0x0000, 0x0000 }, /* R496 */
604 { 0x0000, 0x0000, 0x0000 }, /* R497 */ 602 { 0x0000, 0x0000 }, /* R497 */
605 { 0x0000, 0x0000, 0x0000 }, /* R498 */ 603 { 0x0000, 0x0000 }, /* R498 */
606 { 0x0000, 0x0000, 0x0000 }, /* R499 */ 604 { 0x0000, 0x0000 }, /* R499 */
607 { 0x0000, 0x0000, 0x0000 }, /* R500 */ 605 { 0x0000, 0x0000 }, /* R500 */
608 { 0x0000, 0x0000, 0x0000 }, /* R501 */ 606 { 0x0000, 0x0000 }, /* R501 */
609 { 0x0000, 0x0000, 0x0000 }, /* R502 */ 607 { 0x0000, 0x0000 }, /* R502 */
610 { 0x0000, 0x0000, 0x0000 }, /* R503 */ 608 { 0x0000, 0x0000 }, /* R503 */
611 { 0x0000, 0x0000, 0x0000 }, /* R504 */ 609 { 0x0000, 0x0000 }, /* R504 */
612 { 0x0000, 0x0000, 0x0000 }, /* R505 */ 610 { 0x0000, 0x0000 }, /* R505 */
613 { 0x0000, 0x0000, 0x0000 }, /* R506 */ 611 { 0x0000, 0x0000 }, /* R506 */
614 { 0x0000, 0x0000, 0x0000 }, /* R507 */ 612 { 0x0000, 0x0000 }, /* R507 */
615 { 0x0000, 0x0000, 0x0000 }, /* R508 */ 613 { 0x0000, 0x0000 }, /* R508 */
616 { 0x0000, 0x0000, 0x0000 }, /* R509 */ 614 { 0x0000, 0x0000 }, /* R509 */
617 { 0x0000, 0x0000, 0x0000 }, /* R510 */ 615 { 0x0000, 0x0000 }, /* R510 */
618 { 0x0000, 0x0000, 0x0000 }, /* R511 */ 616 { 0x0000, 0x0000 }, /* R511 */
619 { 0x001F, 0x001F, 0x0000 }, /* R512 - AIF1 Clocking (1) */ 617 { 0x001F, 0x001F }, /* R512 - AIF1 Clocking (1) */
620 { 0x003F, 0x003F, 0x0000 }, /* R513 - AIF1 Clocking (2) */ 618 { 0x003F, 0x003F }, /* R513 - AIF1 Clocking (2) */
621 { 0x0000, 0x0000, 0x0000 }, /* R514 */ 619 { 0x0000, 0x0000 }, /* R514 */
622 { 0x0000, 0x0000, 0x0000 }, /* R515 */ 620 { 0x0000, 0x0000 }, /* R515 */
623 { 0x001F, 0x001F, 0x0000 }, /* R516 - AIF2 Clocking (1) */ 621 { 0x001F, 0x001F }, /* R516 - AIF2 Clocking (1) */
624 { 0x003F, 0x003F, 0x0000 }, /* R517 - AIF2 Clocking (2) */ 622 { 0x003F, 0x003F }, /* R517 - AIF2 Clocking (2) */
625 { 0x0000, 0x0000, 0x0000 }, /* R518 */ 623 { 0x0000, 0x0000 }, /* R518 */
626 { 0x0000, 0x0000, 0x0000 }, /* R519 */ 624 { 0x0000, 0x0000 }, /* R519 */
627 { 0x001F, 0x001F, 0x0000 }, /* R520 - Clocking (1) */ 625 { 0x001F, 0x001F }, /* R520 - Clocking (1) */
628 { 0x0777, 0x0777, 0x0000 }, /* R521 - Clocking (2) */ 626 { 0x0777, 0x0777 }, /* R521 - Clocking (2) */
629 { 0x0000, 0x0000, 0x0000 }, /* R522 */ 627 { 0x0000, 0x0000 }, /* R522 */
630 { 0x0000, 0x0000, 0x0000 }, /* R523 */ 628 { 0x0000, 0x0000 }, /* R523 */
631 { 0x0000, 0x0000, 0x0000 }, /* R524 */ 629 { 0x0000, 0x0000 }, /* R524 */
632 { 0x0000, 0x0000, 0x0000 }, /* R525 */ 630 { 0x0000, 0x0000 }, /* R525 */
633 { 0x0000, 0x0000, 0x0000 }, /* R526 */ 631 { 0x0000, 0x0000 }, /* R526 */
634 { 0x0000, 0x0000, 0x0000 }, /* R527 */ 632 { 0x0000, 0x0000 }, /* R527 */
635 { 0x00FF, 0x00FF, 0x0000 }, /* R528 - AIF1 Rate */ 633 { 0x00FF, 0x00FF }, /* R528 - AIF1 Rate */
636 { 0x00FF, 0x00FF, 0x0000 }, /* R529 - AIF2 Rate */ 634 { 0x00FF, 0x00FF }, /* R529 - AIF2 Rate */
637 { 0x000F, 0x0000, 0x0000 }, /* R530 - Rate Status */ 635 { 0x000F, 0x0000 }, /* R530 - Rate Status */
638 { 0x0000, 0x0000, 0x0000 }, /* R531 */ 636 { 0x0000, 0x0000 }, /* R531 */
639 { 0x0000, 0x0000, 0x0000 }, /* R532 */ 637 { 0x0000, 0x0000 }, /* R532 */
640 { 0x0000, 0x0000, 0x0000 }, /* R533 */ 638 { 0x0000, 0x0000 }, /* R533 */
641 { 0x0000, 0x0000, 0x0000 }, /* R534 */ 639 { 0x0000, 0x0000 }, /* R534 */
642 { 0x0000, 0x0000, 0x0000 }, /* R535 */ 640 { 0x0000, 0x0000 }, /* R535 */
643 { 0x0000, 0x0000, 0x0000 }, /* R536 */ 641 { 0x0000, 0x0000 }, /* R536 */
644 { 0x0000, 0x0000, 0x0000 }, /* R537 */ 642 { 0x0000, 0x0000 }, /* R537 */
645 { 0x0000, 0x0000, 0x0000 }, /* R538 */ 643 { 0x0000, 0x0000 }, /* R538 */
646 { 0x0000, 0x0000, 0x0000 }, /* R539 */ 644 { 0x0000, 0x0000 }, /* R539 */
647 { 0x0000, 0x0000, 0x0000 }, /* R540 */ 645 { 0x0000, 0x0000 }, /* R540 */
648 { 0x0000, 0x0000, 0x0000 }, /* R541 */ 646 { 0x0000, 0x0000 }, /* R541 */
649 { 0x0000, 0x0000, 0x0000 }, /* R542 */ 647 { 0x0000, 0x0000 }, /* R542 */
650 { 0x0000, 0x0000, 0x0000 }, /* R543 */ 648 { 0x0000, 0x0000 }, /* R543 */
651 { 0x0007, 0x0007, 0x0000 }, /* R544 - FLL1 Control (1) */ 649 { 0x0007, 0x0007 }, /* R544 - FLL1 Control (1) */
652 { 0x3F77, 0x3F77, 0x0000 }, /* R545 - FLL1 Control (2) */ 650 { 0x3F77, 0x3F77 }, /* R545 - FLL1 Control (2) */
653 { 0xFFFF, 0xFFFF, 0x0000 }, /* R546 - FLL1 Control (3) */ 651 { 0xFFFF, 0xFFFF }, /* R546 - FLL1 Control (3) */
654 { 0x7FEF, 0x7FEF, 0x0000 }, /* R547 - FLL1 Control (4) */ 652 { 0x7FEF, 0x7FEF }, /* R547 - FLL1 Control (4) */
655 { 0x1FDB, 0x1FDB, 0x0000 }, /* R548 - FLL1 Control (5) */ 653 { 0x1FDB, 0x1FDB }, /* R548 - FLL1 Control (5) */
656 { 0x0000, 0x0000, 0x0000 }, /* R549 */ 654 { 0x0000, 0x0000 }, /* R549 */
657 { 0x0000, 0x0000, 0x0000 }, /* R550 */ 655 { 0x0000, 0x0000 }, /* R550 */
658 { 0x0000, 0x0000, 0x0000 }, /* R551 */ 656 { 0x0000, 0x0000 }, /* R551 */
659 { 0x0000, 0x0000, 0x0000 }, /* R552 */ 657 { 0x0000, 0x0000 }, /* R552 */
660 { 0x0000, 0x0000, 0x0000 }, /* R553 */ 658 { 0x0000, 0x0000 }, /* R553 */
661 { 0x0000, 0x0000, 0x0000 }, /* R554 */ 659 { 0x0000, 0x0000 }, /* R554 */
662 { 0x0000, 0x0000, 0x0000 }, /* R555 */ 660 { 0x0000, 0x0000 }, /* R555 */
663 { 0x0000, 0x0000, 0x0000 }, /* R556 */ 661 { 0x0000, 0x0000 }, /* R556 */
664 { 0x0000, 0x0000, 0x0000 }, /* R557 */ 662 { 0x0000, 0x0000 }, /* R557 */
665 { 0x0000, 0x0000, 0x0000 }, /* R558 */ 663 { 0x0000, 0x0000 }, /* R558 */
666 { 0x0000, 0x0000, 0x0000 }, /* R559 */ 664 { 0x0000, 0x0000 }, /* R559 */
667 { 0x0000, 0x0000, 0x0000 }, /* R560 */ 665 { 0x0000, 0x0000 }, /* R560 */
668 { 0x0000, 0x0000, 0x0000 }, /* R561 */ 666 { 0x0000, 0x0000 }, /* R561 */
669 { 0x0000, 0x0000, 0x0000 }, /* R562 */ 667 { 0x0000, 0x0000 }, /* R562 */
670 { 0x0000, 0x0000, 0x0000 }, /* R563 */ 668 { 0x0000, 0x0000 }, /* R563 */
671 { 0x0000, 0x0000, 0x0000 }, /* R564 */ 669 { 0x0000, 0x0000 }, /* R564 */
672 { 0x0000, 0x0000, 0x0000 }, /* R565 */ 670 { 0x0000, 0x0000 }, /* R565 */
673 { 0x0000, 0x0000, 0x0000 }, /* R566 */ 671 { 0x0000, 0x0000 }, /* R566 */
674 { 0x0000, 0x0000, 0x0000 }, /* R567 */ 672 { 0x0000, 0x0000 }, /* R567 */
675 { 0x0000, 0x0000, 0x0000 }, /* R568 */ 673 { 0x0000, 0x0000 }, /* R568 */
676 { 0x0000, 0x0000, 0x0000 }, /* R569 */ 674 { 0x0000, 0x0000 }, /* R569 */
677 { 0x0000, 0x0000, 0x0000 }, /* R570 */ 675 { 0x0000, 0x0000 }, /* R570 */
678 { 0x0000, 0x0000, 0x0000 }, /* R571 */ 676 { 0x0000, 0x0000 }, /* R571 */
679 { 0x0000, 0x0000, 0x0000 }, /* R572 */ 677 { 0x0000, 0x0000 }, /* R572 */
680 { 0x0000, 0x0000, 0x0000 }, /* R573 */ 678 { 0x0000, 0x0000 }, /* R573 */
681 { 0x0000, 0x0000, 0x0000 }, /* R574 */ 679 { 0x0000, 0x0000 }, /* R574 */
682 { 0x0000, 0x0000, 0x0000 }, /* R575 */ 680 { 0x0000, 0x0000 }, /* R575 */
683 { 0x0007, 0x0007, 0x0000 }, /* R576 - FLL2 Control (1) */ 681 { 0x0007, 0x0007 }, /* R576 - FLL2 Control (1) */
684 { 0x3F77, 0x3F77, 0x0000 }, /* R577 - FLL2 Control (2) */ 682 { 0x3F77, 0x3F77 }, /* R577 - FLL2 Control (2) */
685 { 0xFFFF, 0xFFFF, 0x0000 }, /* R578 - FLL2 Control (3) */ 683 { 0xFFFF, 0xFFFF }, /* R578 - FLL2 Control (3) */
686 { 0x7FEF, 0x7FEF, 0x0000 }, /* R579 - FLL2 Control (4) */ 684 { 0x7FEF, 0x7FEF }, /* R579 - FLL2 Control (4) */
687 { 0x1FDB, 0x1FDB, 0x0000 }, /* R580 - FLL2 Control (5) */ 685 { 0x1FDB, 0x1FDB }, /* R580 - FLL2 Control (5) */
688 { 0x0000, 0x0000, 0x0000 }, /* R581 */ 686 { 0x0000, 0x0000 }, /* R581 */
689 { 0x0000, 0x0000, 0x0000 }, /* R582 */ 687 { 0x0000, 0x0000 }, /* R582 */
690 { 0x0000, 0x0000, 0x0000 }, /* R583 */ 688 { 0x0000, 0x0000 }, /* R583 */
691 { 0x0000, 0x0000, 0x0000 }, /* R584 */ 689 { 0x0000, 0x0000 }, /* R584 */
692 { 0x0000, 0x0000, 0x0000 }, /* R585 */ 690 { 0x0000, 0x0000 }, /* R585 */
693 { 0x0000, 0x0000, 0x0000 }, /* R586 */ 691 { 0x0000, 0x0000 }, /* R586 */
694 { 0x0000, 0x0000, 0x0000 }, /* R587 */ 692 { 0x0000, 0x0000 }, /* R587 */
695 { 0x0000, 0x0000, 0x0000 }, /* R588 */ 693 { 0x0000, 0x0000 }, /* R588 */
696 { 0x0000, 0x0000, 0x0000 }, /* R589 */ 694 { 0x0000, 0x0000 }, /* R589 */
697 { 0x0000, 0x0000, 0x0000 }, /* R590 */ 695 { 0x0000, 0x0000 }, /* R590 */
698 { 0x0000, 0x0000, 0x0000 }, /* R591 */ 696 { 0x0000, 0x0000 }, /* R591 */
699 { 0x0000, 0x0000, 0x0000 }, /* R592 */ 697 { 0x0000, 0x0000 }, /* R592 */
700 { 0x0000, 0x0000, 0x0000 }, /* R593 */ 698 { 0x0000, 0x0000 }, /* R593 */
701 { 0x0000, 0x0000, 0x0000 }, /* R594 */ 699 { 0x0000, 0x0000 }, /* R594 */
702 { 0x0000, 0x0000, 0x0000 }, /* R595 */ 700 { 0x0000, 0x0000 }, /* R595 */
703 { 0x0000, 0x0000, 0x0000 }, /* R596 */ 701 { 0x0000, 0x0000 }, /* R596 */
704 { 0x0000, 0x0000, 0x0000 }, /* R597 */ 702 { 0x0000, 0x0000 }, /* R597 */
705 { 0x0000, 0x0000, 0x0000 }, /* R598 */ 703 { 0x0000, 0x0000 }, /* R598 */
706 { 0x0000, 0x0000, 0x0000 }, /* R599 */ 704 { 0x0000, 0x0000 }, /* R599 */
707 { 0x0000, 0x0000, 0x0000 }, /* R600 */ 705 { 0x0000, 0x0000 }, /* R600 */
708 { 0x0000, 0x0000, 0x0000 }, /* R601 */ 706 { 0x0000, 0x0000 }, /* R601 */
709 { 0x0000, 0x0000, 0x0000 }, /* R602 */ 707 { 0x0000, 0x0000 }, /* R602 */
710 { 0x0000, 0x0000, 0x0000 }, /* R603 */ 708 { 0x0000, 0x0000 }, /* R603 */
711 { 0x0000, 0x0000, 0x0000 }, /* R604 */ 709 { 0x0000, 0x0000 }, /* R604 */
712 { 0x0000, 0x0000, 0x0000 }, /* R605 */ 710 { 0x0000, 0x0000 }, /* R605 */
713 { 0x0000, 0x0000, 0x0000 }, /* R606 */ 711 { 0x0000, 0x0000 }, /* R606 */
714 { 0x0000, 0x0000, 0x0000 }, /* R607 */ 712 { 0x0000, 0x0000 }, /* R607 */
715 { 0x0000, 0x0000, 0x0000 }, /* R608 */ 713 { 0x0000, 0x0000 }, /* R608 */
716 { 0x0000, 0x0000, 0x0000 }, /* R609 */ 714 { 0x0000, 0x0000 }, /* R609 */
717 { 0x0000, 0x0000, 0x0000 }, /* R610 */ 715 { 0x0000, 0x0000 }, /* R610 */
718 { 0x0000, 0x0000, 0x0000 }, /* R611 */ 716 { 0x0000, 0x0000 }, /* R611 */
719 { 0x0000, 0x0000, 0x0000 }, /* R612 */ 717 { 0x0000, 0x0000 }, /* R612 */
720 { 0x0000, 0x0000, 0x0000 }, /* R613 */ 718 { 0x0000, 0x0000 }, /* R613 */
721 { 0x0000, 0x0000, 0x0000 }, /* R614 */ 719 { 0x0000, 0x0000 }, /* R614 */
722 { 0x0000, 0x0000, 0x0000 }, /* R615 */ 720 { 0x0000, 0x0000 }, /* R615 */
723 { 0x0000, 0x0000, 0x0000 }, /* R616 */ 721 { 0x0000, 0x0000 }, /* R616 */
724 { 0x0000, 0x0000, 0x0000 }, /* R617 */ 722 { 0x0000, 0x0000 }, /* R617 */
725 { 0x0000, 0x0000, 0x0000 }, /* R618 */ 723 { 0x0000, 0x0000 }, /* R618 */
726 { 0x0000, 0x0000, 0x0000 }, /* R619 */ 724 { 0x0000, 0x0000 }, /* R619 */
727 { 0x0000, 0x0000, 0x0000 }, /* R620 */ 725 { 0x0000, 0x0000 }, /* R620 */
728 { 0x0000, 0x0000, 0x0000 }, /* R621 */ 726 { 0x0000, 0x0000 }, /* R621 */
729 { 0x0000, 0x0000, 0x0000 }, /* R622 */ 727 { 0x0000, 0x0000 }, /* R622 */
730 { 0x0000, 0x0000, 0x0000 }, /* R623 */ 728 { 0x0000, 0x0000 }, /* R623 */
731 { 0x0000, 0x0000, 0x0000 }, /* R624 */ 729 { 0x0000, 0x0000 }, /* R624 */
732 { 0x0000, 0x0000, 0x0000 }, /* R625 */ 730 { 0x0000, 0x0000 }, /* R625 */
733 { 0x0000, 0x0000, 0x0000 }, /* R626 */ 731 { 0x0000, 0x0000 }, /* R626 */
734 { 0x0000, 0x0000, 0x0000 }, /* R627 */ 732 { 0x0000, 0x0000 }, /* R627 */
735 { 0x0000, 0x0000, 0x0000 }, /* R628 */ 733 { 0x0000, 0x0000 }, /* R628 */
736 { 0x0000, 0x0000, 0x0000 }, /* R629 */ 734 { 0x0000, 0x0000 }, /* R629 */
737 { 0x0000, 0x0000, 0x0000 }, /* R630 */ 735 { 0x0000, 0x0000 }, /* R630 */
738 { 0x0000, 0x0000, 0x0000 }, /* R631 */ 736 { 0x0000, 0x0000 }, /* R631 */
739 { 0x0000, 0x0000, 0x0000 }, /* R632 */ 737 { 0x0000, 0x0000 }, /* R632 */
740 { 0x0000, 0x0000, 0x0000 }, /* R633 */ 738 { 0x0000, 0x0000 }, /* R633 */
741 { 0x0000, 0x0000, 0x0000 }, /* R634 */ 739 { 0x0000, 0x0000 }, /* R634 */
742 { 0x0000, 0x0000, 0x0000 }, /* R635 */ 740 { 0x0000, 0x0000 }, /* R635 */
743 { 0x0000, 0x0000, 0x0000 }, /* R636 */ 741 { 0x0000, 0x0000 }, /* R636 */
744 { 0x0000, 0x0000, 0x0000 }, /* R637 */ 742 { 0x0000, 0x0000 }, /* R637 */
745 { 0x0000, 0x0000, 0x0000 }, /* R638 */ 743 { 0x0000, 0x0000 }, /* R638 */
746 { 0x0000, 0x0000, 0x0000 }, /* R639 */ 744 { 0x0000, 0x0000 }, /* R639 */
747 { 0x0000, 0x0000, 0x0000 }, /* R640 */ 745 { 0x0000, 0x0000 }, /* R640 */
748 { 0x0000, 0x0000, 0x0000 }, /* R641 */ 746 { 0x0000, 0x0000 }, /* R641 */
749 { 0x0000, 0x0000, 0x0000 }, /* R642 */ 747 { 0x0000, 0x0000 }, /* R642 */
750 { 0x0000, 0x0000, 0x0000 }, /* R643 */ 748 { 0x0000, 0x0000 }, /* R643 */
751 { 0x0000, 0x0000, 0x0000 }, /* R644 */ 749 { 0x0000, 0x0000 }, /* R644 */
752 { 0x0000, 0x0000, 0x0000 }, /* R645 */ 750 { 0x0000, 0x0000 }, /* R645 */
753 { 0x0000, 0x0000, 0x0000 }, /* R646 */ 751 { 0x0000, 0x0000 }, /* R646 */
754 { 0x0000, 0x0000, 0x0000 }, /* R647 */ 752 { 0x0000, 0x0000 }, /* R647 */
755 { 0x0000, 0x0000, 0x0000 }, /* R648 */ 753 { 0x0000, 0x0000 }, /* R648 */
756 { 0x0000, 0x0000, 0x0000 }, /* R649 */ 754 { 0x0000, 0x0000 }, /* R649 */
757 { 0x0000, 0x0000, 0x0000 }, /* R650 */ 755 { 0x0000, 0x0000 }, /* R650 */
758 { 0x0000, 0x0000, 0x0000 }, /* R651 */ 756 { 0x0000, 0x0000 }, /* R651 */
759 { 0x0000, 0x0000, 0x0000 }, /* R652 */ 757 { 0x0000, 0x0000 }, /* R652 */
760 { 0x0000, 0x0000, 0x0000 }, /* R653 */ 758 { 0x0000, 0x0000 }, /* R653 */
761 { 0x0000, 0x0000, 0x0000 }, /* R654 */ 759 { 0x0000, 0x0000 }, /* R654 */
762 { 0x0000, 0x0000, 0x0000 }, /* R655 */ 760 { 0x0000, 0x0000 }, /* R655 */
763 { 0x0000, 0x0000, 0x0000 }, /* R656 */ 761 { 0x0000, 0x0000 }, /* R656 */
764 { 0x0000, 0x0000, 0x0000 }, /* R657 */ 762 { 0x0000, 0x0000 }, /* R657 */
765 { 0x0000, 0x0000, 0x0000 }, /* R658 */ 763 { 0x0000, 0x0000 }, /* R658 */
766 { 0x0000, 0x0000, 0x0000 }, /* R659 */ 764 { 0x0000, 0x0000 }, /* R659 */
767 { 0x0000, 0x0000, 0x0000 }, /* R660 */ 765 { 0x0000, 0x0000 }, /* R660 */
768 { 0x0000, 0x0000, 0x0000 }, /* R661 */ 766 { 0x0000, 0x0000 }, /* R661 */
769 { 0x0000, 0x0000, 0x0000 }, /* R662 */ 767 { 0x0000, 0x0000 }, /* R662 */
770 { 0x0000, 0x0000, 0x0000 }, /* R663 */ 768 { 0x0000, 0x0000 }, /* R663 */
771 { 0x0000, 0x0000, 0x0000 }, /* R664 */ 769 { 0x0000, 0x0000 }, /* R664 */
772 { 0x0000, 0x0000, 0x0000 }, /* R665 */ 770 { 0x0000, 0x0000 }, /* R665 */
773 { 0x0000, 0x0000, 0x0000 }, /* R666 */ 771 { 0x0000, 0x0000 }, /* R666 */
774 { 0x0000, 0x0000, 0x0000 }, /* R667 */ 772 { 0x0000, 0x0000 }, /* R667 */
775 { 0x0000, 0x0000, 0x0000 }, /* R668 */ 773 { 0x0000, 0x0000 }, /* R668 */
776 { 0x0000, 0x0000, 0x0000 }, /* R669 */ 774 { 0x0000, 0x0000 }, /* R669 */
777 { 0x0000, 0x0000, 0x0000 }, /* R670 */ 775 { 0x0000, 0x0000 }, /* R670 */
778 { 0x0000, 0x0000, 0x0000 }, /* R671 */ 776 { 0x0000, 0x0000 }, /* R671 */
779 { 0x0000, 0x0000, 0x0000 }, /* R672 */ 777 { 0x0000, 0x0000 }, /* R672 */
780 { 0x0000, 0x0000, 0x0000 }, /* R673 */ 778 { 0x0000, 0x0000 }, /* R673 */
781 { 0x0000, 0x0000, 0x0000 }, /* R674 */ 779 { 0x0000, 0x0000 }, /* R674 */
782 { 0x0000, 0x0000, 0x0000 }, /* R675 */ 780 { 0x0000, 0x0000 }, /* R675 */
783 { 0x0000, 0x0000, 0x0000 }, /* R676 */ 781 { 0x0000, 0x0000 }, /* R676 */
784 { 0x0000, 0x0000, 0x0000 }, /* R677 */ 782 { 0x0000, 0x0000 }, /* R677 */
785 { 0x0000, 0x0000, 0x0000 }, /* R678 */ 783 { 0x0000, 0x0000 }, /* R678 */
786 { 0x0000, 0x0000, 0x0000 }, /* R679 */ 784 { 0x0000, 0x0000 }, /* R679 */
787 { 0x0000, 0x0000, 0x0000 }, /* R680 */ 785 { 0x0000, 0x0000 }, /* R680 */
788 { 0x0000, 0x0000, 0x0000 }, /* R681 */ 786 { 0x0000, 0x0000 }, /* R681 */
789 { 0x0000, 0x0000, 0x0000 }, /* R682 */ 787 { 0x0000, 0x0000 }, /* R682 */
790 { 0x0000, 0x0000, 0x0000 }, /* R683 */ 788 { 0x0000, 0x0000 }, /* R683 */
791 { 0x0000, 0x0000, 0x0000 }, /* R684 */ 789 { 0x0000, 0x0000 }, /* R684 */
792 { 0x0000, 0x0000, 0x0000 }, /* R685 */ 790 { 0x0000, 0x0000 }, /* R685 */
793 { 0x0000, 0x0000, 0x0000 }, /* R686 */ 791 { 0x0000, 0x0000 }, /* R686 */
794 { 0x0000, 0x0000, 0x0000 }, /* R687 */ 792 { 0x0000, 0x0000 }, /* R687 */
795 { 0x0000, 0x0000, 0x0000 }, /* R688 */ 793 { 0x0000, 0x0000 }, /* R688 */
796 { 0x0000, 0x0000, 0x0000 }, /* R689 */ 794 { 0x0000, 0x0000 }, /* R689 */
797 { 0x0000, 0x0000, 0x0000 }, /* R690 */ 795 { 0x0000, 0x0000 }, /* R690 */
798 { 0x0000, 0x0000, 0x0000 }, /* R691 */ 796 { 0x0000, 0x0000 }, /* R691 */
799 { 0x0000, 0x0000, 0x0000 }, /* R692 */ 797 { 0x0000, 0x0000 }, /* R692 */
800 { 0x0000, 0x0000, 0x0000 }, /* R693 */ 798 { 0x0000, 0x0000 }, /* R693 */
801 { 0x0000, 0x0000, 0x0000 }, /* R694 */ 799 { 0x0000, 0x0000 }, /* R694 */
802 { 0x0000, 0x0000, 0x0000 }, /* R695 */ 800 { 0x0000, 0x0000 }, /* R695 */
803 { 0x0000, 0x0000, 0x0000 }, /* R696 */ 801 { 0x0000, 0x0000 }, /* R696 */
804 { 0x0000, 0x0000, 0x0000 }, /* R697 */ 802 { 0x0000, 0x0000 }, /* R697 */
805 { 0x0000, 0x0000, 0x0000 }, /* R698 */ 803 { 0x0000, 0x0000 }, /* R698 */
806 { 0x0000, 0x0000, 0x0000 }, /* R699 */ 804 { 0x0000, 0x0000 }, /* R699 */
807 { 0x0000, 0x0000, 0x0000 }, /* R700 */ 805 { 0x0000, 0x0000 }, /* R700 */
808 { 0x0000, 0x0000, 0x0000 }, /* R701 */ 806 { 0x0000, 0x0000 }, /* R701 */
809 { 0x0000, 0x0000, 0x0000 }, /* R702 */ 807 { 0x0000, 0x0000 }, /* R702 */
810 { 0x0000, 0x0000, 0x0000 }, /* R703 */ 808 { 0x0000, 0x0000 }, /* R703 */
811 { 0x0000, 0x0000, 0x0000 }, /* R704 */ 809 { 0x0000, 0x0000 }, /* R704 */
812 { 0x0000, 0x0000, 0x0000 }, /* R705 */ 810 { 0x0000, 0x0000 }, /* R705 */
813 { 0x0000, 0x0000, 0x0000 }, /* R706 */ 811 { 0x0000, 0x0000 }, /* R706 */
814 { 0x0000, 0x0000, 0x0000 }, /* R707 */ 812 { 0x0000, 0x0000 }, /* R707 */
815 { 0x0000, 0x0000, 0x0000 }, /* R708 */ 813 { 0x0000, 0x0000 }, /* R708 */
816 { 0x0000, 0x0000, 0x0000 }, /* R709 */ 814 { 0x0000, 0x0000 }, /* R709 */
817 { 0x0000, 0x0000, 0x0000 }, /* R710 */ 815 { 0x0000, 0x0000 }, /* R710 */
818 { 0x0000, 0x0000, 0x0000 }, /* R711 */ 816 { 0x0000, 0x0000 }, /* R711 */
819 { 0x0000, 0x0000, 0x0000 }, /* R712 */ 817 { 0x0000, 0x0000 }, /* R712 */
820 { 0x0000, 0x0000, 0x0000 }, /* R713 */ 818 { 0x0000, 0x0000 }, /* R713 */
821 { 0x0000, 0x0000, 0x0000 }, /* R714 */ 819 { 0x0000, 0x0000 }, /* R714 */
822 { 0x0000, 0x0000, 0x0000 }, /* R715 */ 820 { 0x0000, 0x0000 }, /* R715 */
823 { 0x0000, 0x0000, 0x0000 }, /* R716 */ 821 { 0x0000, 0x0000 }, /* R716 */
824 { 0x0000, 0x0000, 0x0000 }, /* R717 */ 822 { 0x0000, 0x0000 }, /* R717 */
825 { 0x0000, 0x0000, 0x0000 }, /* R718 */ 823 { 0x0000, 0x0000 }, /* R718 */
826 { 0x0000, 0x0000, 0x0000 }, /* R719 */ 824 { 0x0000, 0x0000 }, /* R719 */
827 { 0x0000, 0x0000, 0x0000 }, /* R720 */ 825 { 0x0000, 0x0000 }, /* R720 */
828 { 0x0000, 0x0000, 0x0000 }, /* R721 */ 826 { 0x0000, 0x0000 }, /* R721 */
829 { 0x0000, 0x0000, 0x0000 }, /* R722 */ 827 { 0x0000, 0x0000 }, /* R722 */
830 { 0x0000, 0x0000, 0x0000 }, /* R723 */ 828 { 0x0000, 0x0000 }, /* R723 */
831 { 0x0000, 0x0000, 0x0000 }, /* R724 */ 829 { 0x0000, 0x0000 }, /* R724 */
832 { 0x0000, 0x0000, 0x0000 }, /* R725 */ 830 { 0x0000, 0x0000 }, /* R725 */
833 { 0x0000, 0x0000, 0x0000 }, /* R726 */ 831 { 0x0000, 0x0000 }, /* R726 */
834 { 0x0000, 0x0000, 0x0000 }, /* R727 */ 832 { 0x0000, 0x0000 }, /* R727 */
835 { 0x0000, 0x0000, 0x0000 }, /* R728 */ 833 { 0x0000, 0x0000 }, /* R728 */
836 { 0x0000, 0x0000, 0x0000 }, /* R729 */ 834 { 0x0000, 0x0000 }, /* R729 */
837 { 0x0000, 0x0000, 0x0000 }, /* R730 */ 835 { 0x0000, 0x0000 }, /* R730 */
838 { 0x0000, 0x0000, 0x0000 }, /* R731 */ 836 { 0x0000, 0x0000 }, /* R731 */
839 { 0x0000, 0x0000, 0x0000 }, /* R732 */ 837 { 0x0000, 0x0000 }, /* R732 */
840 { 0x0000, 0x0000, 0x0000 }, /* R733 */ 838 { 0x0000, 0x0000 }, /* R733 */
841 { 0x0000, 0x0000, 0x0000 }, /* R734 */ 839 { 0x0000, 0x0000 }, /* R734 */
842 { 0x0000, 0x0000, 0x0000 }, /* R735 */ 840 { 0x0000, 0x0000 }, /* R735 */
843 { 0x0000, 0x0000, 0x0000 }, /* R736 */ 841 { 0x0000, 0x0000 }, /* R736 */
844 { 0x0000, 0x0000, 0x0000 }, /* R737 */ 842 { 0x0000, 0x0000 }, /* R737 */
845 { 0x0000, 0x0000, 0x0000 }, /* R738 */ 843 { 0x0000, 0x0000 }, /* R738 */
846 { 0x0000, 0x0000, 0x0000 }, /* R739 */ 844 { 0x0000, 0x0000 }, /* R739 */
847 { 0x0000, 0x0000, 0x0000 }, /* R740 */ 845 { 0x0000, 0x0000 }, /* R740 */
848 { 0x0000, 0x0000, 0x0000 }, /* R741 */ 846 { 0x0000, 0x0000 }, /* R741 */
849 { 0x0000, 0x0000, 0x0000 }, /* R742 */ 847 { 0x0000, 0x0000 }, /* R742 */
850 { 0x0000, 0x0000, 0x0000 }, /* R743 */ 848 { 0x0000, 0x0000 }, /* R743 */
851 { 0x0000, 0x0000, 0x0000 }, /* R744 */ 849 { 0x0000, 0x0000 }, /* R744 */
852 { 0x0000, 0x0000, 0x0000 }, /* R745 */ 850 { 0x0000, 0x0000 }, /* R745 */
853 { 0x0000, 0x0000, 0x0000 }, /* R746 */ 851 { 0x0000, 0x0000 }, /* R746 */
854 { 0x0000, 0x0000, 0x0000 }, /* R747 */ 852 { 0x0000, 0x0000 }, /* R747 */
855 { 0x0000, 0x0000, 0x0000 }, /* R748 */ 853 { 0x0000, 0x0000 }, /* R748 */
856 { 0x0000, 0x0000, 0x0000 }, /* R749 */ 854 { 0x0000, 0x0000 }, /* R749 */
857 { 0x0000, 0x0000, 0x0000 }, /* R750 */ 855 { 0x0000, 0x0000 }, /* R750 */
858 { 0x0000, 0x0000, 0x0000 }, /* R751 */ 856 { 0x0000, 0x0000 }, /* R751 */
859 { 0x0000, 0x0000, 0x0000 }, /* R752 */ 857 { 0x0000, 0x0000 }, /* R752 */
860 { 0x0000, 0x0000, 0x0000 }, /* R753 */ 858 { 0x0000, 0x0000 }, /* R753 */
861 { 0x0000, 0x0000, 0x0000 }, /* R754 */ 859 { 0x0000, 0x0000 }, /* R754 */
862 { 0x0000, 0x0000, 0x0000 }, /* R755 */ 860 { 0x0000, 0x0000 }, /* R755 */
863 { 0x0000, 0x0000, 0x0000 }, /* R756 */ 861 { 0x0000, 0x0000 }, /* R756 */
864 { 0x0000, 0x0000, 0x0000 }, /* R757 */ 862 { 0x0000, 0x0000 }, /* R757 */
865 { 0x0000, 0x0000, 0x0000 }, /* R758 */ 863 { 0x0000, 0x0000 }, /* R758 */
866 { 0x0000, 0x0000, 0x0000 }, /* R759 */ 864 { 0x0000, 0x0000 }, /* R759 */
867 { 0x0000, 0x0000, 0x0000 }, /* R760 */ 865 { 0x0000, 0x0000 }, /* R760 */
868 { 0x0000, 0x0000, 0x0000 }, /* R761 */ 866 { 0x0000, 0x0000 }, /* R761 */
869 { 0x0000, 0x0000, 0x0000 }, /* R762 */ 867 { 0x0000, 0x0000 }, /* R762 */
870 { 0x0000, 0x0000, 0x0000 }, /* R763 */ 868 { 0x0000, 0x0000 }, /* R763 */
871 { 0x0000, 0x0000, 0x0000 }, /* R764 */ 869 { 0x0000, 0x0000 }, /* R764 */
872 { 0x0000, 0x0000, 0x0000 }, /* R765 */ 870 { 0x0000, 0x0000 }, /* R765 */
873 { 0x0000, 0x0000, 0x0000 }, /* R766 */ 871 { 0x0000, 0x0000 }, /* R766 */
874 { 0x0000, 0x0000, 0x0000 }, /* R767 */ 872 { 0x0000, 0x0000 }, /* R767 */
875 { 0xE1F8, 0xE1F8, 0x0000 }, /* R768 - AIF1 Control (1) */ 873 { 0xE1F8, 0xE1F8 }, /* R768 - AIF1 Control (1) */
876 { 0xCD1F, 0xCD1F, 0x0000 }, /* R769 - AIF1 Control (2) */ 874 { 0xCD1F, 0xCD1F }, /* R769 - AIF1 Control (2) */
877 { 0xF000, 0xF000, 0x0000 }, /* R770 - AIF1 Master/Slave */ 875 { 0xF000, 0xF000 }, /* R770 - AIF1 Master/Slave */
878 { 0x01F0, 0x01F0, 0x0000 }, /* R771 - AIF1 BCLK */ 876 { 0x01F0, 0x01F0 }, /* R771 - AIF1 BCLK */
879 { 0x0FFF, 0x0FFF, 0x0000 }, /* R772 - AIF1ADC LRCLK */ 877 { 0x0FFF, 0x0FFF }, /* R772 - AIF1ADC LRCLK */
880 { 0x0FFF, 0x0FFF, 0x0000 }, /* R773 - AIF1DAC LRCLK */ 878 { 0x0FFF, 0x0FFF }, /* R773 - AIF1DAC LRCLK */
881 { 0x0003, 0x0003, 0x0000 }, /* R774 - AIF1DAC Data */ 879 { 0x0003, 0x0003 }, /* R774 - AIF1DAC Data */
882 { 0x0003, 0x0003, 0x0000 }, /* R775 - AIF1ADC Data */ 880 { 0x0003, 0x0003 }, /* R775 - AIF1ADC Data */
883 { 0x0000, 0x0000, 0x0000 }, /* R776 */ 881 { 0x0000, 0x0000 }, /* R776 */
884 { 0x0000, 0x0000, 0x0000 }, /* R777 */ 882 { 0x0000, 0x0000 }, /* R777 */
885 { 0x0000, 0x0000, 0x0000 }, /* R778 */ 883 { 0x0000, 0x0000 }, /* R778 */
886 { 0x0000, 0x0000, 0x0000 }, /* R779 */ 884 { 0x0000, 0x0000 }, /* R779 */
887 { 0x0000, 0x0000, 0x0000 }, /* R780 */ 885 { 0x0000, 0x0000 }, /* R780 */
888 { 0x0000, 0x0000, 0x0000 }, /* R781 */ 886 { 0x0000, 0x0000 }, /* R781 */
889 { 0x0000, 0x0000, 0x0000 }, /* R782 */ 887 { 0x0000, 0x0000 }, /* R782 */
890 { 0x0000, 0x0000, 0x0000 }, /* R783 */ 888 { 0x0000, 0x0000 }, /* R783 */
891 { 0xF1F8, 0xF1F8, 0x0000 }, /* R784 - AIF2 Control (1) */ 889 { 0xF1F8, 0xF1F8 }, /* R784 - AIF2 Control (1) */
892 { 0xFD1F, 0xFD1F, 0x0000 }, /* R785 - AIF2 Control (2) */ 890 { 0xFD1F, 0xFD1F }, /* R785 - AIF2 Control (2) */
893 { 0xF000, 0xF000, 0x0000 }, /* R786 - AIF2 Master/Slave */ 891 { 0xF000, 0xF000 }, /* R786 - AIF2 Master/Slave */
894 { 0x01F0, 0x01F0, 0x0000 }, /* R787 - AIF2 BCLK */ 892 { 0x01F0, 0x01F0 }, /* R787 - AIF2 BCLK */
895 { 0x0FFF, 0x0FFF, 0x0000 }, /* R788 - AIF2ADC LRCLK */ 893 { 0x0FFF, 0x0FFF }, /* R788 - AIF2ADC LRCLK */
896 { 0x0FFF, 0x0FFF, 0x0000 }, /* R789 - AIF2DAC LRCLK */ 894 { 0x0FFF, 0x0FFF }, /* R789 - AIF2DAC LRCLK */
897 { 0x0003, 0x0003, 0x0000 }, /* R790 - AIF2DAC Data */ 895 { 0x0003, 0x0003 }, /* R790 - AIF2DAC Data */
898 { 0x0003, 0x0003, 0x0000 }, /* R791 - AIF2ADC Data */ 896 { 0x0003, 0x0003 }, /* R791 - AIF2ADC Data */
899 { 0x0000, 0x0000, 0x0000 }, /* R792 */ 897 { 0x0000, 0x0000 }, /* R792 */
900 { 0x0000, 0x0000, 0x0000 }, /* R793 */ 898 { 0x0000, 0x0000 }, /* R793 */
901 { 0x0000, 0x0000, 0x0000 }, /* R794 */ 899 { 0x0000, 0x0000 }, /* R794 */
902 { 0x0000, 0x0000, 0x0000 }, /* R795 */ 900 { 0x0000, 0x0000 }, /* R795 */
903 { 0x0000, 0x0000, 0x0000 }, /* R796 */ 901 { 0x0000, 0x0000 }, /* R796 */
904 { 0x0000, 0x0000, 0x0000 }, /* R797 */ 902 { 0x0000, 0x0000 }, /* R797 */
905 { 0x0000, 0x0000, 0x0000 }, /* R798 */ 903 { 0x0000, 0x0000 }, /* R798 */
906 { 0x0000, 0x0000, 0x0000 }, /* R799 */ 904 { 0x0000, 0x0000 }, /* R799 */
907 { 0x0000, 0x0000, 0x0000 }, /* R800 */ 905 { 0x0000, 0x0000 }, /* R800 */
908 { 0x0000, 0x0000, 0x0000 }, /* R801 */ 906 { 0x0000, 0x0000 }, /* R801 */
909 { 0x0000, 0x0000, 0x0000 }, /* R802 */ 907 { 0x0000, 0x0000 }, /* R802 */
910 { 0x0000, 0x0000, 0x0000 }, /* R803 */ 908 { 0x0000, 0x0000 }, /* R803 */
911 { 0x0000, 0x0000, 0x0000 }, /* R804 */ 909 { 0x0000, 0x0000 }, /* R804 */
912 { 0x0000, 0x0000, 0x0000 }, /* R805 */ 910 { 0x0000, 0x0000 }, /* R805 */
913 { 0x0000, 0x0000, 0x0000 }, /* R806 */ 911 { 0x0000, 0x0000 }, /* R806 */
914 { 0x0000, 0x0000, 0x0000 }, /* R807 */ 912 { 0x0000, 0x0000 }, /* R807 */
915 { 0x0000, 0x0000, 0x0000 }, /* R808 */ 913 { 0x0000, 0x0000 }, /* R808 */
916 { 0x0000, 0x0000, 0x0000 }, /* R809 */ 914 { 0x0000, 0x0000 }, /* R809 */
917 { 0x0000, 0x0000, 0x0000 }, /* R810 */ 915 { 0x0000, 0x0000 }, /* R810 */
918 { 0x0000, 0x0000, 0x0000 }, /* R811 */ 916 { 0x0000, 0x0000 }, /* R811 */
919 { 0x0000, 0x0000, 0x0000 }, /* R812 */ 917 { 0x0000, 0x0000 }, /* R812 */
920 { 0x0000, 0x0000, 0x0000 }, /* R813 */ 918 { 0x0000, 0x0000 }, /* R813 */
921 { 0x0000, 0x0000, 0x0000 }, /* R814 */ 919 { 0x0000, 0x0000 }, /* R814 */
922 { 0x0000, 0x0000, 0x0000 }, /* R815 */ 920 { 0x0000, 0x0000 }, /* R815 */
923 { 0x0000, 0x0000, 0x0000 }, /* R816 */ 921 { 0x0000, 0x0000 }, /* R816 */
924 { 0x0000, 0x0000, 0x0000 }, /* R817 */ 922 { 0x0000, 0x0000 }, /* R817 */
925 { 0x0000, 0x0000, 0x0000 }, /* R818 */ 923 { 0x0000, 0x0000 }, /* R818 */
926 { 0x0000, 0x0000, 0x0000 }, /* R819 */ 924 { 0x0000, 0x0000 }, /* R819 */
927 { 0x0000, 0x0000, 0x0000 }, /* R820 */ 925 { 0x0000, 0x0000 }, /* R820 */
928 { 0x0000, 0x0000, 0x0000 }, /* R821 */ 926 { 0x0000, 0x0000 }, /* R821 */
929 { 0x0000, 0x0000, 0x0000 }, /* R822 */ 927 { 0x0000, 0x0000 }, /* R822 */
930 { 0x0000, 0x0000, 0x0000 }, /* R823 */ 928 { 0x0000, 0x0000 }, /* R823 */
931 { 0x0000, 0x0000, 0x0000 }, /* R824 */ 929 { 0x0000, 0x0000 }, /* R824 */
932 { 0x0000, 0x0000, 0x0000 }, /* R825 */ 930 { 0x0000, 0x0000 }, /* R825 */
933 { 0x0000, 0x0000, 0x0000 }, /* R826 */ 931 { 0x0000, 0x0000 }, /* R826 */
934 { 0x0000, 0x0000, 0x0000 }, /* R827 */ 932 { 0x0000, 0x0000 }, /* R827 */
935 { 0x0000, 0x0000, 0x0000 }, /* R828 */ 933 { 0x0000, 0x0000 }, /* R828 */
936 { 0x0000, 0x0000, 0x0000 }, /* R829 */ 934 { 0x0000, 0x0000 }, /* R829 */
937 { 0x0000, 0x0000, 0x0000 }, /* R830 */ 935 { 0x0000, 0x0000 }, /* R830 */
938 { 0x0000, 0x0000, 0x0000 }, /* R831 */ 936 { 0x0000, 0x0000 }, /* R831 */
939 { 0x0000, 0x0000, 0x0000 }, /* R832 */ 937 { 0x0000, 0x0000 }, /* R832 */
940 { 0x0000, 0x0000, 0x0000 }, /* R833 */ 938 { 0x0000, 0x0000 }, /* R833 */
941 { 0x0000, 0x0000, 0x0000 }, /* R834 */ 939 { 0x0000, 0x0000 }, /* R834 */
942 { 0x0000, 0x0000, 0x0000 }, /* R835 */ 940 { 0x0000, 0x0000 }, /* R835 */
943 { 0x0000, 0x0000, 0x0000 }, /* R836 */ 941 { 0x0000, 0x0000 }, /* R836 */
944 { 0x0000, 0x0000, 0x0000 }, /* R837 */ 942 { 0x0000, 0x0000 }, /* R837 */
945 { 0x0000, 0x0000, 0x0000 }, /* R838 */ 943 { 0x0000, 0x0000 }, /* R838 */
946 { 0x0000, 0x0000, 0x0000 }, /* R839 */ 944 { 0x0000, 0x0000 }, /* R839 */
947 { 0x0000, 0x0000, 0x0000 }, /* R840 */ 945 { 0x0000, 0x0000 }, /* R840 */
948 { 0x0000, 0x0000, 0x0000 }, /* R841 */ 946 { 0x0000, 0x0000 }, /* R841 */
949 { 0x0000, 0x0000, 0x0000 }, /* R842 */ 947 { 0x0000, 0x0000 }, /* R842 */
950 { 0x0000, 0x0000, 0x0000 }, /* R843 */ 948 { 0x0000, 0x0000 }, /* R843 */
951 { 0x0000, 0x0000, 0x0000 }, /* R844 */ 949 { 0x0000, 0x0000 }, /* R844 */
952 { 0x0000, 0x0000, 0x0000 }, /* R845 */ 950 { 0x0000, 0x0000 }, /* R845 */
953 { 0x0000, 0x0000, 0x0000 }, /* R846 */ 951 { 0x0000, 0x0000 }, /* R846 */
954 { 0x0000, 0x0000, 0x0000 }, /* R847 */ 952 { 0x0000, 0x0000 }, /* R847 */
955 { 0x0000, 0x0000, 0x0000 }, /* R848 */ 953 { 0x0000, 0x0000 }, /* R848 */
956 { 0x0000, 0x0000, 0x0000 }, /* R849 */ 954 { 0x0000, 0x0000 }, /* R849 */
957 { 0x0000, 0x0000, 0x0000 }, /* R850 */ 955 { 0x0000, 0x0000 }, /* R850 */
958 { 0x0000, 0x0000, 0x0000 }, /* R851 */ 956 { 0x0000, 0x0000 }, /* R851 */
959 { 0x0000, 0x0000, 0x0000 }, /* R852 */ 957 { 0x0000, 0x0000 }, /* R852 */
960 { 0x0000, 0x0000, 0x0000 }, /* R853 */ 958 { 0x0000, 0x0000 }, /* R853 */
961 { 0x0000, 0x0000, 0x0000 }, /* R854 */ 959 { 0x0000, 0x0000 }, /* R854 */
962 { 0x0000, 0x0000, 0x0000 }, /* R855 */ 960 { 0x0000, 0x0000 }, /* R855 */
963 { 0x0000, 0x0000, 0x0000 }, /* R856 */ 961 { 0x0000, 0x0000 }, /* R856 */
964 { 0x0000, 0x0000, 0x0000 }, /* R857 */ 962 { 0x0000, 0x0000 }, /* R857 */
965 { 0x0000, 0x0000, 0x0000 }, /* R858 */ 963 { 0x0000, 0x0000 }, /* R858 */
966 { 0x0000, 0x0000, 0x0000 }, /* R859 */ 964 { 0x0000, 0x0000 }, /* R859 */
967 { 0x0000, 0x0000, 0x0000 }, /* R860 */ 965 { 0x0000, 0x0000 }, /* R860 */
968 { 0x0000, 0x0000, 0x0000 }, /* R861 */ 966 { 0x0000, 0x0000 }, /* R861 */
969 { 0x0000, 0x0000, 0x0000 }, /* R862 */ 967 { 0x0000, 0x0000 }, /* R862 */
970 { 0x0000, 0x0000, 0x0000 }, /* R863 */ 968 { 0x0000, 0x0000 }, /* R863 */
971 { 0x0000, 0x0000, 0x0000 }, /* R864 */ 969 { 0x0000, 0x0000 }, /* R864 */
972 { 0x0000, 0x0000, 0x0000 }, /* R865 */ 970 { 0x0000, 0x0000 }, /* R865 */
973 { 0x0000, 0x0000, 0x0000 }, /* R866 */ 971 { 0x0000, 0x0000 }, /* R866 */
974 { 0x0000, 0x0000, 0x0000 }, /* R867 */ 972 { 0x0000, 0x0000 }, /* R867 */
975 { 0x0000, 0x0000, 0x0000 }, /* R868 */ 973 { 0x0000, 0x0000 }, /* R868 */
976 { 0x0000, 0x0000, 0x0000 }, /* R869 */ 974 { 0x0000, 0x0000 }, /* R869 */
977 { 0x0000, 0x0000, 0x0000 }, /* R870 */ 975 { 0x0000, 0x0000 }, /* R870 */
978 { 0x0000, 0x0000, 0x0000 }, /* R871 */ 976 { 0x0000, 0x0000 }, /* R871 */
979 { 0x0000, 0x0000, 0x0000 }, /* R872 */ 977 { 0x0000, 0x0000 }, /* R872 */
980 { 0x0000, 0x0000, 0x0000 }, /* R873 */ 978 { 0x0000, 0x0000 }, /* R873 */
981 { 0x0000, 0x0000, 0x0000 }, /* R874 */ 979 { 0x0000, 0x0000 }, /* R874 */
982 { 0x0000, 0x0000, 0x0000 }, /* R875 */ 980 { 0x0000, 0x0000 }, /* R875 */
983 { 0x0000, 0x0000, 0x0000 }, /* R876 */ 981 { 0x0000, 0x0000 }, /* R876 */
984 { 0x0000, 0x0000, 0x0000 }, /* R877 */ 982 { 0x0000, 0x0000 }, /* R877 */
985 { 0x0000, 0x0000, 0x0000 }, /* R878 */ 983 { 0x0000, 0x0000 }, /* R878 */
986 { 0x0000, 0x0000, 0x0000 }, /* R879 */ 984 { 0x0000, 0x0000 }, /* R879 */
987 { 0x0000, 0x0000, 0x0000 }, /* R880 */ 985 { 0x0000, 0x0000 }, /* R880 */
988 { 0x0000, 0x0000, 0x0000 }, /* R881 */ 986 { 0x0000, 0x0000 }, /* R881 */
989 { 0x0000, 0x0000, 0x0000 }, /* R882 */ 987 { 0x0000, 0x0000 }, /* R882 */
990 { 0x0000, 0x0000, 0x0000 }, /* R883 */ 988 { 0x0000, 0x0000 }, /* R883 */
991 { 0x0000, 0x0000, 0x0000 }, /* R884 */ 989 { 0x0000, 0x0000 }, /* R884 */
992 { 0x0000, 0x0000, 0x0000 }, /* R885 */ 990 { 0x0000, 0x0000 }, /* R885 */
993 { 0x0000, 0x0000, 0x0000 }, /* R886 */ 991 { 0x0000, 0x0000 }, /* R886 */
994 { 0x0000, 0x0000, 0x0000 }, /* R887 */ 992 { 0x0000, 0x0000 }, /* R887 */
995 { 0x0000, 0x0000, 0x0000 }, /* R888 */ 993 { 0x0000, 0x0000 }, /* R888 */
996 { 0x0000, 0x0000, 0x0000 }, /* R889 */ 994 { 0x0000, 0x0000 }, /* R889 */
997 { 0x0000, 0x0000, 0x0000 }, /* R890 */ 995 { 0x0000, 0x0000 }, /* R890 */
998 { 0x0000, 0x0000, 0x0000 }, /* R891 */ 996 { 0x0000, 0x0000 }, /* R891 */
999 { 0x0000, 0x0000, 0x0000 }, /* R892 */ 997 { 0x0000, 0x0000 }, /* R892 */
1000 { 0x0000, 0x0000, 0x0000 }, /* R893 */ 998 { 0x0000, 0x0000 }, /* R893 */
1001 { 0x0000, 0x0000, 0x0000 }, /* R894 */ 999 { 0x0000, 0x0000 }, /* R894 */
1002 { 0x0000, 0x0000, 0x0000 }, /* R895 */ 1000 { 0x0000, 0x0000 }, /* R895 */
1003 { 0x0000, 0x0000, 0x0000 }, /* R896 */ 1001 { 0x0000, 0x0000 }, /* R896 */
1004 { 0x0000, 0x0000, 0x0000 }, /* R897 */ 1002 { 0x0000, 0x0000 }, /* R897 */
1005 { 0x0000, 0x0000, 0x0000 }, /* R898 */ 1003 { 0x0000, 0x0000 }, /* R898 */
1006 { 0x0000, 0x0000, 0x0000 }, /* R899 */ 1004 { 0x0000, 0x0000 }, /* R899 */
1007 { 0x0000, 0x0000, 0x0000 }, /* R900 */ 1005 { 0x0000, 0x0000 }, /* R900 */
1008 { 0x0000, 0x0000, 0x0000 }, /* R901 */ 1006 { 0x0000, 0x0000 }, /* R901 */
1009 { 0x0000, 0x0000, 0x0000 }, /* R902 */ 1007 { 0x0000, 0x0000 }, /* R902 */
1010 { 0x0000, 0x0000, 0x0000 }, /* R903 */ 1008 { 0x0000, 0x0000 }, /* R903 */
1011 { 0x0000, 0x0000, 0x0000 }, /* R904 */ 1009 { 0x0000, 0x0000 }, /* R904 */
1012 { 0x0000, 0x0000, 0x0000 }, /* R905 */ 1010 { 0x0000, 0x0000 }, /* R905 */
1013 { 0x0000, 0x0000, 0x0000 }, /* R906 */ 1011 { 0x0000, 0x0000 }, /* R906 */
1014 { 0x0000, 0x0000, 0x0000 }, /* R907 */ 1012 { 0x0000, 0x0000 }, /* R907 */
1015 { 0x0000, 0x0000, 0x0000 }, /* R908 */ 1013 { 0x0000, 0x0000 }, /* R908 */
1016 { 0x0000, 0x0000, 0x0000 }, /* R909 */ 1014 { 0x0000, 0x0000 }, /* R909 */
1017 { 0x0000, 0x0000, 0x0000 }, /* R910 */ 1015 { 0x0000, 0x0000 }, /* R910 */
1018 { 0x0000, 0x0000, 0x0000 }, /* R911 */ 1016 { 0x0000, 0x0000 }, /* R911 */
1019 { 0x0000, 0x0000, 0x0000 }, /* R912 */ 1017 { 0x0000, 0x0000 }, /* R912 */
1020 { 0x0000, 0x0000, 0x0000 }, /* R913 */ 1018 { 0x0000, 0x0000 }, /* R913 */
1021 { 0x0000, 0x0000, 0x0000 }, /* R914 */ 1019 { 0x0000, 0x0000 }, /* R914 */
1022 { 0x0000, 0x0000, 0x0000 }, /* R915 */ 1020 { 0x0000, 0x0000 }, /* R915 */
1023 { 0x0000, 0x0000, 0x0000 }, /* R916 */ 1021 { 0x0000, 0x0000 }, /* R916 */
1024 { 0x0000, 0x0000, 0x0000 }, /* R917 */ 1022 { 0x0000, 0x0000 }, /* R917 */
1025 { 0x0000, 0x0000, 0x0000 }, /* R918 */ 1023 { 0x0000, 0x0000 }, /* R918 */
1026 { 0x0000, 0x0000, 0x0000 }, /* R919 */ 1024 { 0x0000, 0x0000 }, /* R919 */
1027 { 0x0000, 0x0000, 0x0000 }, /* R920 */ 1025 { 0x0000, 0x0000 }, /* R920 */
1028 { 0x0000, 0x0000, 0x0000 }, /* R921 */ 1026 { 0x0000, 0x0000 }, /* R921 */
1029 { 0x0000, 0x0000, 0x0000 }, /* R922 */ 1027 { 0x0000, 0x0000 }, /* R922 */
1030 { 0x0000, 0x0000, 0x0000 }, /* R923 */ 1028 { 0x0000, 0x0000 }, /* R923 */
1031 { 0x0000, 0x0000, 0x0000 }, /* R924 */ 1029 { 0x0000, 0x0000 }, /* R924 */
1032 { 0x0000, 0x0000, 0x0000 }, /* R925 */ 1030 { 0x0000, 0x0000 }, /* R925 */
1033 { 0x0000, 0x0000, 0x0000 }, /* R926 */ 1031 { 0x0000, 0x0000 }, /* R926 */
1034 { 0x0000, 0x0000, 0x0000 }, /* R927 */ 1032 { 0x0000, 0x0000 }, /* R927 */
1035 { 0x0000, 0x0000, 0x0000 }, /* R928 */ 1033 { 0x0000, 0x0000 }, /* R928 */
1036 { 0x0000, 0x0000, 0x0000 }, /* R929 */ 1034 { 0x0000, 0x0000 }, /* R929 */
1037 { 0x0000, 0x0000, 0x0000 }, /* R930 */ 1035 { 0x0000, 0x0000 }, /* R930 */
1038 { 0x0000, 0x0000, 0x0000 }, /* R931 */ 1036 { 0x0000, 0x0000 }, /* R931 */
1039 { 0x0000, 0x0000, 0x0000 }, /* R932 */ 1037 { 0x0000, 0x0000 }, /* R932 */
1040 { 0x0000, 0x0000, 0x0000 }, /* R933 */ 1038 { 0x0000, 0x0000 }, /* R933 */
1041 { 0x0000, 0x0000, 0x0000 }, /* R934 */ 1039 { 0x0000, 0x0000 }, /* R934 */
1042 { 0x0000, 0x0000, 0x0000 }, /* R935 */ 1040 { 0x0000, 0x0000 }, /* R935 */
1043 { 0x0000, 0x0000, 0x0000 }, /* R936 */ 1041 { 0x0000, 0x0000 }, /* R936 */
1044 { 0x0000, 0x0000, 0x0000 }, /* R937 */ 1042 { 0x0000, 0x0000 }, /* R937 */
1045 { 0x0000, 0x0000, 0x0000 }, /* R938 */ 1043 { 0x0000, 0x0000 }, /* R938 */
1046 { 0x0000, 0x0000, 0x0000 }, /* R939 */ 1044 { 0x0000, 0x0000 }, /* R939 */
1047 { 0x0000, 0x0000, 0x0000 }, /* R940 */ 1045 { 0x0000, 0x0000 }, /* R940 */
1048 { 0x0000, 0x0000, 0x0000 }, /* R941 */ 1046 { 0x0000, 0x0000 }, /* R941 */
1049 { 0x0000, 0x0000, 0x0000 }, /* R942 */ 1047 { 0x0000, 0x0000 }, /* R942 */
1050 { 0x0000, 0x0000, 0x0000 }, /* R943 */ 1048 { 0x0000, 0x0000 }, /* R943 */
1051 { 0x0000, 0x0000, 0x0000 }, /* R944 */ 1049 { 0x0000, 0x0000 }, /* R944 */
1052 { 0x0000, 0x0000, 0x0000 }, /* R945 */ 1050 { 0x0000, 0x0000 }, /* R945 */
1053 { 0x0000, 0x0000, 0x0000 }, /* R946 */ 1051 { 0x0000, 0x0000 }, /* R946 */
1054 { 0x0000, 0x0000, 0x0000 }, /* R947 */ 1052 { 0x0000, 0x0000 }, /* R947 */
1055 { 0x0000, 0x0000, 0x0000 }, /* R948 */ 1053 { 0x0000, 0x0000 }, /* R948 */
1056 { 0x0000, 0x0000, 0x0000 }, /* R949 */ 1054 { 0x0000, 0x0000 }, /* R949 */
1057 { 0x0000, 0x0000, 0x0000 }, /* R950 */ 1055 { 0x0000, 0x0000 }, /* R950 */
1058 { 0x0000, 0x0000, 0x0000 }, /* R951 */ 1056 { 0x0000, 0x0000 }, /* R951 */
1059 { 0x0000, 0x0000, 0x0000 }, /* R952 */ 1057 { 0x0000, 0x0000 }, /* R952 */
1060 { 0x0000, 0x0000, 0x0000 }, /* R953 */ 1058 { 0x0000, 0x0000 }, /* R953 */
1061 { 0x0000, 0x0000, 0x0000 }, /* R954 */ 1059 { 0x0000, 0x0000 }, /* R954 */
1062 { 0x0000, 0x0000, 0x0000 }, /* R955 */ 1060 { 0x0000, 0x0000 }, /* R955 */
1063 { 0x0000, 0x0000, 0x0000 }, /* R956 */ 1061 { 0x0000, 0x0000 }, /* R956 */
1064 { 0x0000, 0x0000, 0x0000 }, /* R957 */ 1062 { 0x0000, 0x0000 }, /* R957 */
1065 { 0x0000, 0x0000, 0x0000 }, /* R958 */ 1063 { 0x0000, 0x0000 }, /* R958 */
1066 { 0x0000, 0x0000, 0x0000 }, /* R959 */ 1064 { 0x0000, 0x0000 }, /* R959 */
1067 { 0x0000, 0x0000, 0x0000 }, /* R960 */ 1065 { 0x0000, 0x0000 }, /* R960 */
1068 { 0x0000, 0x0000, 0x0000 }, /* R961 */ 1066 { 0x0000, 0x0000 }, /* R961 */
1069 { 0x0000, 0x0000, 0x0000 }, /* R962 */ 1067 { 0x0000, 0x0000 }, /* R962 */
1070 { 0x0000, 0x0000, 0x0000 }, /* R963 */ 1068 { 0x0000, 0x0000 }, /* R963 */
1071 { 0x0000, 0x0000, 0x0000 }, /* R964 */ 1069 { 0x0000, 0x0000 }, /* R964 */
1072 { 0x0000, 0x0000, 0x0000 }, /* R965 */ 1070 { 0x0000, 0x0000 }, /* R965 */
1073 { 0x0000, 0x0000, 0x0000 }, /* R966 */ 1071 { 0x0000, 0x0000 }, /* R966 */
1074 { 0x0000, 0x0000, 0x0000 }, /* R967 */ 1072 { 0x0000, 0x0000 }, /* R967 */
1075 { 0x0000, 0x0000, 0x0000 }, /* R968 */ 1073 { 0x0000, 0x0000 }, /* R968 */
1076 { 0x0000, 0x0000, 0x0000 }, /* R969 */ 1074 { 0x0000, 0x0000 }, /* R969 */
1077 { 0x0000, 0x0000, 0x0000 }, /* R970 */ 1075 { 0x0000, 0x0000 }, /* R970 */
1078 { 0x0000, 0x0000, 0x0000 }, /* R971 */ 1076 { 0x0000, 0x0000 }, /* R971 */
1079 { 0x0000, 0x0000, 0x0000 }, /* R972 */ 1077 { 0x0000, 0x0000 }, /* R972 */
1080 { 0x0000, 0x0000, 0x0000 }, /* R973 */ 1078 { 0x0000, 0x0000 }, /* R973 */
1081 { 0x0000, 0x0000, 0x0000 }, /* R974 */ 1079 { 0x0000, 0x0000 }, /* R974 */
1082 { 0x0000, 0x0000, 0x0000 }, /* R975 */ 1080 { 0x0000, 0x0000 }, /* R975 */
1083 { 0x0000, 0x0000, 0x0000 }, /* R976 */ 1081 { 0x0000, 0x0000 }, /* R976 */
1084 { 0x0000, 0x0000, 0x0000 }, /* R977 */ 1082 { 0x0000, 0x0000 }, /* R977 */
1085 { 0x0000, 0x0000, 0x0000 }, /* R978 */ 1083 { 0x0000, 0x0000 }, /* R978 */
1086 { 0x0000, 0x0000, 0x0000 }, /* R979 */ 1084 { 0x0000, 0x0000 }, /* R979 */
1087 { 0x0000, 0x0000, 0x0000 }, /* R980 */ 1085 { 0x0000, 0x0000 }, /* R980 */
1088 { 0x0000, 0x0000, 0x0000 }, /* R981 */ 1086 { 0x0000, 0x0000 }, /* R981 */
1089 { 0x0000, 0x0000, 0x0000 }, /* R982 */ 1087 { 0x0000, 0x0000 }, /* R982 */
1090 { 0x0000, 0x0000, 0x0000 }, /* R983 */ 1088 { 0x0000, 0x0000 }, /* R983 */
1091 { 0x0000, 0x0000, 0x0000 }, /* R984 */ 1089 { 0x0000, 0x0000 }, /* R984 */
1092 { 0x0000, 0x0000, 0x0000 }, /* R985 */ 1090 { 0x0000, 0x0000 }, /* R985 */
1093 { 0x0000, 0x0000, 0x0000 }, /* R986 */ 1091 { 0x0000, 0x0000 }, /* R986 */
1094 { 0x0000, 0x0000, 0x0000 }, /* R987 */ 1092 { 0x0000, 0x0000 }, /* R987 */
1095 { 0x0000, 0x0000, 0x0000 }, /* R988 */ 1093 { 0x0000, 0x0000 }, /* R988 */
1096 { 0x0000, 0x0000, 0x0000 }, /* R989 */ 1094 { 0x0000, 0x0000 }, /* R989 */
1097 { 0x0000, 0x0000, 0x0000 }, /* R990 */ 1095 { 0x0000, 0x0000 }, /* R990 */
1098 { 0x0000, 0x0000, 0x0000 }, /* R991 */ 1096 { 0x0000, 0x0000 }, /* R991 */
1099 { 0x0000, 0x0000, 0x0000 }, /* R992 */ 1097 { 0x0000, 0x0000 }, /* R992 */
1100 { 0x0000, 0x0000, 0x0000 }, /* R993 */ 1098 { 0x0000, 0x0000 }, /* R993 */
1101 { 0x0000, 0x0000, 0x0000 }, /* R994 */ 1099 { 0x0000, 0x0000 }, /* R994 */
1102 { 0x0000, 0x0000, 0x0000 }, /* R995 */ 1100 { 0x0000, 0x0000 }, /* R995 */
1103 { 0x0000, 0x0000, 0x0000 }, /* R996 */ 1101 { 0x0000, 0x0000 }, /* R996 */
1104 { 0x0000, 0x0000, 0x0000 }, /* R997 */ 1102 { 0x0000, 0x0000 }, /* R997 */
1105 { 0x0000, 0x0000, 0x0000 }, /* R998 */ 1103 { 0x0000, 0x0000 }, /* R998 */
1106 { 0x0000, 0x0000, 0x0000 }, /* R999 */ 1104 { 0x0000, 0x0000 }, /* R999 */
1107 { 0x0000, 0x0000, 0x0000 }, /* R1000 */ 1105 { 0x0000, 0x0000 }, /* R1000 */
1108 { 0x0000, 0x0000, 0x0000 }, /* R1001 */ 1106 { 0x0000, 0x0000 }, /* R1001 */
1109 { 0x0000, 0x0000, 0x0000 }, /* R1002 */ 1107 { 0x0000, 0x0000 }, /* R1002 */
1110 { 0x0000, 0x0000, 0x0000 }, /* R1003 */ 1108 { 0x0000, 0x0000 }, /* R1003 */
1111 { 0x0000, 0x0000, 0x0000 }, /* R1004 */ 1109 { 0x0000, 0x0000 }, /* R1004 */
1112 { 0x0000, 0x0000, 0x0000 }, /* R1005 */ 1110 { 0x0000, 0x0000 }, /* R1005 */
1113 { 0x0000, 0x0000, 0x0000 }, /* R1006 */ 1111 { 0x0000, 0x0000 }, /* R1006 */
1114 { 0x0000, 0x0000, 0x0000 }, /* R1007 */ 1112 { 0x0000, 0x0000 }, /* R1007 */
1115 { 0x0000, 0x0000, 0x0000 }, /* R1008 */ 1113 { 0x0000, 0x0000 }, /* R1008 */
1116 { 0x0000, 0x0000, 0x0000 }, /* R1009 */ 1114 { 0x0000, 0x0000 }, /* R1009 */
1117 { 0x0000, 0x0000, 0x0000 }, /* R1010 */ 1115 { 0x0000, 0x0000 }, /* R1010 */
1118 { 0x0000, 0x0000, 0x0000 }, /* R1011 */ 1116 { 0x0000, 0x0000 }, /* R1011 */
1119 { 0x0000, 0x0000, 0x0000 }, /* R1012 */ 1117 { 0x0000, 0x0000 }, /* R1012 */
1120 { 0x0000, 0x0000, 0x0000 }, /* R1013 */ 1118 { 0x0000, 0x0000 }, /* R1013 */
1121 { 0x0000, 0x0000, 0x0000 }, /* R1014 */ 1119 { 0x0000, 0x0000 }, /* R1014 */
1122 { 0x0000, 0x0000, 0x0000 }, /* R1015 */ 1120 { 0x0000, 0x0000 }, /* R1015 */
1123 { 0x0000, 0x0000, 0x0000 }, /* R1016 */ 1121 { 0x0000, 0x0000 }, /* R1016 */
1124 { 0x0000, 0x0000, 0x0000 }, /* R1017 */ 1122 { 0x0000, 0x0000 }, /* R1017 */
1125 { 0x0000, 0x0000, 0x0000 }, /* R1018 */ 1123 { 0x0000, 0x0000 }, /* R1018 */
1126 { 0x0000, 0x0000, 0x0000 }, /* R1019 */ 1124 { 0x0000, 0x0000 }, /* R1019 */
1127 { 0x0000, 0x0000, 0x0000 }, /* R1020 */ 1125 { 0x0000, 0x0000 }, /* R1020 */
1128 { 0x0000, 0x0000, 0x0000 }, /* R1021 */ 1126 { 0x0000, 0x0000 }, /* R1021 */
1129 { 0x0000, 0x0000, 0x0000 }, /* R1022 */ 1127 { 0x0000, 0x0000 }, /* R1022 */
1130 { 0x0000, 0x0000, 0x0000 }, /* R1023 */ 1128 { 0x0000, 0x0000 }, /* R1023 */
1131 { 0x00FF, 0x01FF, 0x0000 }, /* R1024 - AIF1 ADC1 Left Volume */ 1129 { 0x00FF, 0x01FF }, /* R1024 - AIF1 ADC1 Left Volume */
1132 { 0x00FF, 0x01FF, 0x0000 }, /* R1025 - AIF1 ADC1 Right Volume */ 1130 { 0x00FF, 0x01FF }, /* R1025 - AIF1 ADC1 Right Volume */
1133 { 0x00FF, 0x01FF, 0x0000 }, /* R1026 - AIF1 DAC1 Left Volume */ 1131 { 0x00FF, 0x01FF }, /* R1026 - AIF1 DAC1 Left Volume */
1134 { 0x00FF, 0x01FF, 0x0000 }, /* R1027 - AIF1 DAC1 Right Volume */ 1132 { 0x00FF, 0x01FF }, /* R1027 - AIF1 DAC1 Right Volume */
1135 { 0x00FF, 0x01FF, 0x0000 }, /* R1028 - AIF1 ADC2 Left Volume */ 1133 { 0x00FF, 0x01FF }, /* R1028 - AIF1 ADC2 Left Volume */
1136 { 0x00FF, 0x01FF, 0x0000 }, /* R1029 - AIF1 ADC2 Right Volume */ 1134 { 0x00FF, 0x01FF }, /* R1029 - AIF1 ADC2 Right Volume */
1137 { 0x00FF, 0x01FF, 0x0000 }, /* R1030 - AIF1 DAC2 Left Volume */ 1135 { 0x00FF, 0x01FF }, /* R1030 - AIF1 DAC2 Left Volume */
1138 { 0x00FF, 0x01FF, 0x0000 }, /* R1031 - AIF1 DAC2 Right Volume */ 1136 { 0x00FF, 0x01FF }, /* R1031 - AIF1 DAC2 Right Volume */
1139 { 0x0000, 0x0000, 0x0000 }, /* R1032 */ 1137 { 0x0000, 0x0000 }, /* R1032 */
1140 { 0x0000, 0x0000, 0x0000 }, /* R1033 */ 1138 { 0x0000, 0x0000 }, /* R1033 */
1141 { 0x0000, 0x0000, 0x0000 }, /* R1034 */ 1139 { 0x0000, 0x0000 }, /* R1034 */
1142 { 0x0000, 0x0000, 0x0000 }, /* R1035 */ 1140 { 0x0000, 0x0000 }, /* R1035 */
1143 { 0x0000, 0x0000, 0x0000 }, /* R1036 */ 1141 { 0x0000, 0x0000 }, /* R1036 */
1144 { 0x0000, 0x0000, 0x0000 }, /* R1037 */ 1142 { 0x0000, 0x0000 }, /* R1037 */
1145 { 0x0000, 0x0000, 0x0000 }, /* R1038 */ 1143 { 0x0000, 0x0000 }, /* R1038 */
1146 { 0x0000, 0x0000, 0x0000 }, /* R1039 */ 1144 { 0x0000, 0x0000 }, /* R1039 */
1147 { 0xF800, 0xF800, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */ 1145 { 0xF800, 0xF800 }, /* R1040 - AIF1 ADC1 Filters */
1148 { 0x7800, 0x7800, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */ 1146 { 0x7800, 0x7800 }, /* R1041 - AIF1 ADC2 Filters */
1149 { 0x0000, 0x0000, 0x0000 }, /* R1042 */ 1147 { 0x0000, 0x0000 }, /* R1042 */
1150 { 0x0000, 0x0000, 0x0000 }, /* R1043 */ 1148 { 0x0000, 0x0000 }, /* R1043 */
1151 { 0x0000, 0x0000, 0x0000 }, /* R1044 */ 1149 { 0x0000, 0x0000 }, /* R1044 */
1152 { 0x0000, 0x0000, 0x0000 }, /* R1045 */ 1150 { 0x0000, 0x0000 }, /* R1045 */
1153 { 0x0000, 0x0000, 0x0000 }, /* R1046 */ 1151 { 0x0000, 0x0000 }, /* R1046 */
1154 { 0x0000, 0x0000, 0x0000 }, /* R1047 */ 1152 { 0x0000, 0x0000 }, /* R1047 */
1155 { 0x0000, 0x0000, 0x0000 }, /* R1048 */ 1153 { 0x0000, 0x0000 }, /* R1048 */
1156 { 0x0000, 0x0000, 0x0000 }, /* R1049 */ 1154 { 0x0000, 0x0000 }, /* R1049 */
1157 { 0x0000, 0x0000, 0x0000 }, /* R1050 */ 1155 { 0x0000, 0x0000 }, /* R1050 */
1158 { 0x0000, 0x0000, 0x0000 }, /* R1051 */ 1156 { 0x0000, 0x0000 }, /* R1051 */
1159 { 0x0000, 0x0000, 0x0000 }, /* R1052 */ 1157 { 0x0000, 0x0000 }, /* R1052 */
1160 { 0x0000, 0x0000, 0x0000 }, /* R1053 */ 1158 { 0x0000, 0x0000 }, /* R1053 */
1161 { 0x0000, 0x0000, 0x0000 }, /* R1054 */ 1159 { 0x0000, 0x0000 }, /* R1054 */
1162 { 0x0000, 0x0000, 0x0000 }, /* R1055 */ 1160 { 0x0000, 0x0000 }, /* R1055 */
1163 { 0x02B6, 0x02B6, 0x0000 }, /* R1056 - AIF1 DAC1 Filters (1) */ 1161 { 0x02B6, 0x02B6 }, /* R1056 - AIF1 DAC1 Filters (1) */
1164 { 0x3F00, 0x3F00, 0x0000 }, /* R1057 - AIF1 DAC1 Filters (2) */ 1162 { 0x3F00, 0x3F00 }, /* R1057 - AIF1 DAC1 Filters (2) */
1165 { 0x02B6, 0x02B6, 0x0000 }, /* R1058 - AIF1 DAC2 Filters (1) */ 1163 { 0x02B6, 0x02B6 }, /* R1058 - AIF1 DAC2 Filters (1) */
1166 { 0x3F00, 0x3F00, 0x0000 }, /* R1059 - AIF1 DAC2 Filters (2) */ 1164 { 0x3F00, 0x3F00 }, /* R1059 - AIF1 DAC2 Filters (2) */
1167 { 0x0000, 0x0000, 0x0000 }, /* R1060 */ 1165 { 0x0000, 0x0000 }, /* R1060 */
1168 { 0x0000, 0x0000, 0x0000 }, /* R1061 */ 1166 { 0x0000, 0x0000 }, /* R1061 */
1169 { 0x0000, 0x0000, 0x0000 }, /* R1062 */ 1167 { 0x0000, 0x0000 }, /* R1062 */
1170 { 0x0000, 0x0000, 0x0000 }, /* R1063 */ 1168 { 0x0000, 0x0000 }, /* R1063 */
1171 { 0x0000, 0x0000, 0x0000 }, /* R1064 */ 1169 { 0x0000, 0x0000 }, /* R1064 */
1172 { 0x0000, 0x0000, 0x0000 }, /* R1065 */ 1170 { 0x0000, 0x0000 }, /* R1065 */
1173 { 0x0000, 0x0000, 0x0000 }, /* R1066 */ 1171 { 0x0000, 0x0000 }, /* R1066 */
1174 { 0x0000, 0x0000, 0x0000 }, /* R1067 */ 1172 { 0x0000, 0x0000 }, /* R1067 */
1175 { 0x0000, 0x0000, 0x0000 }, /* R1068 */ 1173 { 0x0000, 0x0000 }, /* R1068 */
1176 { 0x0000, 0x0000, 0x0000 }, /* R1069 */ 1174 { 0x0000, 0x0000 }, /* R1069 */
1177 { 0x0000, 0x0000, 0x0000 }, /* R1070 */ 1175 { 0x0000, 0x0000 }, /* R1070 */
1178 { 0x0000, 0x0000, 0x0000 }, /* R1071 */ 1176 { 0x0000, 0x0000 }, /* R1071 */
1179 { 0x0000, 0x0000, 0x0000 }, /* R1072 */ 1177 { 0x0000, 0x0000 }, /* R1072 */
1180 { 0x0000, 0x0000, 0x0000 }, /* R1073 */ 1178 { 0x0000, 0x0000 }, /* R1073 */
1181 { 0x0000, 0x0000, 0x0000 }, /* R1074 */ 1179 { 0x0000, 0x0000 }, /* R1074 */
1182 { 0x0000, 0x0000, 0x0000 }, /* R1075 */ 1180 { 0x0000, 0x0000 }, /* R1075 */
1183 { 0x0000, 0x0000, 0x0000 }, /* R1076 */ 1181 { 0x0000, 0x0000 }, /* R1076 */
1184 { 0x0000, 0x0000, 0x0000 }, /* R1077 */ 1182 { 0x0000, 0x0000 }, /* R1077 */
1185 { 0x0000, 0x0000, 0x0000 }, /* R1078 */ 1183 { 0x0000, 0x0000 }, /* R1078 */
1186 { 0x0000, 0x0000, 0x0000 }, /* R1079 */ 1184 { 0x0000, 0x0000 }, /* R1079 */
1187 { 0x0000, 0x0000, 0x0000 }, /* R1080 */ 1185 { 0x0000, 0x0000 }, /* R1080 */
1188 { 0x0000, 0x0000, 0x0000 }, /* R1081 */ 1186 { 0x0000, 0x0000 }, /* R1081 */
1189 { 0x0000, 0x0000, 0x0000 }, /* R1082 */ 1187 { 0x0000, 0x0000 }, /* R1082 */
1190 { 0x0000, 0x0000, 0x0000 }, /* R1083 */ 1188 { 0x0000, 0x0000 }, /* R1083 */
1191 { 0x0000, 0x0000, 0x0000 }, /* R1084 */ 1189 { 0x0000, 0x0000 }, /* R1084 */
1192 { 0x0000, 0x0000, 0x0000 }, /* R1085 */ 1190 { 0x0000, 0x0000 }, /* R1085 */
1193 { 0x0000, 0x0000, 0x0000 }, /* R1086 */ 1191 { 0x0000, 0x0000 }, /* R1086 */
1194 { 0x0000, 0x0000, 0x0000 }, /* R1087 */ 1192 { 0x0000, 0x0000 }, /* R1087 */
1195 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1088 - AIF1 DRC1 (1) */ 1193 { 0xFFFF, 0xFFFF }, /* R1088 - AIF1 DRC1 (1) */
1196 { 0x1FFF, 0x1FFF, 0x0000 }, /* R1089 - AIF1 DRC1 (2) */ 1194 { 0x1FFF, 0x1FFF }, /* R1089 - AIF1 DRC1 (2) */
1197 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */ 1195 { 0xFFFF, 0xFFFF }, /* R1090 - AIF1 DRC1 (3) */
1198 { 0x07FF, 0x07FF, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */ 1196 { 0x07FF, 0x07FF }, /* R1091 - AIF1 DRC1 (4) */
1199 { 0x03FF, 0x03FF, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */ 1197 { 0x03FF, 0x03FF }, /* R1092 - AIF1 DRC1 (5) */
1200 { 0x0000, 0x0000, 0x0000 }, /* R1093 */ 1198 { 0x0000, 0x0000 }, /* R1093 */
1201 { 0x0000, 0x0000, 0x0000 }, /* R1094 */ 1199 { 0x0000, 0x0000 }, /* R1094 */
1202 { 0x0000, 0x0000, 0x0000 }, /* R1095 */ 1200 { 0x0000, 0x0000 }, /* R1095 */
1203 { 0x0000, 0x0000, 0x0000 }, /* R1096 */ 1201 { 0x0000, 0x0000 }, /* R1096 */
1204 { 0x0000, 0x0000, 0x0000 }, /* R1097 */ 1202 { 0x0000, 0x0000 }, /* R1097 */
1205 { 0x0000, 0x0000, 0x0000 }, /* R1098 */ 1203 { 0x0000, 0x0000 }, /* R1098 */
1206 { 0x0000, 0x0000, 0x0000 }, /* R1099 */ 1204 { 0x0000, 0x0000 }, /* R1099 */
1207 { 0x0000, 0x0000, 0x0000 }, /* R1100 */ 1205 { 0x0000, 0x0000 }, /* R1100 */
1208 { 0x0000, 0x0000, 0x0000 }, /* R1101 */ 1206 { 0x0000, 0x0000 }, /* R1101 */
1209 { 0x0000, 0x0000, 0x0000 }, /* R1102 */ 1207 { 0x0000, 0x0000 }, /* R1102 */
1210 { 0x0000, 0x0000, 0x0000 }, /* R1103 */ 1208 { 0x0000, 0x0000 }, /* R1103 */
1211 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1104 - AIF1 DRC2 (1) */ 1209 { 0xFFFF, 0xFFFF }, /* R1104 - AIF1 DRC2 (1) */
1212 { 0x1FFF, 0x1FFF, 0x0000 }, /* R1105 - AIF1 DRC2 (2) */ 1210 { 0x1FFF, 0x1FFF }, /* R1105 - AIF1 DRC2 (2) */
1213 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */ 1211 { 0xFFFF, 0xFFFF }, /* R1106 - AIF1 DRC2 (3) */
1214 { 0x07FF, 0x07FF, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */ 1212 { 0x07FF, 0x07FF }, /* R1107 - AIF1 DRC2 (4) */
1215 { 0x03FF, 0x03FF, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */ 1213 { 0x03FF, 0x03FF }, /* R1108 - AIF1 DRC2 (5) */
1216 { 0x0000, 0x0000, 0x0000 }, /* R1109 */ 1214 { 0x0000, 0x0000 }, /* R1109 */
1217 { 0x0000, 0x0000, 0x0000 }, /* R1110 */ 1215 { 0x0000, 0x0000 }, /* R1110 */
1218 { 0x0000, 0x0000, 0x0000 }, /* R1111 */ 1216 { 0x0000, 0x0000 }, /* R1111 */
1219 { 0x0000, 0x0000, 0x0000 }, /* R1112 */ 1217 { 0x0000, 0x0000 }, /* R1112 */
1220 { 0x0000, 0x0000, 0x0000 }, /* R1113 */ 1218 { 0x0000, 0x0000 }, /* R1113 */
1221 { 0x0000, 0x0000, 0x0000 }, /* R1114 */ 1219 { 0x0000, 0x0000 }, /* R1114 */
1222 { 0x0000, 0x0000, 0x0000 }, /* R1115 */ 1220 { 0x0000, 0x0000 }, /* R1115 */
1223 { 0x0000, 0x0000, 0x0000 }, /* R1116 */ 1221 { 0x0000, 0x0000 }, /* R1116 */
1224 { 0x0000, 0x0000, 0x0000 }, /* R1117 */ 1222 { 0x0000, 0x0000 }, /* R1117 */
1225 { 0x0000, 0x0000, 0x0000 }, /* R1118 */ 1223 { 0x0000, 0x0000 }, /* R1118 */
1226 { 0x0000, 0x0000, 0x0000 }, /* R1119 */ 1224 { 0x0000, 0x0000 }, /* R1119 */
1227 { 0x0000, 0x0000, 0x0000 }, /* R1120 */ 1225 { 0x0000, 0x0000 }, /* R1120 */
1228 { 0x0000, 0x0000, 0x0000 }, /* R1121 */ 1226 { 0x0000, 0x0000 }, /* R1121 */
1229 { 0x0000, 0x0000, 0x0000 }, /* R1122 */ 1227 { 0x0000, 0x0000 }, /* R1122 */
1230 { 0x0000, 0x0000, 0x0000 }, /* R1123 */ 1228 { 0x0000, 0x0000 }, /* R1123 */
1231 { 0x0000, 0x0000, 0x0000 }, /* R1124 */ 1229 { 0x0000, 0x0000 }, /* R1124 */
1232 { 0x0000, 0x0000, 0x0000 }, /* R1125 */ 1230 { 0x0000, 0x0000 }, /* R1125 */
1233 { 0x0000, 0x0000, 0x0000 }, /* R1126 */ 1231 { 0x0000, 0x0000 }, /* R1126 */
1234 { 0x0000, 0x0000, 0x0000 }, /* R1127 */ 1232 { 0x0000, 0x0000 }, /* R1127 */
1235 { 0x0000, 0x0000, 0x0000 }, /* R1128 */ 1233 { 0x0000, 0x0000 }, /* R1128 */
1236 { 0x0000, 0x0000, 0x0000 }, /* R1129 */ 1234 { 0x0000, 0x0000 }, /* R1129 */
1237 { 0x0000, 0x0000, 0x0000 }, /* R1130 */ 1235 { 0x0000, 0x0000 }, /* R1130 */
1238 { 0x0000, 0x0000, 0x0000 }, /* R1131 */ 1236 { 0x0000, 0x0000 }, /* R1131 */
1239 { 0x0000, 0x0000, 0x0000 }, /* R1132 */ 1237 { 0x0000, 0x0000 }, /* R1132 */
1240 { 0x0000, 0x0000, 0x0000 }, /* R1133 */ 1238 { 0x0000, 0x0000 }, /* R1133 */
1241 { 0x0000, 0x0000, 0x0000 }, /* R1134 */ 1239 { 0x0000, 0x0000 }, /* R1134 */
1242 { 0x0000, 0x0000, 0x0000 }, /* R1135 */ 1240 { 0x0000, 0x0000 }, /* R1135 */
1243 { 0x0000, 0x0000, 0x0000 }, /* R1136 */ 1241 { 0x0000, 0x0000 }, /* R1136 */
1244 { 0x0000, 0x0000, 0x0000 }, /* R1137 */ 1242 { 0x0000, 0x0000 }, /* R1137 */
1245 { 0x0000, 0x0000, 0x0000 }, /* R1138 */ 1243 { 0x0000, 0x0000 }, /* R1138 */
1246 { 0x0000, 0x0000, 0x0000 }, /* R1139 */ 1244 { 0x0000, 0x0000 }, /* R1139 */
1247 { 0x0000, 0x0000, 0x0000 }, /* R1140 */ 1245 { 0x0000, 0x0000 }, /* R1140 */
1248 { 0x0000, 0x0000, 0x0000 }, /* R1141 */ 1246 { 0x0000, 0x0000 }, /* R1141 */
1249 { 0x0000, 0x0000, 0x0000 }, /* R1142 */ 1247 { 0x0000, 0x0000 }, /* R1142 */
1250 { 0x0000, 0x0000, 0x0000 }, /* R1143 */ 1248 { 0x0000, 0x0000 }, /* R1143 */
1251 { 0x0000, 0x0000, 0x0000 }, /* R1144 */ 1249 { 0x0000, 0x0000 }, /* R1144 */
1252 { 0x0000, 0x0000, 0x0000 }, /* R1145 */ 1250 { 0x0000, 0x0000 }, /* R1145 */
1253 { 0x0000, 0x0000, 0x0000 }, /* R1146 */ 1251 { 0x0000, 0x0000 }, /* R1146 */
1254 { 0x0000, 0x0000, 0x0000 }, /* R1147 */ 1252 { 0x0000, 0x0000 }, /* R1147 */
1255 { 0x0000, 0x0000, 0x0000 }, /* R1148 */ 1253 { 0x0000, 0x0000 }, /* R1148 */
1256 { 0x0000, 0x0000, 0x0000 }, /* R1149 */ 1254 { 0x0000, 0x0000 }, /* R1149 */
1257 { 0x0000, 0x0000, 0x0000 }, /* R1150 */ 1255 { 0x0000, 0x0000 }, /* R1150 */
1258 { 0x0000, 0x0000, 0x0000 }, /* R1151 */ 1256 { 0x0000, 0x0000 }, /* R1151 */
1259 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */ 1257 { 0xFFFF, 0xFFFF }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
1260 { 0xFFC0, 0xFFC0, 0x0000 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */ 1258 { 0xFFC0, 0xFFC0 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
1261 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1154 - AIF1 DAC1 EQ Band 1 A */ 1259 { 0xFFFF, 0xFFFF }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
1262 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */ 1260 { 0xFFFF, 0xFFFF }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
1263 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */ 1261 { 0xFFFF, 0xFFFF }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
1264 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */ 1262 { 0xFFFF, 0xFFFF }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
1265 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */ 1263 { 0xFFFF, 0xFFFF }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
1266 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */ 1264 { 0xFFFF, 0xFFFF }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
1267 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */ 1265 { 0xFFFF, 0xFFFF }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
1268 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */ 1266 { 0xFFFF, 0xFFFF }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
1269 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */ 1267 { 0xFFFF, 0xFFFF }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
1270 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */ 1268 { 0xFFFF, 0xFFFF }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
1271 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */ 1269 { 0xFFFF, 0xFFFF }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
1272 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1165 - AIF1 DAC1 EQ Band 4 A */ 1270 { 0xFFFF, 0xFFFF }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
1273 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */ 1271 { 0xFFFF, 0xFFFF }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
1274 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1167 - AIF1 DAC1 EQ Band 4 C */ 1272 { 0xFFFF, 0xFFFF }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
1275 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */ 1273 { 0xFFFF, 0xFFFF }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
1276 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */ 1274 { 0xFFFF, 0xFFFF }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
1277 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */ 1275 { 0xFFFF, 0xFFFF }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
1278 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */ 1276 { 0xFFFF, 0xFFFF }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
1279 { 0x0000, 0x0000, 0x0000 }, /* R1172 */ 1277 { 0x0000, 0x0000 }, /* R1172 */
1280 { 0x0000, 0x0000, 0x0000 }, /* R1173 */ 1278 { 0x0000, 0x0000 }, /* R1173 */
1281 { 0x0000, 0x0000, 0x0000 }, /* R1174 */ 1279 { 0x0000, 0x0000 }, /* R1174 */
1282 { 0x0000, 0x0000, 0x0000 }, /* R1175 */ 1280 { 0x0000, 0x0000 }, /* R1175 */
1283 { 0x0000, 0x0000, 0x0000 }, /* R1176 */ 1281 { 0x0000, 0x0000 }, /* R1176 */
1284 { 0x0000, 0x0000, 0x0000 }, /* R1177 */ 1282 { 0x0000, 0x0000 }, /* R1177 */
1285 { 0x0000, 0x0000, 0x0000 }, /* R1178 */ 1283 { 0x0000, 0x0000 }, /* R1178 */
1286 { 0x0000, 0x0000, 0x0000 }, /* R1179 */ 1284 { 0x0000, 0x0000 }, /* R1179 */
1287 { 0x0000, 0x0000, 0x0000 }, /* R1180 */ 1285 { 0x0000, 0x0000 }, /* R1180 */
1288 { 0x0000, 0x0000, 0x0000 }, /* R1181 */ 1286 { 0x0000, 0x0000 }, /* R1181 */
1289 { 0x0000, 0x0000, 0x0000 }, /* R1182 */ 1287 { 0x0000, 0x0000 }, /* R1182 */
1290 { 0x0000, 0x0000, 0x0000 }, /* R1183 */ 1288 { 0x0000, 0x0000 }, /* R1183 */
1291 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */ 1289 { 0xFFFF, 0xFFFF }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
1292 { 0xFFC0, 0xFFC0, 0x0000 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */ 1290 { 0xFFC0, 0xFFC0 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
1293 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1186 - AIF1 DAC2 EQ Band 1 A */ 1291 { 0xFFFF, 0xFFFF }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
1294 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */ 1292 { 0xFFFF, 0xFFFF }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
1295 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */ 1293 { 0xFFFF, 0xFFFF }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
1296 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */ 1294 { 0xFFFF, 0xFFFF }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
1297 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */ 1295 { 0xFFFF, 0xFFFF }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
1298 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */ 1296 { 0xFFFF, 0xFFFF }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
1299 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */ 1297 { 0xFFFF, 0xFFFF }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
1300 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */ 1298 { 0xFFFF, 0xFFFF }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
1301 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */ 1299 { 0xFFFF, 0xFFFF }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
1302 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */ 1300 { 0xFFFF, 0xFFFF }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
1303 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */ 1301 { 0xFFFF, 0xFFFF }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
1304 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1197 - AIF1 DAC2 EQ Band 4 A */ 1302 { 0xFFFF, 0xFFFF }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
1305 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */ 1303 { 0xFFFF, 0xFFFF }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
1306 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1199 - AIF1 DAC2 EQ Band 4 C */ 1304 { 0xFFFF, 0xFFFF }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
1307 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */ 1305 { 0xFFFF, 0xFFFF }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
1308 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */ 1306 { 0xFFFF, 0xFFFF }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
1309 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */ 1307 { 0xFFFF, 0xFFFF }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
1310 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */ 1308 { 0xFFFF, 0xFFFF }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
1311 { 0x0000, 0x0000, 0x0000 }, /* R1204 */ 1309 { 0x0000, 0x0000 }, /* R1204 */
1312 { 0x0000, 0x0000, 0x0000 }, /* R1205 */ 1310 { 0x0000, 0x0000 }, /* R1205 */
1313 { 0x0000, 0x0000, 0x0000 }, /* R1206 */ 1311 { 0x0000, 0x0000 }, /* R1206 */
1314 { 0x0000, 0x0000, 0x0000 }, /* R1207 */ 1312 { 0x0000, 0x0000 }, /* R1207 */
1315 { 0x0000, 0x0000, 0x0000 }, /* R1208 */ 1313 { 0x0000, 0x0000 }, /* R1208 */
1316 { 0x0000, 0x0000, 0x0000 }, /* R1209 */ 1314 { 0x0000, 0x0000 }, /* R1209 */
1317 { 0x0000, 0x0000, 0x0000 }, /* R1210 */ 1315 { 0x0000, 0x0000 }, /* R1210 */
1318 { 0x0000, 0x0000, 0x0000 }, /* R1211 */ 1316 { 0x0000, 0x0000 }, /* R1211 */
1319 { 0x0000, 0x0000, 0x0000 }, /* R1212 */ 1317 { 0x0000, 0x0000 }, /* R1212 */
1320 { 0x0000, 0x0000, 0x0000 }, /* R1213 */ 1318 { 0x0000, 0x0000 }, /* R1213 */
1321 { 0x0000, 0x0000, 0x0000 }, /* R1214 */ 1319 { 0x0000, 0x0000 }, /* R1214 */
1322 { 0x0000, 0x0000, 0x0000 }, /* R1215 */ 1320 { 0x0000, 0x0000 }, /* R1215 */
1323 { 0x0000, 0x0000, 0x0000 }, /* R1216 */ 1321 { 0x0000, 0x0000 }, /* R1216 */
1324 { 0x0000, 0x0000, 0x0000 }, /* R1217 */ 1322 { 0x0000, 0x0000 }, /* R1217 */
1325 { 0x0000, 0x0000, 0x0000 }, /* R1218 */ 1323 { 0x0000, 0x0000 }, /* R1218 */
1326 { 0x0000, 0x0000, 0x0000 }, /* R1219 */ 1324 { 0x0000, 0x0000 }, /* R1219 */
1327 { 0x0000, 0x0000, 0x0000 }, /* R1220 */ 1325 { 0x0000, 0x0000 }, /* R1220 */
1328 { 0x0000, 0x0000, 0x0000 }, /* R1221 */ 1326 { 0x0000, 0x0000 }, /* R1221 */
1329 { 0x0000, 0x0000, 0x0000 }, /* R1222 */ 1327 { 0x0000, 0x0000 }, /* R1222 */
1330 { 0x0000, 0x0000, 0x0000 }, /* R1223 */ 1328 { 0x0000, 0x0000 }, /* R1223 */
1331 { 0x0000, 0x0000, 0x0000 }, /* R1224 */ 1329 { 0x0000, 0x0000 }, /* R1224 */
1332 { 0x0000, 0x0000, 0x0000 }, /* R1225 */ 1330 { 0x0000, 0x0000 }, /* R1225 */
1333 { 0x0000, 0x0000, 0x0000 }, /* R1226 */ 1331 { 0x0000, 0x0000 }, /* R1226 */
1334 { 0x0000, 0x0000, 0x0000 }, /* R1227 */ 1332 { 0x0000, 0x0000 }, /* R1227 */
1335 { 0x0000, 0x0000, 0x0000 }, /* R1228 */ 1333 { 0x0000, 0x0000 }, /* R1228 */
1336 { 0x0000, 0x0000, 0x0000 }, /* R1229 */ 1334 { 0x0000, 0x0000 }, /* R1229 */
1337 { 0x0000, 0x0000, 0x0000 }, /* R1230 */ 1335 { 0x0000, 0x0000 }, /* R1230 */
1338 { 0x0000, 0x0000, 0x0000 }, /* R1231 */ 1336 { 0x0000, 0x0000 }, /* R1231 */
1339 { 0x0000, 0x0000, 0x0000 }, /* R1232 */ 1337 { 0x0000, 0x0000 }, /* R1232 */
1340 { 0x0000, 0x0000, 0x0000 }, /* R1233 */ 1338 { 0x0000, 0x0000 }, /* R1233 */
1341 { 0x0000, 0x0000, 0x0000 }, /* R1234 */ 1339 { 0x0000, 0x0000 }, /* R1234 */
1342 { 0x0000, 0x0000, 0x0000 }, /* R1235 */ 1340 { 0x0000, 0x0000 }, /* R1235 */
1343 { 0x0000, 0x0000, 0x0000 }, /* R1236 */ 1341 { 0x0000, 0x0000 }, /* R1236 */
1344 { 0x0000, 0x0000, 0x0000 }, /* R1237 */ 1342 { 0x0000, 0x0000 }, /* R1237 */
1345 { 0x0000, 0x0000, 0x0000 }, /* R1238 */ 1343 { 0x0000, 0x0000 }, /* R1238 */
1346 { 0x0000, 0x0000, 0x0000 }, /* R1239 */ 1344 { 0x0000, 0x0000 }, /* R1239 */
1347 { 0x0000, 0x0000, 0x0000 }, /* R1240 */ 1345 { 0x0000, 0x0000 }, /* R1240 */
1348 { 0x0000, 0x0000, 0x0000 }, /* R1241 */ 1346 { 0x0000, 0x0000 }, /* R1241 */
1349 { 0x0000, 0x0000, 0x0000 }, /* R1242 */ 1347 { 0x0000, 0x0000 }, /* R1242 */
1350 { 0x0000, 0x0000, 0x0000 }, /* R1243 */ 1348 { 0x0000, 0x0000 }, /* R1243 */
1351 { 0x0000, 0x0000, 0x0000 }, /* R1244 */ 1349 { 0x0000, 0x0000 }, /* R1244 */
1352 { 0x0000, 0x0000, 0x0000 }, /* R1245 */ 1350 { 0x0000, 0x0000 }, /* R1245 */
1353 { 0x0000, 0x0000, 0x0000 }, /* R1246 */ 1351 { 0x0000, 0x0000 }, /* R1246 */
1354 { 0x0000, 0x0000, 0x0000 }, /* R1247 */ 1352 { 0x0000, 0x0000 }, /* R1247 */
1355 { 0x0000, 0x0000, 0x0000 }, /* R1248 */ 1353 { 0x0000, 0x0000 }, /* R1248 */
1356 { 0x0000, 0x0000, 0x0000 }, /* R1249 */ 1354 { 0x0000, 0x0000 }, /* R1249 */
1357 { 0x0000, 0x0000, 0x0000 }, /* R1250 */ 1355 { 0x0000, 0x0000 }, /* R1250 */
1358 { 0x0000, 0x0000, 0x0000 }, /* R1251 */ 1356 { 0x0000, 0x0000 }, /* R1251 */
1359 { 0x0000, 0x0000, 0x0000 }, /* R1252 */ 1357 { 0x0000, 0x0000 }, /* R1252 */
1360 { 0x0000, 0x0000, 0x0000 }, /* R1253 */ 1358 { 0x0000, 0x0000 }, /* R1253 */
1361 { 0x0000, 0x0000, 0x0000 }, /* R1254 */ 1359 { 0x0000, 0x0000 }, /* R1254 */
1362 { 0x0000, 0x0000, 0x0000 }, /* R1255 */ 1360 { 0x0000, 0x0000 }, /* R1255 */
1363 { 0x0000, 0x0000, 0x0000 }, /* R1256 */ 1361 { 0x0000, 0x0000 }, /* R1256 */
1364 { 0x0000, 0x0000, 0x0000 }, /* R1257 */ 1362 { 0x0000, 0x0000 }, /* R1257 */
1365 { 0x0000, 0x0000, 0x0000 }, /* R1258 */ 1363 { 0x0000, 0x0000 }, /* R1258 */
1366 { 0x0000, 0x0000, 0x0000 }, /* R1259 */ 1364 { 0x0000, 0x0000 }, /* R1259 */
1367 { 0x0000, 0x0000, 0x0000 }, /* R1260 */ 1365 { 0x0000, 0x0000 }, /* R1260 */
1368 { 0x0000, 0x0000, 0x0000 }, /* R1261 */ 1366 { 0x0000, 0x0000 }, /* R1261 */
1369 { 0x0000, 0x0000, 0x0000 }, /* R1262 */ 1367 { 0x0000, 0x0000 }, /* R1262 */
1370 { 0x0000, 0x0000, 0x0000 }, /* R1263 */ 1368 { 0x0000, 0x0000 }, /* R1263 */
1371 { 0x0000, 0x0000, 0x0000 }, /* R1264 */ 1369 { 0x0000, 0x0000 }, /* R1264 */
1372 { 0x0000, 0x0000, 0x0000 }, /* R1265 */ 1370 { 0x0000, 0x0000 }, /* R1265 */
1373 { 0x0000, 0x0000, 0x0000 }, /* R1266 */ 1371 { 0x0000, 0x0000 }, /* R1266 */
1374 { 0x0000, 0x0000, 0x0000 }, /* R1267 */ 1372 { 0x0000, 0x0000 }, /* R1267 */
1375 { 0x0000, 0x0000, 0x0000 }, /* R1268 */ 1373 { 0x0000, 0x0000 }, /* R1268 */
1376 { 0x0000, 0x0000, 0x0000 }, /* R1269 */ 1374 { 0x0000, 0x0000 }, /* R1269 */
1377 { 0x0000, 0x0000, 0x0000 }, /* R1270 */ 1375 { 0x0000, 0x0000 }, /* R1270 */
1378 { 0x0000, 0x0000, 0x0000 }, /* R1271 */ 1376 { 0x0000, 0x0000 }, /* R1271 */
1379 { 0x0000, 0x0000, 0x0000 }, /* R1272 */ 1377 { 0x0000, 0x0000 }, /* R1272 */
1380 { 0x0000, 0x0000, 0x0000 }, /* R1273 */ 1378 { 0x0000, 0x0000 }, /* R1273 */
1381 { 0x0000, 0x0000, 0x0000 }, /* R1274 */ 1379 { 0x0000, 0x0000 }, /* R1274 */
1382 { 0x0000, 0x0000, 0x0000 }, /* R1275 */ 1380 { 0x0000, 0x0000 }, /* R1275 */
1383 { 0x0000, 0x0000, 0x0000 }, /* R1276 */ 1381 { 0x0000, 0x0000 }, /* R1276 */
1384 { 0x0000, 0x0000, 0x0000 }, /* R1277 */ 1382 { 0x0000, 0x0000 }, /* R1277 */
1385 { 0x0000, 0x0000, 0x0000 }, /* R1278 */ 1383 { 0x0000, 0x0000 }, /* R1278 */
1386 { 0x0000, 0x0000, 0x0000 }, /* R1279 */ 1384 { 0x0000, 0x0000 }, /* R1279 */
1387 { 0x00FF, 0x01FF, 0x0000 }, /* R1280 - AIF2 ADC Left Volume */ 1385 { 0x00FF, 0x01FF }, /* R1280 - AIF2 ADC Left Volume */
1388 { 0x00FF, 0x01FF, 0x0000 }, /* R1281 - AIF2 ADC Right Volume */ 1386 { 0x00FF, 0x01FF }, /* R1281 - AIF2 ADC Right Volume */
1389 { 0x00FF, 0x01FF, 0x0000 }, /* R1282 - AIF2 DAC Left Volume */ 1387 { 0x00FF, 0x01FF }, /* R1282 - AIF2 DAC Left Volume */
1390 { 0x00FF, 0x01FF, 0x0000 }, /* R1283 - AIF2 DAC Right Volume */ 1388 { 0x00FF, 0x01FF }, /* R1283 - AIF2 DAC Right Volume */
1391 { 0x0000, 0x0000, 0x0000 }, /* R1284 */ 1389 { 0x0000, 0x0000 }, /* R1284 */
1392 { 0x0000, 0x0000, 0x0000 }, /* R1285 */ 1390 { 0x0000, 0x0000 }, /* R1285 */
1393 { 0x0000, 0x0000, 0x0000 }, /* R1286 */ 1391 { 0x0000, 0x0000 }, /* R1286 */
1394 { 0x0000, 0x0000, 0x0000 }, /* R1287 */ 1392 { 0x0000, 0x0000 }, /* R1287 */
1395 { 0x0000, 0x0000, 0x0000 }, /* R1288 */ 1393 { 0x0000, 0x0000 }, /* R1288 */
1396 { 0x0000, 0x0000, 0x0000 }, /* R1289 */ 1394 { 0x0000, 0x0000 }, /* R1289 */
1397 { 0x0000, 0x0000, 0x0000 }, /* R1290 */ 1395 { 0x0000, 0x0000 }, /* R1290 */
1398 { 0x0000, 0x0000, 0x0000 }, /* R1291 */ 1396 { 0x0000, 0x0000 }, /* R1291 */
1399 { 0x0000, 0x0000, 0x0000 }, /* R1292 */ 1397 { 0x0000, 0x0000 }, /* R1292 */
1400 { 0x0000, 0x0000, 0x0000 }, /* R1293 */ 1398 { 0x0000, 0x0000 }, /* R1293 */
1401 { 0x0000, 0x0000, 0x0000 }, /* R1294 */ 1399 { 0x0000, 0x0000 }, /* R1294 */
1402 { 0x0000, 0x0000, 0x0000 }, /* R1295 */ 1400 { 0x0000, 0x0000 }, /* R1295 */
1403 { 0xF800, 0xF800, 0x0000 }, /* R1296 - AIF2 ADC Filters */ 1401 { 0xF800, 0xF800 }, /* R1296 - AIF2 ADC Filters */
1404 { 0x0000, 0x0000, 0x0000 }, /* R1297 */ 1402 { 0x0000, 0x0000 }, /* R1297 */
1405 { 0x0000, 0x0000, 0x0000 }, /* R1298 */ 1403 { 0x0000, 0x0000 }, /* R1298 */
1406 { 0x0000, 0x0000, 0x0000 }, /* R1299 */ 1404 { 0x0000, 0x0000 }, /* R1299 */
1407 { 0x0000, 0x0000, 0x0000 }, /* R1300 */ 1405 { 0x0000, 0x0000 }, /* R1300 */
1408 { 0x0000, 0x0000, 0x0000 }, /* R1301 */ 1406 { 0x0000, 0x0000 }, /* R1301 */
1409 { 0x0000, 0x0000, 0x0000 }, /* R1302 */ 1407 { 0x0000, 0x0000 }, /* R1302 */
1410 { 0x0000, 0x0000, 0x0000 }, /* R1303 */ 1408 { 0x0000, 0x0000 }, /* R1303 */
1411 { 0x0000, 0x0000, 0x0000 }, /* R1304 */ 1409 { 0x0000, 0x0000 }, /* R1304 */
1412 { 0x0000, 0x0000, 0x0000 }, /* R1305 */ 1410 { 0x0000, 0x0000 }, /* R1305 */
1413 { 0x0000, 0x0000, 0x0000 }, /* R1306 */ 1411 { 0x0000, 0x0000 }, /* R1306 */
1414 { 0x0000, 0x0000, 0x0000 }, /* R1307 */ 1412 { 0x0000, 0x0000 }, /* R1307 */
1415 { 0x0000, 0x0000, 0x0000 }, /* R1308 */ 1413 { 0x0000, 0x0000 }, /* R1308 */
1416 { 0x0000, 0x0000, 0x0000 }, /* R1309 */ 1414 { 0x0000, 0x0000 }, /* R1309 */
1417 { 0x0000, 0x0000, 0x0000 }, /* R1310 */ 1415 { 0x0000, 0x0000 }, /* R1310 */
1418 { 0x0000, 0x0000, 0x0000 }, /* R1311 */ 1416 { 0x0000, 0x0000 }, /* R1311 */
1419 { 0x02B6, 0x02B6, 0x0000 }, /* R1312 - AIF2 DAC Filters (1) */ 1417 { 0x02B6, 0x02B6 }, /* R1312 - AIF2 DAC Filters (1) */
1420 { 0x3F00, 0x3F00, 0x0000 }, /* R1313 - AIF2 DAC Filters (2) */ 1418 { 0x3F00, 0x3F00 }, /* R1313 - AIF2 DAC Filters (2) */
1421 { 0x0000, 0x0000, 0x0000 }, /* R1314 */ 1419 { 0x0000, 0x0000 }, /* R1314 */
1422 { 0x0000, 0x0000, 0x0000 }, /* R1315 */ 1420 { 0x0000, 0x0000 }, /* R1315 */
1423 { 0x0000, 0x0000, 0x0000 }, /* R1316 */ 1421 { 0x0000, 0x0000 }, /* R1316 */
1424 { 0x0000, 0x0000, 0x0000 }, /* R1317 */ 1422 { 0x0000, 0x0000 }, /* R1317 */
1425 { 0x0000, 0x0000, 0x0000 }, /* R1318 */ 1423 { 0x0000, 0x0000 }, /* R1318 */
1426 { 0x0000, 0x0000, 0x0000 }, /* R1319 */ 1424 { 0x0000, 0x0000 }, /* R1319 */
1427 { 0x0000, 0x0000, 0x0000 }, /* R1320 */ 1425 { 0x0000, 0x0000 }, /* R1320 */
1428 { 0x0000, 0x0000, 0x0000 }, /* R1321 */ 1426 { 0x0000, 0x0000 }, /* R1321 */
1429 { 0x0000, 0x0000, 0x0000 }, /* R1322 */ 1427 { 0x0000, 0x0000 }, /* R1322 */
1430 { 0x0000, 0x0000, 0x0000 }, /* R1323 */ 1428 { 0x0000, 0x0000 }, /* R1323 */
1431 { 0x0000, 0x0000, 0x0000 }, /* R1324 */ 1429 { 0x0000, 0x0000 }, /* R1324 */
1432 { 0x0000, 0x0000, 0x0000 }, /* R1325 */ 1430 { 0x0000, 0x0000 }, /* R1325 */
1433 { 0x0000, 0x0000, 0x0000 }, /* R1326 */ 1431 { 0x0000, 0x0000 }, /* R1326 */
1434 { 0x0000, 0x0000, 0x0000 }, /* R1327 */ 1432 { 0x0000, 0x0000 }, /* R1327 */
1435 { 0x0000, 0x0000, 0x0000 }, /* R1328 */ 1433 { 0x0000, 0x0000 }, /* R1328 */
1436 { 0x0000, 0x0000, 0x0000 }, /* R1329 */ 1434 { 0x0000, 0x0000 }, /* R1329 */
1437 { 0x0000, 0x0000, 0x0000 }, /* R1330 */ 1435 { 0x0000, 0x0000 }, /* R1330 */
1438 { 0x0000, 0x0000, 0x0000 }, /* R1331 */ 1436 { 0x0000, 0x0000 }, /* R1331 */
1439 { 0x0000, 0x0000, 0x0000 }, /* R1332 */ 1437 { 0x0000, 0x0000 }, /* R1332 */
1440 { 0x0000, 0x0000, 0x0000 }, /* R1333 */ 1438 { 0x0000, 0x0000 }, /* R1333 */
1441 { 0x0000, 0x0000, 0x0000 }, /* R1334 */ 1439 { 0x0000, 0x0000 }, /* R1334 */
1442 { 0x0000, 0x0000, 0x0000 }, /* R1335 */ 1440 { 0x0000, 0x0000 }, /* R1335 */
1443 { 0x0000, 0x0000, 0x0000 }, /* R1336 */ 1441 { 0x0000, 0x0000 }, /* R1336 */
1444 { 0x0000, 0x0000, 0x0000 }, /* R1337 */ 1442 { 0x0000, 0x0000 }, /* R1337 */
1445 { 0x0000, 0x0000, 0x0000 }, /* R1338 */ 1443 { 0x0000, 0x0000 }, /* R1338 */
1446 { 0x0000, 0x0000, 0x0000 }, /* R1339 */ 1444 { 0x0000, 0x0000 }, /* R1339 */
1447 { 0x0000, 0x0000, 0x0000 }, /* R1340 */ 1445 { 0x0000, 0x0000 }, /* R1340 */
1448 { 0x0000, 0x0000, 0x0000 }, /* R1341 */ 1446 { 0x0000, 0x0000 }, /* R1341 */
1449 { 0x0000, 0x0000, 0x0000 }, /* R1342 */ 1447 { 0x0000, 0x0000 }, /* R1342 */
1450 { 0x0000, 0x0000, 0x0000 }, /* R1343 */ 1448 { 0x0000, 0x0000 }, /* R1343 */
1451 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1344 - AIF2 DRC (1) */ 1449 { 0xFFFF, 0xFFFF }, /* R1344 - AIF2 DRC (1) */
1452 { 0x1FFF, 0x1FFF, 0x0000 }, /* R1345 - AIF2 DRC (2) */ 1450 { 0x1FFF, 0x1FFF }, /* R1345 - AIF2 DRC (2) */
1453 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1346 - AIF2 DRC (3) */ 1451 { 0xFFFF, 0xFFFF }, /* R1346 - AIF2 DRC (3) */
1454 { 0x07FF, 0x07FF, 0x0000 }, /* R1347 - AIF2 DRC (4) */ 1452 { 0x07FF, 0x07FF }, /* R1347 - AIF2 DRC (4) */
1455 { 0x03FF, 0x03FF, 0x0000 }, /* R1348 - AIF2 DRC (5) */ 1453 { 0x03FF, 0x03FF }, /* R1348 - AIF2 DRC (5) */
1456 { 0x0000, 0x0000, 0x0000 }, /* R1349 */ 1454 { 0x0000, 0x0000 }, /* R1349 */
1457 { 0x0000, 0x0000, 0x0000 }, /* R1350 */ 1455 { 0x0000, 0x0000 }, /* R1350 */
1458 { 0x0000, 0x0000, 0x0000 }, /* R1351 */ 1456 { 0x0000, 0x0000 }, /* R1351 */
1459 { 0x0000, 0x0000, 0x0000 }, /* R1352 */ 1457 { 0x0000, 0x0000 }, /* R1352 */
1460 { 0x0000, 0x0000, 0x0000 }, /* R1353 */ 1458 { 0x0000, 0x0000 }, /* R1353 */
1461 { 0x0000, 0x0000, 0x0000 }, /* R1354 */ 1459 { 0x0000, 0x0000 }, /* R1354 */
1462 { 0x0000, 0x0000, 0x0000 }, /* R1355 */ 1460 { 0x0000, 0x0000 }, /* R1355 */
1463 { 0x0000, 0x0000, 0x0000 }, /* R1356 */ 1461 { 0x0000, 0x0000 }, /* R1356 */
1464 { 0x0000, 0x0000, 0x0000 }, /* R1357 */ 1462 { 0x0000, 0x0000 }, /* R1357 */
1465 { 0x0000, 0x0000, 0x0000 }, /* R1358 */ 1463 { 0x0000, 0x0000 }, /* R1358 */
1466 { 0x0000, 0x0000, 0x0000 }, /* R1359 */ 1464 { 0x0000, 0x0000 }, /* R1359 */
1467 { 0x0000, 0x0000, 0x0000 }, /* R1360 */ 1465 { 0x0000, 0x0000 }, /* R1360 */
1468 { 0x0000, 0x0000, 0x0000 }, /* R1361 */ 1466 { 0x0000, 0x0000 }, /* R1361 */
1469 { 0x0000, 0x0000, 0x0000 }, /* R1362 */ 1467 { 0x0000, 0x0000 }, /* R1362 */
1470 { 0x0000, 0x0000, 0x0000 }, /* R1363 */ 1468 { 0x0000, 0x0000 }, /* R1363 */
1471 { 0x0000, 0x0000, 0x0000 }, /* R1364 */ 1469 { 0x0000, 0x0000 }, /* R1364 */
1472 { 0x0000, 0x0000, 0x0000 }, /* R1365 */ 1470 { 0x0000, 0x0000 }, /* R1365 */
1473 { 0x0000, 0x0000, 0x0000 }, /* R1366 */ 1471 { 0x0000, 0x0000 }, /* R1366 */
1474 { 0x0000, 0x0000, 0x0000 }, /* R1367 */ 1472 { 0x0000, 0x0000 }, /* R1367 */
1475 { 0x0000, 0x0000, 0x0000 }, /* R1368 */ 1473 { 0x0000, 0x0000 }, /* R1368 */
1476 { 0x0000, 0x0000, 0x0000 }, /* R1369 */ 1474 { 0x0000, 0x0000 }, /* R1369 */
1477 { 0x0000, 0x0000, 0x0000 }, /* R1370 */ 1475 { 0x0000, 0x0000 }, /* R1370 */
1478 { 0x0000, 0x0000, 0x0000 }, /* R1371 */ 1476 { 0x0000, 0x0000 }, /* R1371 */
1479 { 0x0000, 0x0000, 0x0000 }, /* R1372 */ 1477 { 0x0000, 0x0000 }, /* R1372 */
1480 { 0x0000, 0x0000, 0x0000 }, /* R1373 */ 1478 { 0x0000, 0x0000 }, /* R1373 */
1481 { 0x0000, 0x0000, 0x0000 }, /* R1374 */ 1479 { 0x0000, 0x0000 }, /* R1374 */
1482 { 0x0000, 0x0000, 0x0000 }, /* R1375 */ 1480 { 0x0000, 0x0000 }, /* R1375 */
1483 { 0x0000, 0x0000, 0x0000 }, /* R1376 */ 1481 { 0x0000, 0x0000 }, /* R1376 */
1484 { 0x0000, 0x0000, 0x0000 }, /* R1377 */ 1482 { 0x0000, 0x0000 }, /* R1377 */
1485 { 0x0000, 0x0000, 0x0000 }, /* R1378 */ 1483 { 0x0000, 0x0000 }, /* R1378 */
1486 { 0x0000, 0x0000, 0x0000 }, /* R1379 */ 1484 { 0x0000, 0x0000 }, /* R1379 */
1487 { 0x0000, 0x0000, 0x0000 }, /* R1380 */ 1485 { 0x0000, 0x0000 }, /* R1380 */
1488 { 0x0000, 0x0000, 0x0000 }, /* R1381 */ 1486 { 0x0000, 0x0000 }, /* R1381 */
1489 { 0x0000, 0x0000, 0x0000 }, /* R1382 */ 1487 { 0x0000, 0x0000 }, /* R1382 */
1490 { 0x0000, 0x0000, 0x0000 }, /* R1383 */ 1488 { 0x0000, 0x0000 }, /* R1383 */
1491 { 0x0000, 0x0000, 0x0000 }, /* R1384 */ 1489 { 0x0000, 0x0000 }, /* R1384 */
1492 { 0x0000, 0x0000, 0x0000 }, /* R1385 */ 1490 { 0x0000, 0x0000 }, /* R1385 */
1493 { 0x0000, 0x0000, 0x0000 }, /* R1386 */ 1491 { 0x0000, 0x0000 }, /* R1386 */
1494 { 0x0000, 0x0000, 0x0000 }, /* R1387 */ 1492 { 0x0000, 0x0000 }, /* R1387 */
1495 { 0x0000, 0x0000, 0x0000 }, /* R1388 */ 1493 { 0x0000, 0x0000 }, /* R1388 */
1496 { 0x0000, 0x0000, 0x0000 }, /* R1389 */ 1494 { 0x0000, 0x0000 }, /* R1389 */
1497 { 0x0000, 0x0000, 0x0000 }, /* R1390 */ 1495 { 0x0000, 0x0000 }, /* R1390 */
1498 { 0x0000, 0x0000, 0x0000 }, /* R1391 */ 1496 { 0x0000, 0x0000 }, /* R1391 */
1499 { 0x0000, 0x0000, 0x0000 }, /* R1392 */ 1497 { 0x0000, 0x0000 }, /* R1392 */
1500 { 0x0000, 0x0000, 0x0000 }, /* R1393 */ 1498 { 0x0000, 0x0000 }, /* R1393 */
1501 { 0x0000, 0x0000, 0x0000 }, /* R1394 */ 1499 { 0x0000, 0x0000 }, /* R1394 */
1502 { 0x0000, 0x0000, 0x0000 }, /* R1395 */ 1500 { 0x0000, 0x0000 }, /* R1395 */
1503 { 0x0000, 0x0000, 0x0000 }, /* R1396 */ 1501 { 0x0000, 0x0000 }, /* R1396 */
1504 { 0x0000, 0x0000, 0x0000 }, /* R1397 */ 1502 { 0x0000, 0x0000 }, /* R1397 */
1505 { 0x0000, 0x0000, 0x0000 }, /* R1398 */ 1503 { 0x0000, 0x0000 }, /* R1398 */
1506 { 0x0000, 0x0000, 0x0000 }, /* R1399 */ 1504 { 0x0000, 0x0000 }, /* R1399 */
1507 { 0x0000, 0x0000, 0x0000 }, /* R1400 */ 1505 { 0x0000, 0x0000 }, /* R1400 */
1508 { 0x0000, 0x0000, 0x0000 }, /* R1401 */ 1506 { 0x0000, 0x0000 }, /* R1401 */
1509 { 0x0000, 0x0000, 0x0000 }, /* R1402 */ 1507 { 0x0000, 0x0000 }, /* R1402 */
1510 { 0x0000, 0x0000, 0x0000 }, /* R1403 */ 1508 { 0x0000, 0x0000 }, /* R1403 */
1511 { 0x0000, 0x0000, 0x0000 }, /* R1404 */ 1509 { 0x0000, 0x0000 }, /* R1404 */
1512 { 0x0000, 0x0000, 0x0000 }, /* R1405 */ 1510 { 0x0000, 0x0000 }, /* R1405 */
1513 { 0x0000, 0x0000, 0x0000 }, /* R1406 */ 1511 { 0x0000, 0x0000 }, /* R1406 */
1514 { 0x0000, 0x0000, 0x0000 }, /* R1407 */ 1512 { 0x0000, 0x0000 }, /* R1407 */
1515 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1408 - AIF2 EQ Gains (1) */ 1513 { 0xFFFF, 0xFFFF }, /* R1408 - AIF2 EQ Gains (1) */
1516 { 0xFFC0, 0xFFC0, 0x0000 }, /* R1409 - AIF2 EQ Gains (2) */ 1514 { 0xFFC0, 0xFFC0 }, /* R1409 - AIF2 EQ Gains (2) */
1517 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1410 - AIF2 EQ Band 1 A */ 1515 { 0xFFFF, 0xFFFF }, /* R1410 - AIF2 EQ Band 1 A */
1518 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1411 - AIF2 EQ Band 1 B */ 1516 { 0xFFFF, 0xFFFF }, /* R1411 - AIF2 EQ Band 1 B */
1519 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1412 - AIF2 EQ Band 1 PG */ 1517 { 0xFFFF, 0xFFFF }, /* R1412 - AIF2 EQ Band 1 PG */
1520 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1413 - AIF2 EQ Band 2 A */ 1518 { 0xFFFF, 0xFFFF }, /* R1413 - AIF2 EQ Band 2 A */
1521 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1414 - AIF2 EQ Band 2 B */ 1519 { 0xFFFF, 0xFFFF }, /* R1414 - AIF2 EQ Band 2 B */
1522 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1415 - AIF2 EQ Band 2 C */ 1520 { 0xFFFF, 0xFFFF }, /* R1415 - AIF2 EQ Band 2 C */
1523 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1416 - AIF2 EQ Band 2 PG */ 1521 { 0xFFFF, 0xFFFF }, /* R1416 - AIF2 EQ Band 2 PG */
1524 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1417 - AIF2 EQ Band 3 A */ 1522 { 0xFFFF, 0xFFFF }, /* R1417 - AIF2 EQ Band 3 A */
1525 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1418 - AIF2 EQ Band 3 B */ 1523 { 0xFFFF, 0xFFFF }, /* R1418 - AIF2 EQ Band 3 B */
1526 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1419 - AIF2 EQ Band 3 C */ 1524 { 0xFFFF, 0xFFFF }, /* R1419 - AIF2 EQ Band 3 C */
1527 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1420 - AIF2 EQ Band 3 PG */ 1525 { 0xFFFF, 0xFFFF }, /* R1420 - AIF2 EQ Band 3 PG */
1528 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1421 - AIF2 EQ Band 4 A */ 1526 { 0xFFFF, 0xFFFF }, /* R1421 - AIF2 EQ Band 4 A */
1529 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1422 - AIF2 EQ Band 4 B */ 1527 { 0xFFFF, 0xFFFF }, /* R1422 - AIF2 EQ Band 4 B */
1530 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1423 - AIF2 EQ Band 4 C */ 1528 { 0xFFFF, 0xFFFF }, /* R1423 - AIF2 EQ Band 4 C */
1531 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1424 - AIF2 EQ Band 4 PG */ 1529 { 0xFFFF, 0xFFFF }, /* R1424 - AIF2 EQ Band 4 PG */
1532 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1425 - AIF2 EQ Band 5 A */ 1530 { 0xFFFF, 0xFFFF }, /* R1425 - AIF2 EQ Band 5 A */
1533 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1426 - AIF2 EQ Band 5 B */ 1531 { 0xFFFF, 0xFFFF }, /* R1426 - AIF2 EQ Band 5 B */
1534 { 0xFFFF, 0xFFFF, 0x0000 }, /* R1427 - AIF2 EQ Band 5 PG */ 1532 { 0xFFFF, 0xFFFF }, /* R1427 - AIF2 EQ Band 5 PG */
1535 { 0x0000, 0x0000, 0x0000 }, /* R1428 */ 1533 { 0x0000, 0x0000 }, /* R1428 */
1536 { 0x0000, 0x0000, 0x0000 }, /* R1429 */ 1534 { 0x0000, 0x0000 }, /* R1429 */
1537 { 0x0000, 0x0000, 0x0000 }, /* R1430 */ 1535 { 0x0000, 0x0000 }, /* R1430 */
1538 { 0x0000, 0x0000, 0x0000 }, /* R1431 */ 1536 { 0x0000, 0x0000 }, /* R1431 */
1539 { 0x0000, 0x0000, 0x0000 }, /* R1432 */ 1537 { 0x0000, 0x0000 }, /* R1432 */
1540 { 0x0000, 0x0000, 0x0000 }, /* R1433 */ 1538 { 0x0000, 0x0000 }, /* R1433 */
1541 { 0x0000, 0x0000, 0x0000 }, /* R1434 */ 1539 { 0x0000, 0x0000 }, /* R1434 */
1542 { 0x0000, 0x0000, 0x0000 }, /* R1435 */ 1540 { 0x0000, 0x0000 }, /* R1435 */
1543 { 0x0000, 0x0000, 0x0000 }, /* R1436 */ 1541 { 0x0000, 0x0000 }, /* R1436 */
1544 { 0x0000, 0x0000, 0x0000 }, /* R1437 */ 1542 { 0x0000, 0x0000 }, /* R1437 */
1545 { 0x0000, 0x0000, 0x0000 }, /* R1438 */ 1543 { 0x0000, 0x0000 }, /* R1438 */
1546 { 0x0000, 0x0000, 0x0000 }, /* R1439 */ 1544 { 0x0000, 0x0000 }, /* R1439 */
1547 { 0x0000, 0x0000, 0x0000 }, /* R1440 */ 1545 { 0x0000, 0x0000 }, /* R1440 */
1548 { 0x0000, 0x0000, 0x0000 }, /* R1441 */ 1546 { 0x0000, 0x0000 }, /* R1441 */
1549 { 0x0000, 0x0000, 0x0000 }, /* R1442 */ 1547 { 0x0000, 0x0000 }, /* R1442 */
1550 { 0x0000, 0x0000, 0x0000 }, /* R1443 */ 1548 { 0x0000, 0x0000 }, /* R1443 */
1551 { 0x0000, 0x0000, 0x0000 }, /* R1444 */ 1549 { 0x0000, 0x0000 }, /* R1444 */
1552 { 0x0000, 0x0000, 0x0000 }, /* R1445 */ 1550 { 0x0000, 0x0000 }, /* R1445 */
1553 { 0x0000, 0x0000, 0x0000 }, /* R1446 */ 1551 { 0x0000, 0x0000 }, /* R1446 */
1554 { 0x0000, 0x0000, 0x0000 }, /* R1447 */ 1552 { 0x0000, 0x0000 }, /* R1447 */
1555 { 0x0000, 0x0000, 0x0000 }, /* R1448 */ 1553 { 0x0000, 0x0000 }, /* R1448 */
1556 { 0x0000, 0x0000, 0x0000 }, /* R1449 */ 1554 { 0x0000, 0x0000 }, /* R1449 */
1557 { 0x0000, 0x0000, 0x0000 }, /* R1450 */ 1555 { 0x0000, 0x0000 }, /* R1450 */
1558 { 0x0000, 0x0000, 0x0000 }, /* R1451 */ 1556 { 0x0000, 0x0000 }, /* R1451 */
1559 { 0x0000, 0x0000, 0x0000 }, /* R1452 */ 1557 { 0x0000, 0x0000 }, /* R1452 */
1560 { 0x0000, 0x0000, 0x0000 }, /* R1453 */ 1558 { 0x0000, 0x0000 }, /* R1453 */
1561 { 0x0000, 0x0000, 0x0000 }, /* R1454 */ 1559 { 0x0000, 0x0000 }, /* R1454 */
1562 { 0x0000, 0x0000, 0x0000 }, /* R1455 */ 1560 { 0x0000, 0x0000 }, /* R1455 */
1563 { 0x0000, 0x0000, 0x0000 }, /* R1456 */ 1561 { 0x0000, 0x0000 }, /* R1456 */
1564 { 0x0000, 0x0000, 0x0000 }, /* R1457 */ 1562 { 0x0000, 0x0000 }, /* R1457 */
1565 { 0x0000, 0x0000, 0x0000 }, /* R1458 */ 1563 { 0x0000, 0x0000 }, /* R1458 */
1566 { 0x0000, 0x0000, 0x0000 }, /* R1459 */ 1564 { 0x0000, 0x0000 }, /* R1459 */
1567 { 0x0000, 0x0000, 0x0000 }, /* R1460 */ 1565 { 0x0000, 0x0000 }, /* R1460 */
1568 { 0x0000, 0x0000, 0x0000 }, /* R1461 */ 1566 { 0x0000, 0x0000 }, /* R1461 */
1569 { 0x0000, 0x0000, 0x0000 }, /* R1462 */ 1567 { 0x0000, 0x0000 }, /* R1462 */
1570 { 0x0000, 0x0000, 0x0000 }, /* R1463 */ 1568 { 0x0000, 0x0000 }, /* R1463 */
1571 { 0x0000, 0x0000, 0x0000 }, /* R1464 */ 1569 { 0x0000, 0x0000 }, /* R1464 */
1572 { 0x0000, 0x0000, 0x0000 }, /* R1465 */ 1570 { 0x0000, 0x0000 }, /* R1465 */
1573 { 0x0000, 0x0000, 0x0000 }, /* R1466 */ 1571 { 0x0000, 0x0000 }, /* R1466 */
1574 { 0x0000, 0x0000, 0x0000 }, /* R1467 */ 1572 { 0x0000, 0x0000 }, /* R1467 */
1575 { 0x0000, 0x0000, 0x0000 }, /* R1468 */ 1573 { 0x0000, 0x0000 }, /* R1468 */
1576 { 0x0000, 0x0000, 0x0000 }, /* R1469 */ 1574 { 0x0000, 0x0000 }, /* R1469 */
1577 { 0x0000, 0x0000, 0x0000 }, /* R1470 */ 1575 { 0x0000, 0x0000 }, /* R1470 */
1578 { 0x0000, 0x0000, 0x0000 }, /* R1471 */ 1576 { 0x0000, 0x0000 }, /* R1471 */
1579 { 0x0000, 0x0000, 0x0000 }, /* R1472 */ 1577 { 0x0000, 0x0000 }, /* R1472 */
1580 { 0x0000, 0x0000, 0x0000 }, /* R1473 */ 1578 { 0x0000, 0x0000 }, /* R1473 */
1581 { 0x0000, 0x0000, 0x0000 }, /* R1474 */ 1579 { 0x0000, 0x0000 }, /* R1474 */
1582 { 0x0000, 0x0000, 0x0000 }, /* R1475 */ 1580 { 0x0000, 0x0000 }, /* R1475 */
1583 { 0x0000, 0x0000, 0x0000 }, /* R1476 */ 1581 { 0x0000, 0x0000 }, /* R1476 */
1584 { 0x0000, 0x0000, 0x0000 }, /* R1477 */ 1582 { 0x0000, 0x0000 }, /* R1477 */
1585 { 0x0000, 0x0000, 0x0000 }, /* R1478 */ 1583 { 0x0000, 0x0000 }, /* R1478 */
1586 { 0x0000, 0x0000, 0x0000 }, /* R1479 */ 1584 { 0x0000, 0x0000 }, /* R1479 */
1587 { 0x0000, 0x0000, 0x0000 }, /* R1480 */ 1585 { 0x0000, 0x0000 }, /* R1480 */
1588 { 0x0000, 0x0000, 0x0000 }, /* R1481 */ 1586 { 0x0000, 0x0000 }, /* R1481 */
1589 { 0x0000, 0x0000, 0x0000 }, /* R1482 */ 1587 { 0x0000, 0x0000 }, /* R1482 */
1590 { 0x0000, 0x0000, 0x0000 }, /* R1483 */ 1588 { 0x0000, 0x0000 }, /* R1483 */
1591 { 0x0000, 0x0000, 0x0000 }, /* R1484 */ 1589 { 0x0000, 0x0000 }, /* R1484 */
1592 { 0x0000, 0x0000, 0x0000 }, /* R1485 */ 1590 { 0x0000, 0x0000 }, /* R1485 */
1593 { 0x0000, 0x0000, 0x0000 }, /* R1486 */ 1591 { 0x0000, 0x0000 }, /* R1486 */
1594 { 0x0000, 0x0000, 0x0000 }, /* R1487 */ 1592 { 0x0000, 0x0000 }, /* R1487 */
1595 { 0x0000, 0x0000, 0x0000 }, /* R1488 */ 1593 { 0x0000, 0x0000 }, /* R1488 */
1596 { 0x0000, 0x0000, 0x0000 }, /* R1489 */ 1594 { 0x0000, 0x0000 }, /* R1489 */
1597 { 0x0000, 0x0000, 0x0000 }, /* R1490 */ 1595 { 0x0000, 0x0000 }, /* R1490 */
1598 { 0x0000, 0x0000, 0x0000 }, /* R1491 */ 1596 { 0x0000, 0x0000 }, /* R1491 */
1599 { 0x0000, 0x0000, 0x0000 }, /* R1492 */ 1597 { 0x0000, 0x0000 }, /* R1492 */
1600 { 0x0000, 0x0000, 0x0000 }, /* R1493 */ 1598 { 0x0000, 0x0000 }, /* R1493 */
1601 { 0x0000, 0x0000, 0x0000 }, /* R1494 */ 1599 { 0x0000, 0x0000 }, /* R1494 */
1602 { 0x0000, 0x0000, 0x0000 }, /* R1495 */ 1600 { 0x0000, 0x0000 }, /* R1495 */
1603 { 0x0000, 0x0000, 0x0000 }, /* R1496 */ 1601 { 0x0000, 0x0000 }, /* R1496 */
1604 { 0x0000, 0x0000, 0x0000 }, /* R1497 */ 1602 { 0x0000, 0x0000 }, /* R1497 */
1605 { 0x0000, 0x0000, 0x0000 }, /* R1498 */ 1603 { 0x0000, 0x0000 }, /* R1498 */
1606 { 0x0000, 0x0000, 0x0000 }, /* R1499 */ 1604 { 0x0000, 0x0000 }, /* R1499 */
1607 { 0x0000, 0x0000, 0x0000 }, /* R1500 */ 1605 { 0x0000, 0x0000 }, /* R1500 */
1608 { 0x0000, 0x0000, 0x0000 }, /* R1501 */ 1606 { 0x0000, 0x0000 }, /* R1501 */
1609 { 0x0000, 0x0000, 0x0000 }, /* R1502 */ 1607 { 0x0000, 0x0000 }, /* R1502 */
1610 { 0x0000, 0x0000, 0x0000 }, /* R1503 */ 1608 { 0x0000, 0x0000 }, /* R1503 */
1611 { 0x0000, 0x0000, 0x0000 }, /* R1504 */ 1609 { 0x0000, 0x0000 }, /* R1504 */
1612 { 0x0000, 0x0000, 0x0000 }, /* R1505 */ 1610 { 0x0000, 0x0000 }, /* R1505 */
1613 { 0x0000, 0x0000, 0x0000 }, /* R1506 */ 1611 { 0x0000, 0x0000 }, /* R1506 */
1614 { 0x0000, 0x0000, 0x0000 }, /* R1507 */ 1612 { 0x0000, 0x0000 }, /* R1507 */
1615 { 0x0000, 0x0000, 0x0000 }, /* R1508 */ 1613 { 0x0000, 0x0000 }, /* R1508 */
1616 { 0x0000, 0x0000, 0x0000 }, /* R1509 */ 1614 { 0x0000, 0x0000 }, /* R1509 */
1617 { 0x0000, 0x0000, 0x0000 }, /* R1510 */ 1615 { 0x0000, 0x0000 }, /* R1510 */
1618 { 0x0000, 0x0000, 0x0000 }, /* R1511 */ 1616 { 0x0000, 0x0000 }, /* R1511 */
1619 { 0x0000, 0x0000, 0x0000 }, /* R1512 */ 1617 { 0x0000, 0x0000 }, /* R1512 */
1620 { 0x0000, 0x0000, 0x0000 }, /* R1513 */ 1618 { 0x0000, 0x0000 }, /* R1513 */
1621 { 0x0000, 0x0000, 0x0000 }, /* R1514 */ 1619 { 0x0000, 0x0000 }, /* R1514 */
1622 { 0x0000, 0x0000, 0x0000 }, /* R1515 */ 1620 { 0x0000, 0x0000 }, /* R1515 */
1623 { 0x0000, 0x0000, 0x0000 }, /* R1516 */ 1621 { 0x0000, 0x0000 }, /* R1516 */
1624 { 0x0000, 0x0000, 0x0000 }, /* R1517 */ 1622 { 0x0000, 0x0000 }, /* R1517 */
1625 { 0x0000, 0x0000, 0x0000 }, /* R1518 */ 1623 { 0x0000, 0x0000 }, /* R1518 */
1626 { 0x0000, 0x0000, 0x0000 }, /* R1519 */ 1624 { 0x0000, 0x0000 }, /* R1519 */
1627 { 0x0000, 0x0000, 0x0000 }, /* R1520 */ 1625 { 0x0000, 0x0000 }, /* R1520 */
1628 { 0x0000, 0x0000, 0x0000 }, /* R1521 */ 1626 { 0x0000, 0x0000 }, /* R1521 */
1629 { 0x0000, 0x0000, 0x0000 }, /* R1522 */ 1627 { 0x0000, 0x0000 }, /* R1522 */
1630 { 0x0000, 0x0000, 0x0000 }, /* R1523 */ 1628 { 0x0000, 0x0000 }, /* R1523 */
1631 { 0x0000, 0x0000, 0x0000 }, /* R1524 */ 1629 { 0x0000, 0x0000 }, /* R1524 */
1632 { 0x0000, 0x0000, 0x0000 }, /* R1525 */ 1630 { 0x0000, 0x0000 }, /* R1525 */
1633 { 0x0000, 0x0000, 0x0000 }, /* R1526 */ 1631 { 0x0000, 0x0000 }, /* R1526 */
1634 { 0x0000, 0x0000, 0x0000 }, /* R1527 */ 1632 { 0x0000, 0x0000 }, /* R1527 */
1635 { 0x0000, 0x0000, 0x0000 }, /* R1528 */ 1633 { 0x0000, 0x0000 }, /* R1528 */
1636 { 0x0000, 0x0000, 0x0000 }, /* R1529 */ 1634 { 0x0000, 0x0000 }, /* R1529 */
1637 { 0x0000, 0x0000, 0x0000 }, /* R1530 */ 1635 { 0x0000, 0x0000 }, /* R1530 */
1638 { 0x0000, 0x0000, 0x0000 }, /* R1531 */ 1636 { 0x0000, 0x0000 }, /* R1531 */
1639 { 0x0000, 0x0000, 0x0000 }, /* R1532 */ 1637 { 0x0000, 0x0000 }, /* R1532 */
1640 { 0x0000, 0x0000, 0x0000 }, /* R1533 */ 1638 { 0x0000, 0x0000 }, /* R1533 */
1641 { 0x0000, 0x0000, 0x0000 }, /* R1534 */ 1639 { 0x0000, 0x0000 }, /* R1534 */
1642 { 0x0000, 0x0000, 0x0000 }, /* R1535 */ 1640 { 0x0000, 0x0000 }, /* R1535 */
1643 { 0x01EF, 0x01EF, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */ 1641 { 0x01EF, 0x01EF }, /* R1536 - DAC1 Mixer Volumes */
1644 { 0x0037, 0x0037, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */ 1642 { 0x0037, 0x0037 }, /* R1537 - DAC1 Left Mixer Routing */
1645 { 0x0037, 0x0037, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */ 1643 { 0x0037, 0x0037 }, /* R1538 - DAC1 Right Mixer Routing */
1646 { 0x01EF, 0x01EF, 0x0000 }, /* R1539 - DAC2 Mixer Volumes */ 1644 { 0x01EF, 0x01EF }, /* R1539 - DAC2 Mixer Volumes */
1647 { 0x0037, 0x0037, 0x0000 }, /* R1540 - DAC2 Left Mixer Routing */ 1645 { 0x0037, 0x0037 }, /* R1540 - DAC2 Left Mixer Routing */
1648 { 0x0037, 0x0037, 0x0000 }, /* R1541 - DAC2 Right Mixer Routing */ 1646 { 0x0037, 0x0037 }, /* R1541 - DAC2 Right Mixer Routing */
1649 { 0x0003, 0x0003, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */ 1647 { 0x0003, 0x0003 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
1650 { 0x0003, 0x0003, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */ 1648 { 0x0003, 0x0003 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
1651 { 0x0003, 0x0003, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */ 1649 { 0x0003, 0x0003 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
1652 { 0x0003, 0x0003, 0x0000 }, /* R1545 - AIF1 ADC2 Right mixer Routing */ 1650 { 0x0003, 0x0003 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
1653 { 0x0000, 0x0000, 0x0000 }, /* R1546 */ 1651 { 0x0000, 0x0000 }, /* R1546 */
1654 { 0x0000, 0x0000, 0x0000 }, /* R1547 */ 1652 { 0x0000, 0x0000 }, /* R1547 */
1655 { 0x0000, 0x0000, 0x0000 }, /* R1548 */ 1653 { 0x0000, 0x0000 }, /* R1548 */
1656 { 0x0000, 0x0000, 0x0000 }, /* R1549 */ 1654 { 0x0000, 0x0000 }, /* R1549 */
1657 { 0x0000, 0x0000, 0x0000 }, /* R1550 */ 1655 { 0x0000, 0x0000 }, /* R1550 */
1658 { 0x0000, 0x0000, 0x0000 }, /* R1551 */ 1656 { 0x0000, 0x0000 }, /* R1551 */
1659 { 0x02FF, 0x03FF, 0x0000 }, /* R1552 - DAC1 Left Volume */ 1657 { 0x02FF, 0x03FF }, /* R1552 - DAC1 Left Volume */
1660 { 0x02FF, 0x03FF, 0x0000 }, /* R1553 - DAC1 Right Volume */ 1658 { 0x02FF, 0x03FF }, /* R1553 - DAC1 Right Volume */
1661 { 0x02FF, 0x03FF, 0x0000 }, /* R1554 - DAC2 Left Volume */ 1659 { 0x02FF, 0x03FF }, /* R1554 - DAC2 Left Volume */
1662 { 0x02FF, 0x03FF, 0x0000 }, /* R1555 - DAC2 Right Volume */ 1660 { 0x02FF, 0x03FF }, /* R1555 - DAC2 Right Volume */
1663 { 0x0003, 0x0003, 0x0000 }, /* R1556 - DAC Softmute */ 1661 { 0x0003, 0x0003 }, /* R1556 - DAC Softmute */
1664 { 0x0000, 0x0000, 0x0000 }, /* R1557 */ 1662 { 0x0000, 0x0000 }, /* R1557 */
1665 { 0x0000, 0x0000, 0x0000 }, /* R1558 */ 1663 { 0x0000, 0x0000 }, /* R1558 */
1666 { 0x0000, 0x0000, 0x0000 }, /* R1559 */ 1664 { 0x0000, 0x0000 }, /* R1559 */
1667 { 0x0000, 0x0000, 0x0000 }, /* R1560 */ 1665 { 0x0000, 0x0000 }, /* R1560 */
1668 { 0x0000, 0x0000, 0x0000 }, /* R1561 */ 1666 { 0x0000, 0x0000 }, /* R1561 */
1669 { 0x0000, 0x0000, 0x0000 }, /* R1562 */ 1667 { 0x0000, 0x0000 }, /* R1562 */
1670 { 0x0000, 0x0000, 0x0000 }, /* R1563 */ 1668 { 0x0000, 0x0000 }, /* R1563 */
1671 { 0x0000, 0x0000, 0x0000 }, /* R1564 */ 1669 { 0x0000, 0x0000 }, /* R1564 */
1672 { 0x0000, 0x0000, 0x0000 }, /* R1565 */ 1670 { 0x0000, 0x0000 }, /* R1565 */
1673 { 0x0000, 0x0000, 0x0000 }, /* R1566 */ 1671 { 0x0000, 0x0000 }, /* R1566 */
1674 { 0x0000, 0x0000, 0x0000 }, /* R1567 */ 1672 { 0x0000, 0x0000 }, /* R1567 */
1675 { 0x0003, 0x0003, 0x0000 }, /* R1568 - Oversampling */ 1673 { 0x0003, 0x0003 }, /* R1568 - Oversampling */
1676 { 0x03C3, 0x03C3, 0x0000 }, /* R1569 - Sidetone */ 1674 { 0x03C3, 0x03C3 }, /* R1569 - Sidetone */
1677}; 1675};
1678 1676
1679static int wm8994_readable(unsigned int reg) 1677static int wm8994_readable(unsigned int reg)
@@ -1902,8 +1900,6 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol,
1902 return snd_soc_put_volsw(kcontrol, ucontrol); 1900 return snd_soc_put_volsw(kcontrol, ucontrol);
1903} 1901}
1904 1902
1905
1906
1907static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) 1903static void wm8994_set_drc(struct snd_soc_codec *codec, int drc)
1908{ 1904{
1909 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 1905 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
@@ -1942,7 +1938,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol,
1942 struct snd_ctl_elem_value *ucontrol) 1938 struct snd_ctl_elem_value *ucontrol)
1943{ 1939{
1944 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1940 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1945 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 1941 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
1946 struct wm8994_pdata *pdata = wm8994->pdata; 1942 struct wm8994_pdata *pdata = wm8994->pdata;
1947 int drc = wm8994_get_drc(kcontrol->id.name); 1943 int drc = wm8994_get_drc(kcontrol->id.name);
1948 int value = ucontrol->value.integer.value[0]; 1944 int value = ucontrol->value.integer.value[0];
@@ -2045,7 +2041,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol,
2045 struct snd_ctl_elem_value *ucontrol) 2041 struct snd_ctl_elem_value *ucontrol)
2046{ 2042{
2047 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2043 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2048 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2044 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2049 struct wm8994_pdata *pdata = wm8994->pdata; 2045 struct wm8994_pdata *pdata = wm8994->pdata;
2050 int block = wm8994_get_retune_mobile_block(kcontrol->id.name); 2046 int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
2051 int value = ucontrol->value.integer.value[0]; 2047 int value = ucontrol->value.integer.value[0];
@@ -2067,7 +2063,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
2067 struct snd_ctl_elem_value *ucontrol) 2063 struct snd_ctl_elem_value *ucontrol)
2068{ 2064{
2069 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 2065 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
2070 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2066 struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec);
2071 int block = wm8994_get_retune_mobile_block(kcontrol->id.name); 2067 int block = wm8994_get_retune_mobile_block(kcontrol->id.name);
2072 2068
2073 ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; 2069 ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block];
@@ -2075,6 +2071,22 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol,
2075 return 0; 2071 return 0;
2076} 2072}
2077 2073
2074static const char *aifdac_src_text[] = {
2075 "Left", "Right"
2076};
2077
2078static const struct soc_enum aif1dacl_src =
2079 SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 15, 2, aifdac_src_text);
2080
2081static const struct soc_enum aif1dacr_src =
2082 SOC_ENUM_SINGLE(WM8994_AIF1_CONTROL_2, 14, 2, aifdac_src_text);
2083
2084static const struct soc_enum aif2dacl_src =
2085 SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 15, 2, aifdac_src_text);
2086
2087static const struct soc_enum aif2dacr_src =
2088 SOC_ENUM_SINGLE(WM8994_AIF2_CONTROL_2, 14, 2, aifdac_src_text);
2089
2078static const struct snd_kcontrol_new wm8994_snd_controls[] = { 2090static const struct snd_kcontrol_new wm8994_snd_controls[] = {
2079SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME, 2091SOC_DOUBLE_R_TLV("AIF1ADC1 Volume", WM8994_AIF1_ADC1_LEFT_VOLUME,
2080 WM8994_AIF1_ADC1_RIGHT_VOLUME, 2092 WM8994_AIF1_ADC1_RIGHT_VOLUME,
@@ -2086,6 +2098,11 @@ SOC_DOUBLE_R_TLV("AIF2ADC Volume", WM8994_AIF2_ADC_LEFT_VOLUME,
2086 WM8994_AIF2_ADC_RIGHT_VOLUME, 2098 WM8994_AIF2_ADC_RIGHT_VOLUME,
2087 1, 119, 0, digital_tlv), 2099 1, 119, 0, digital_tlv),
2088 2100
2101SOC_ENUM("AIF1DACL Source", aif1dacl_src),
2102SOC_ENUM("AIF1DACR Source", aif1dacr_src),
2103SOC_ENUM("AIF2DACL Source", aif1dacl_src),
2104SOC_ENUM("AIF2DACR Source", aif1dacr_src),
2105
2089SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME, 2106SOC_DOUBLE_R_TLV("AIF1DAC1 Volume", WM8994_AIF1_DAC1_LEFT_VOLUME,
2090 WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv), 2107 WM8994_AIF1_DAC1_RIGHT_VOLUME, 1, 96, 0, digital_tlv),
2091SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME, 2108SOC_DOUBLE_R_TLV("AIF1DAC2 Volume", WM8994_AIF1_DAC2_LEFT_VOLUME,
@@ -2881,10 +2898,9 @@ static int wm8994_get_fll_config(struct fll_div *fll,
2881 return 0; 2898 return 0;
2882} 2899}
2883 2900
2884static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, 2901static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
2885 unsigned int freq_in, unsigned int freq_out) 2902 unsigned int freq_in, unsigned int freq_out)
2886{ 2903{
2887 struct snd_soc_codec *codec = dai->codec;
2888 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 2904 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
2889 int reg_offset, ret; 2905 int reg_offset, ret;
2890 struct fll_div fll; 2906 struct fll_div fll;
@@ -2995,8 +3011,15 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
2995 return 0; 3011 return 0;
2996} 3012}
2997 3013
3014
2998static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; 3015static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 };
2999 3016
3017static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src,
3018 unsigned int freq_in, unsigned int freq_out)
3019{
3020 return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out);
3021}
3022
3000static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, 3023static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
3001 int clk_id, unsigned int freq, int dir) 3024 int clk_id, unsigned int freq, int dir)
3002{ 3025{
@@ -3313,20 +3336,24 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
3313 bclk_reg = WM8994_AIF1_BCLK; 3336 bclk_reg = WM8994_AIF1_BCLK;
3314 rate_reg = WM8994_AIF1_RATE; 3337 rate_reg = WM8994_AIF1_RATE;
3315 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || 3338 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
3316 wm8994->lrclk_shared[0]) 3339 wm8994->lrclk_shared[0]) {
3317 lrclk_reg = WM8994_AIF1DAC_LRCLK; 3340 lrclk_reg = WM8994_AIF1DAC_LRCLK;
3318 else 3341 } else {
3319 lrclk_reg = WM8994_AIF1ADC_LRCLK; 3342 lrclk_reg = WM8994_AIF1ADC_LRCLK;
3343 dev_dbg(codec->dev, "AIF1 using split LRCLK\n");
3344 }
3320 break; 3345 break;
3321 case 2: 3346 case 2:
3322 aif1_reg = WM8994_AIF2_CONTROL_1; 3347 aif1_reg = WM8994_AIF2_CONTROL_1;
3323 bclk_reg = WM8994_AIF2_BCLK; 3348 bclk_reg = WM8994_AIF2_BCLK;
3324 rate_reg = WM8994_AIF2_RATE; 3349 rate_reg = WM8994_AIF2_RATE;
3325 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || 3350 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
3326 wm8994->lrclk_shared[1]) 3351 wm8994->lrclk_shared[1]) {
3327 lrclk_reg = WM8994_AIF2DAC_LRCLK; 3352 lrclk_reg = WM8994_AIF2DAC_LRCLK;
3328 else 3353 } else {
3329 lrclk_reg = WM8994_AIF2ADC_LRCLK; 3354 lrclk_reg = WM8994_AIF2ADC_LRCLK;
3355 dev_dbg(codec->dev, "AIF2 using split LRCLK\n");
3356 }
3330 break; 3357 break;
3331 default: 3358 default:
3332 return -EINVAL; 3359 return -EINVAL;
@@ -3491,7 +3518,7 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate)
3491#define WM8994_RATES SNDRV_PCM_RATE_8000_96000 3518#define WM8994_RATES SNDRV_PCM_RATE_8000_96000
3492 3519
3493#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 3520#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
3494 SNDRV_PCM_FMTBIT_S24_LE) 3521 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
3495 3522
3496static struct snd_soc_dai_ops wm8994_aif1_dai_ops = { 3523static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
3497 .set_sysclk = wm8994_set_dai_sysclk, 3524 .set_sysclk = wm8994_set_dai_sysclk,
@@ -3515,9 +3542,9 @@ static struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
3515 .set_tristate = wm8994_set_tristate, 3542 .set_tristate = wm8994_set_tristate,
3516}; 3543};
3517 3544
3518struct snd_soc_dai wm8994_dai[] = { 3545static struct snd_soc_dai_driver wm8994_dai[] = {
3519 { 3546 {
3520 .name = "WM8994 AIF1", 3547 .name = "wm8994-aif1",
3521 .id = 1, 3548 .id = 1,
3522 .playback = { 3549 .playback = {
3523 .stream_name = "AIF1 Playback", 3550 .stream_name = "AIF1 Playback",
@@ -3536,7 +3563,7 @@ struct snd_soc_dai wm8994_dai[] = {
3536 .ops = &wm8994_aif1_dai_ops, 3563 .ops = &wm8994_aif1_dai_ops,
3537 }, 3564 },
3538 { 3565 {
3539 .name = "WM8994 AIF2", 3566 .name = "wm8994-aif2",
3540 .id = 2, 3567 .id = 2,
3541 .playback = { 3568 .playback = {
3542 .stream_name = "AIF2 Playback", 3569 .stream_name = "AIF2 Playback",
@@ -3555,7 +3582,7 @@ struct snd_soc_dai wm8994_dai[] = {
3555 .ops = &wm8994_aif2_dai_ops, 3582 .ops = &wm8994_aif2_dai_ops,
3556 }, 3583 },
3557 { 3584 {
3558 .name = "WM8994 AIF3", 3585 .name = "wm8994-aif3",
3559 .id = 3, 3586 .id = 3,
3560 .playback = { 3587 .playback = {
3561 .stream_name = "AIF3 Playback", 3588 .stream_name = "AIF3 Playback",
@@ -3574,20 +3601,17 @@ struct snd_soc_dai wm8994_dai[] = {
3574 .ops = &wm8994_aif3_dai_ops, 3601 .ops = &wm8994_aif3_dai_ops,
3575 } 3602 }
3576}; 3603};
3577EXPORT_SYMBOL_GPL(wm8994_dai);
3578 3604
3579#ifdef CONFIG_PM 3605#ifdef CONFIG_PM
3580static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) 3606static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
3581{ 3607{
3582 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
3583 struct snd_soc_codec *codec = socdev->card->codec;
3584 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 3608 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
3585 int i, ret; 3609 int i, ret;
3586 3610
3587 for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { 3611 for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
3588 memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], 3612 memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i],
3589 sizeof(struct fll_config)); 3613 sizeof(struct fll_config));
3590 ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0); 3614 ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0);
3591 if (ret < 0) 3615 if (ret < 0)
3592 dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", 3616 dev_warn(codec->dev, "Failed to stop FLL%d: %d\n",
3593 i + 1, ret); 3617 i + 1, ret);
@@ -3598,10 +3622,8 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t state)
3598 return 0; 3622 return 0;
3599} 3623}
3600 3624
3601static int wm8994_resume(struct platform_device *pdev) 3625static int wm8994_resume(struct snd_soc_codec *codec)
3602{ 3626{
3603 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
3604 struct snd_soc_codec *codec = socdev->card->codec;
3605 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); 3627 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
3606 u16 *reg_cache = codec->reg_cache; 3628 u16 *reg_cache = codec->reg_cache;
3607 int i, ret; 3629 int i, ret;
@@ -3630,7 +3652,7 @@ static int wm8994_resume(struct platform_device *pdev)
3630 if (!wm8994->fll_suspend[i].out) 3652 if (!wm8994->fll_suspend[i].out)
3631 continue; 3653 continue;
3632 3654
3633 ret = wm8994_set_fll(&codec->dai[0], i + 1, 3655 ret = _wm8994_set_fll(codec, i + 1,
3634 wm8994->fll_suspend[i].src, 3656 wm8994->fll_suspend[i].src,
3635 wm8994->fll_suspend[i].in, 3657 wm8994->fll_suspend[i].in,
3636 wm8994->fll_suspend[i].out); 3658 wm8994->fll_suspend[i].out);
@@ -3648,7 +3670,7 @@ static int wm8994_resume(struct platform_device *pdev)
3648 3670
3649static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) 3671static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
3650{ 3672{
3651 struct snd_soc_codec *codec = &wm8994->codec; 3673 struct snd_soc_codec *codec = wm8994->codec;
3652 struct wm8994_pdata *pdata = wm8994->pdata; 3674 struct wm8994_pdata *pdata = wm8994->pdata;
3653 struct snd_kcontrol_new controls[] = { 3675 struct snd_kcontrol_new controls[] = {
3654 SOC_ENUM_EXT("AIF1.1 EQ Mode", 3676 SOC_ENUM_EXT("AIF1.1 EQ Mode",
@@ -3706,16 +3728,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
3706 wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; 3728 wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;
3707 wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; 3729 wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts;
3708 3730
3709 ret = snd_soc_add_controls(&wm8994->codec, controls, 3731 ret = snd_soc_add_controls(wm8994->codec, controls,
3710 ARRAY_SIZE(controls)); 3732 ARRAY_SIZE(controls));
3711 if (ret != 0) 3733 if (ret != 0)
3712 dev_err(wm8994->codec.dev, 3734 dev_err(wm8994->codec->dev,
3713 "Failed to add ReTune Mobile controls: %d\n", ret); 3735 "Failed to add ReTune Mobile controls: %d\n", ret);
3714} 3736}
3715 3737
3716static void wm8994_handle_pdata(struct wm8994_priv *wm8994) 3738static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
3717{ 3739{
3718 struct snd_soc_codec *codec = &wm8994->codec; 3740 struct snd_soc_codec *codec = wm8994->codec;
3719 struct wm8994_pdata *pdata = wm8994->pdata; 3741 struct wm8994_pdata *pdata = wm8994->pdata;
3720 int ret, i; 3742 int ret, i;
3721 3743
@@ -3747,7 +3769,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
3747 wm8994->drc_texts = kmalloc(sizeof(char *) 3769 wm8994->drc_texts = kmalloc(sizeof(char *)
3748 * pdata->num_drc_cfgs, GFP_KERNEL); 3770 * pdata->num_drc_cfgs, GFP_KERNEL);
3749 if (!wm8994->drc_texts) { 3771 if (!wm8994->drc_texts) {
3750 dev_err(wm8994->codec.dev, 3772 dev_err(wm8994->codec->dev,
3751 "Failed to allocate %d DRC config texts\n", 3773 "Failed to allocate %d DRC config texts\n",
3752 pdata->num_drc_cfgs); 3774 pdata->num_drc_cfgs);
3753 return; 3775 return;
@@ -3759,10 +3781,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
3759 wm8994->drc_enum.max = pdata->num_drc_cfgs; 3781 wm8994->drc_enum.max = pdata->num_drc_cfgs;
3760 wm8994->drc_enum.texts = wm8994->drc_texts; 3782 wm8994->drc_enum.texts = wm8994->drc_texts;
3761 3783
3762 ret = snd_soc_add_controls(&wm8994->codec, controls, 3784 ret = snd_soc_add_controls(wm8994->codec, controls,
3763 ARRAY_SIZE(controls)); 3785 ARRAY_SIZE(controls));
3764 if (ret != 0) 3786 if (ret != 0)
3765 dev_err(wm8994->codec.dev, 3787 dev_err(wm8994->codec->dev,
3766 "Failed to add DRC mode controls: %d\n", ret); 3788 "Failed to add DRC mode controls: %d\n", ret);
3767 3789
3768 for (i = 0; i < WM8994_NUM_DRC; i++) 3790 for (i = 0; i < WM8994_NUM_DRC; i++)
@@ -3775,62 +3797,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
3775 if (pdata->num_retune_mobile_cfgs) 3797 if (pdata->num_retune_mobile_cfgs)
3776 wm8994_handle_retune_mobile_pdata(wm8994); 3798 wm8994_handle_retune_mobile_pdata(wm8994);
3777 else 3799 else
3778 snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls, 3800 snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
3779 ARRAY_SIZE(wm8994_eq_controls)); 3801 ARRAY_SIZE(wm8994_eq_controls));
3780} 3802}
3781 3803
3782static int wm8994_probe(struct platform_device *pdev)
3783{
3784 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
3785 struct snd_soc_codec *codec;
3786 int ret = 0;
3787
3788 if (wm8994_codec == NULL) {
3789 dev_err(&pdev->dev, "Codec device not registered\n");
3790 return -ENODEV;
3791 }
3792
3793 socdev->card->codec = wm8994_codec;
3794 codec = wm8994_codec;
3795
3796 /* register pcms */
3797 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
3798 if (ret < 0) {
3799 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
3800 return ret;
3801 }
3802
3803 wm8994_handle_pdata(snd_soc_codec_get_drvdata(codec));
3804
3805 wm_hubs_add_analogue_controls(codec);
3806 snd_soc_add_controls(codec, wm8994_snd_controls,
3807 ARRAY_SIZE(wm8994_snd_controls));
3808 snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets,
3809 ARRAY_SIZE(wm8994_dapm_widgets));
3810 wm_hubs_add_analogue_routes(codec, 0, 0);
3811 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
3812
3813 return 0;
3814}
3815
3816static int wm8994_remove(struct platform_device *pdev)
3817{
3818 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
3819
3820 snd_soc_free_pcms(socdev);
3821 snd_soc_dapm_free(socdev);
3822
3823 return 0;
3824}
3825
3826struct snd_soc_codec_device soc_codec_dev_wm8994 = {
3827 .probe = wm8994_probe,
3828 .remove = wm8994_remove,
3829 .suspend = wm8994_suspend,
3830 .resume = wm8994_resume,
3831};
3832EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
3833
3834/** 3804/**
3835 * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ 3805 * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ
3836 * 3806 *
@@ -3842,7 +3812,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994);
3842 * 3812 *
3843 * Enable microphone detection via IRQ on the WM8994. If GPIOs are 3813 * Enable microphone detection via IRQ on the WM8994. If GPIOs are
3844 * being used to bring out signals to the processor then only platform 3814 * being used to bring out signals to the processor then only platform
3845 * data configuration is needed for WM8903 and processor GPIOs should 3815 * data configuration is needed for WM8994 and processor GPIOs should
3846 * be configured using snd_soc_jack_add_gpios() instead. 3816 * be configured using snd_soc_jack_add_gpios() instead.
3847 * 3817 *
3848 * Configuration of detection levels is available via the micbias1_lvl 3818 * Configuration of detection levels is available via the micbias1_lvl
@@ -3889,7 +3859,7 @@ EXPORT_SYMBOL_GPL(wm8994_mic_detect);
3889static irqreturn_t wm8994_mic_irq(int irq, void *data) 3859static irqreturn_t wm8994_mic_irq(int irq, void *data)
3890{ 3860{
3891 struct wm8994_priv *priv = data; 3861 struct wm8994_priv *priv = data;
3892 struct snd_soc_codec *codec = &priv->codec; 3862 struct snd_soc_codec *codec = priv->codec;
3893 int reg; 3863 int reg;
3894 int report; 3864 int report;
3895 3865
@@ -3921,46 +3891,20 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
3921 return IRQ_HANDLED; 3891 return IRQ_HANDLED;
3922} 3892}
3923 3893
3924static int wm8994_codec_probe(struct platform_device *pdev) 3894static int wm8994_codec_probe(struct snd_soc_codec *codec)
3925{ 3895{
3926 int ret;
3927 struct wm8994_priv *wm8994; 3896 struct wm8994_priv *wm8994;
3928 struct snd_soc_codec *codec; 3897 int ret, i;
3929 int i;
3930 3898
3931 if (wm8994_codec) { 3899 codec->control_data = dev_get_drvdata(codec->dev->parent);
3932 dev_err(&pdev->dev, "Another WM8994 is registered\n");
3933 return -EINVAL;
3934 }
3935 3900
3936 wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); 3901 wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
3937 if (!wm8994) { 3902 if (wm8994 == NULL)
3938 dev_err(&pdev->dev, "Failed to allocate private data\n");
3939 return -ENOMEM; 3903 return -ENOMEM;
3940 }
3941
3942 codec = &wm8994->codec;
3943
3944 mutex_init(&codec->mutex);
3945 INIT_LIST_HEAD(&codec->dapm_widgets);
3946 INIT_LIST_HEAD(&codec->dapm_paths);
3947
3948 snd_soc_codec_set_drvdata(codec, wm8994); 3904 snd_soc_codec_set_drvdata(codec, wm8994);
3949 codec->control_data = dev_get_drvdata(pdev->dev.parent); 3905
3950 codec->name = "WM8994"; 3906 wm8994->pdata = dev_get_platdata(codec->dev->parent);
3951 codec->owner = THIS_MODULE; 3907 wm8994->codec = codec;
3952 codec->read = wm8994_read;
3953 codec->write = wm8994_write;
3954 codec->readable_register = wm8994_readable;
3955 codec->bias_level = SND_SOC_BIAS_OFF;
3956 codec->set_bias_level = wm8994_set_bias_level;
3957 codec->dai = &wm8994_dai[0];
3958 codec->num_dai = 3;
3959 codec->reg_cache_size = WM8994_MAX_REGISTER;
3960 codec->reg_cache = &wm8994->reg_cache;
3961 codec->dev = &pdev->dev;
3962
3963 wm8994->pdata = pdev->dev.parent->platform_data;
3964 3908
3965 /* Fill the cache with physical values we inherited; don't reset */ 3909 /* Fill the cache with physical values we inherited; don't reset */
3966 ret = wm8994_bulk_read(codec->control_data, 0, 3910 ret = wm8994_bulk_read(codec->control_data, 0,
@@ -3996,25 +3940,25 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3996 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, 3940 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
3997 wm8994_mic_irq, "Mic 1 detect", wm8994); 3941 wm8994_mic_irq, "Mic 1 detect", wm8994);
3998 if (ret != 0) 3942 if (ret != 0)
3999 dev_warn(&pdev->dev, 3943 dev_warn(codec->dev,
4000 "Failed to request Mic1 detect IRQ: %d\n", ret); 3944 "Failed to request Mic1 detect IRQ: %d\n", ret);
4001 3945
4002 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, 3946 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
4003 wm8994_mic_irq, "Mic 1 short", wm8994); 3947 wm8994_mic_irq, "Mic 1 short", wm8994);
4004 if (ret != 0) 3948 if (ret != 0)
4005 dev_warn(&pdev->dev, 3949 dev_warn(codec->dev,
4006 "Failed to request Mic1 short IRQ: %d\n", ret); 3950 "Failed to request Mic1 short IRQ: %d\n", ret);
4007 3951
4008 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, 3952 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
4009 wm8994_mic_irq, "Mic 2 detect", wm8994); 3953 wm8994_mic_irq, "Mic 2 detect", wm8994);
4010 if (ret != 0) 3954 if (ret != 0)
4011 dev_warn(&pdev->dev, 3955 dev_warn(codec->dev,
4012 "Failed to request Mic2 detect IRQ: %d\n", ret); 3956 "Failed to request Mic2 detect IRQ: %d\n", ret);
4013 3957
4014 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, 3958 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT,
4015 wm8994_mic_irq, "Mic 2 short", wm8994); 3959 wm8994_mic_irq, "Mic 2 short", wm8994);
4016 if (ret != 0) 3960 if (ret != 0)
4017 dev_warn(&pdev->dev, 3961 dev_warn(codec->dev,
4018 "Failed to request Mic2 short IRQ: %d\n", ret); 3962 "Failed to request Mic2 short IRQ: %d\n", ret);
4019 3963
4020 /* Remember if AIFnLRCLK is configured as a GPIO. This should be 3964 /* Remember if AIFnLRCLK is configured as a GPIO. This should be
@@ -4045,13 +3989,8 @@ static int wm8994_codec_probe(struct platform_device *pdev)
4045 wm8994->lrclk_shared[1] = 0; 3989 wm8994->lrclk_shared[1] = 0;
4046 } 3990 }
4047 3991
4048 for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++)
4049 wm8994_dai[i].dev = codec->dev;
4050
4051 wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 3992 wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
4052 3993
4053 wm8994_codec = codec;
4054
4055 /* Latch volume updates (right only; we always do left then right). */ 3994 /* Latch volume updates (right only; we always do left then right). */
4056 snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, 3995 snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME,
4057 WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); 3996 WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU);
@@ -4088,24 +4027,18 @@ static int wm8994_codec_probe(struct platform_device *pdev)
4088 4027
4089 wm8994_update_class_w(codec); 4028 wm8994_update_class_w(codec);
4090 4029
4091 ret = snd_soc_register_codec(codec); 4030 wm8994_handle_pdata(wm8994);
4092 if (ret != 0) {
4093 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
4094 goto err_irq;
4095 }
4096
4097 ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai));
4098 if (ret != 0) {
4099 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
4100 goto err_codec;
4101 }
4102 4031
4103 platform_set_drvdata(pdev, wm8994); 4032 wm_hubs_add_analogue_controls(codec);
4033 snd_soc_add_controls(codec, wm8994_snd_controls,
4034 ARRAY_SIZE(wm8994_snd_controls));
4035 snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets,
4036 ARRAY_SIZE(wm8994_dapm_widgets));
4037 wm_hubs_add_analogue_routes(codec, 0, 0);
4038 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
4104 4039
4105 return 0; 4040 return 0;
4106 4041
4107err_codec:
4108 snd_soc_unregister_codec(codec);
4109err_irq: 4042err_irq:
4110 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); 4043 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
4111 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); 4044 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
@@ -4116,31 +4049,50 @@ err:
4116 return ret; 4049 return ret;
4117} 4050}
4118 4051
4119static int __devexit wm8994_codec_remove(struct platform_device *pdev) 4052static int wm8994_codec_remove(struct snd_soc_codec *codec)
4120{ 4053{
4121 struct wm8994_priv *wm8994 = platform_get_drvdata(pdev); 4054 struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
4122 struct snd_soc_codec *codec = &wm8994->codec;
4123 4055
4124 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); 4056 wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
4125 snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); 4057
4126 snd_soc_unregister_codec(&wm8994->codec);
4127 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); 4058 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
4128 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); 4059 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
4129 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); 4060 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
4130 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); 4061 wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994);
4131 kfree(wm8994); 4062 kfree(wm8994);
4132 wm8994_codec = NULL;
4133 4063
4134 return 0; 4064 return 0;
4135} 4065}
4136 4066
4067static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
4068 .probe = wm8994_codec_probe,
4069 .remove = wm8994_codec_remove,
4070 .suspend = wm8994_suspend,
4071 .resume = wm8994_resume,
4072 .read = wm8994_read,
4073 .write = wm8994_write,
4074 .set_bias_level = wm8994_set_bias_level,
4075};
4076
4077static int __devinit wm8994_probe(struct platform_device *pdev)
4078{
4079 return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
4080 wm8994_dai, ARRAY_SIZE(wm8994_dai));
4081}
4082
4083static int __devexit wm8994_remove(struct platform_device *pdev)
4084{
4085 snd_soc_unregister_codec(&pdev->dev);
4086 return 0;
4087}
4088
4137static struct platform_driver wm8994_codec_driver = { 4089static struct platform_driver wm8994_codec_driver = {
4138 .driver = { 4090 .driver = {
4139 .name = "wm8994-codec", 4091 .name = "wm8994-codec",
4140 .owner = THIS_MODULE, 4092 .owner = THIS_MODULE,
4141 }, 4093 },
4142 .probe = wm8994_codec_probe, 4094 .probe = wm8994_probe,
4143 .remove = __devexit_p(wm8994_codec_remove), 4095 .remove = __devexit_p(wm8994_remove),
4144}; 4096};
4145 4097
4146static __init int wm8994_init(void) 4098static __init int wm8994_init(void)
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 2e0ca67a8df7..d8dce260c430 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -11,9 +11,6 @@
11 11
12#include <sound/soc.h> 12#include <sound/soc.h>
13 13
14extern struct snd_soc_codec_device soc_codec_dev_wm8994;
15extern struct snd_soc_dai wm8994_dai[];
16
17/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */ 14/* Sources for AIF1/2 SYSCLK - use with set_dai_sysclk() */
18#define WM8994_SYSCLK_MCLK1 1 15#define WM8994_SYSCLK_MCLK1 1
19#define WM8994_SYSCLK_MCLK2 2 16#define WM8994_SYSCLK_MCLK2 2
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 76b37ff6c264..ecc7c37180c7 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -156,7 +156,8 @@ static struct {
156}; 156};
157 157
158struct wm9081_priv { 158struct wm9081_priv {
159 struct snd_soc_codec codec; 159 enum snd_soc_control_type control_type;
160 void *control_data;
160 u16 reg_cache[WM9081_MAX_REGISTER + 1]; 161 u16 reg_cache[WM9081_MAX_REGISTER + 1];
161 int sysclk_source; 162 int sysclk_source;
162 int mclk_rate; 163 int mclk_rate;
@@ -1212,8 +1213,8 @@ static struct snd_soc_dai_ops wm9081_dai_ops = {
1212/* We report two channels because the CODEC processes a stereo signal, even 1213/* We report two channels because the CODEC processes a stereo signal, even
1213 * though it is only capable of handling a mono output. 1214 * though it is only capable of handling a mono output.
1214 */ 1215 */
1215struct snd_soc_dai wm9081_dai = { 1216static struct snd_soc_dai_driver wm9081_dai = {
1216 .name = "WM9081", 1217 .name = "wm9081-hifi",
1217 .playback = { 1218 .playback = {
1218 .stream_name = "HiFi Playback", 1219 .stream_name = "HiFi Playback",
1219 .channels_min = 1, 1220 .channels_min = 1,
@@ -1223,34 +1224,42 @@ struct snd_soc_dai wm9081_dai = {
1223 }, 1224 },
1224 .ops = &wm9081_dai_ops, 1225 .ops = &wm9081_dai_ops,
1225}; 1226};
1226EXPORT_SYMBOL_GPL(wm9081_dai);
1227 1227
1228 1228static int wm9081_probe(struct snd_soc_codec *codec)
1229static struct snd_soc_codec *wm9081_codec;
1230
1231static int wm9081_probe(struct platform_device *pdev)
1232{ 1229{
1233 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1230 struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
1234 struct snd_soc_codec *codec; 1231 int ret;
1235 struct wm9081_priv *wm9081; 1232 u16 reg;
1236 int ret = 0;
1237 1233
1238 if (wm9081_codec == NULL) { 1234 codec->control_data = wm9081->control_data;
1239 dev_err(&pdev->dev, "Codec device not registered\n"); 1235 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
1240 return -ENODEV; 1236 if (ret != 0) {
1237 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1238 return ret;
1241 } 1239 }
1242 1240
1243 socdev->card->codec = wm9081_codec; 1241 reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
1244 codec = wm9081_codec; 1242 if (reg != 0x9081) {
1245 wm9081 = snd_soc_codec_get_drvdata(codec); 1243 dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
1244 ret = -EINVAL;
1245 return ret;
1246 }
1246 1247
1247 /* register pcms */ 1248 ret = wm9081_reset(codec);
1248 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1249 if (ret < 0) { 1249 if (ret < 0) {
1250 dev_err(codec->dev, "failed to create pcms: %d\n", ret); 1250 dev_err(codec->dev, "Failed to issue reset\n");
1251 goto pcm_err; 1251 return ret;
1252 } 1252 }
1253 1253
1254 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1255
1256 /* Enable zero cross by default */
1257 reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
1258 snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
1259 reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
1260 snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
1261 reg | WM9081_SPKPGAZC);
1262
1254 snd_soc_add_controls(codec, wm9081_snd_controls, 1263 snd_soc_add_controls(codec, wm9081_snd_controls,
1255 ARRAY_SIZE(wm9081_snd_controls)); 1264 ARRAY_SIZE(wm9081_snd_controls));
1256 if (!wm9081->retune) { 1265 if (!wm9081->retune) {
@@ -1265,40 +1274,28 @@ static int wm9081_probe(struct platform_device *pdev)
1265 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 1274 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
1266 1275
1267 return ret; 1276 return ret;
1268
1269pcm_err:
1270 return ret;
1271} 1277}
1272 1278
1273static int wm9081_remove(struct platform_device *pdev) 1279static int wm9081_remove(struct snd_soc_codec *codec)
1274{ 1280{
1275 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1281 wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
1276
1277 snd_soc_free_pcms(socdev);
1278 snd_soc_dapm_free(socdev);
1279
1280 return 0; 1282 return 0;
1281} 1283}
1282 1284
1283#ifdef CONFIG_PM 1285#ifdef CONFIG_PM
1284static int wm9081_suspend(struct platform_device *pdev, pm_message_t state) 1286static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)
1285{ 1287{
1286 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1287 struct snd_soc_codec *codec = socdev->card->codec;
1288
1289 wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF); 1288 wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
1290 1289
1291 return 0; 1290 return 0;
1292} 1291}
1293 1292
1294static int wm9081_resume(struct platform_device *pdev) 1293static int wm9081_resume(struct snd_soc_codec *codec)
1295{ 1294{
1296 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1297 struct snd_soc_codec *codec = socdev->card->codec;
1298 u16 *reg_cache = codec->reg_cache; 1295 u16 *reg_cache = codec->reg_cache;
1299 int i; 1296 int i;
1300 1297
1301 for (i = 0; i < codec->reg_cache_size; i++) { 1298 for (i = 0; i < codec->driver->reg_cache_size; i++) {
1302 if (i == WM9081_SOFTWARE_RESET) 1299 if (i == WM9081_SOFTWARE_RESET)
1303 continue; 1300 continue;
1304 1301
@@ -1314,133 +1311,43 @@ static int wm9081_resume(struct platform_device *pdev)
1314#define wm9081_resume NULL 1311#define wm9081_resume NULL
1315#endif 1312#endif
1316 1313
1317struct snd_soc_codec_device soc_codec_dev_wm9081 = { 1314static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
1318 .probe = wm9081_probe, 1315 .probe = wm9081_probe,
1319 .remove = wm9081_remove, 1316 .remove = wm9081_remove,
1320 .suspend = wm9081_suspend, 1317 .suspend = wm9081_suspend,
1321 .resume = wm9081_resume, 1318 .resume = wm9081_resume,
1319 .set_bias_level = wm9081_set_bias_level,
1320 .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults),
1321 .reg_word_size = sizeof(u16),
1322 .reg_cache_default = wm9081_reg_defaults,
1323 .volatile_register = wm9081_volatile_register,
1322}; 1324};
1323EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081);
1324
1325static int wm9081_register(struct wm9081_priv *wm9081,
1326 enum snd_soc_control_type control)
1327{
1328 struct snd_soc_codec *codec = &wm9081->codec;
1329 int ret;
1330 u16 reg;
1331
1332 if (wm9081_codec) {
1333 dev_err(codec->dev, "Another WM9081 is registered\n");
1334 ret = -EINVAL;
1335 goto err;
1336 }
1337
1338 mutex_init(&codec->mutex);
1339 INIT_LIST_HEAD(&codec->dapm_widgets);
1340 INIT_LIST_HEAD(&codec->dapm_paths);
1341
1342 snd_soc_codec_set_drvdata(codec, wm9081);
1343 codec->name = "WM9081";
1344 codec->owner = THIS_MODULE;
1345 codec->dai = &wm9081_dai;
1346 codec->num_dai = 1;
1347 codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache);
1348 codec->reg_cache = &wm9081->reg_cache;
1349 codec->bias_level = SND_SOC_BIAS_OFF;
1350 codec->set_bias_level = wm9081_set_bias_level;
1351 codec->volatile_register = wm9081_volatile_register;
1352
1353 memcpy(codec->reg_cache, wm9081_reg_defaults,
1354 sizeof(wm9081_reg_defaults));
1355
1356 ret = snd_soc_codec_set_cache_io(codec, 8, 16, control);
1357 if (ret != 0) {
1358 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1359 goto err;
1360 }
1361
1362 reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
1363 if (reg != 0x9081) {
1364 dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
1365 ret = -EINVAL;
1366 goto err;
1367 }
1368
1369 ret = wm9081_reset(codec);
1370 if (ret < 0) {
1371 dev_err(codec->dev, "Failed to issue reset\n");
1372 goto err;
1373 }
1374
1375 wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1376
1377 /* Enable zero cross by default */
1378 reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
1379 snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
1380 reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
1381 snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
1382 reg | WM9081_SPKPGAZC);
1383
1384 wm9081_dai.dev = codec->dev;
1385
1386 wm9081_codec = codec;
1387
1388 ret = snd_soc_register_codec(codec);
1389 if (ret != 0) {
1390 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1391 goto err;
1392 }
1393
1394 ret = snd_soc_register_dai(&wm9081_dai);
1395 if (ret != 0) {
1396 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1397 goto err_codec;
1398 }
1399
1400 return 0;
1401
1402err_codec:
1403 snd_soc_unregister_codec(codec);
1404err:
1405 kfree(wm9081);
1406 return ret;
1407}
1408
1409static void wm9081_unregister(struct wm9081_priv *wm9081)
1410{
1411 wm9081_set_bias_level(&wm9081->codec, SND_SOC_BIAS_OFF);
1412 snd_soc_unregister_dai(&wm9081_dai);
1413 snd_soc_unregister_codec(&wm9081->codec);
1414 kfree(wm9081);
1415 wm9081_codec = NULL;
1416}
1417 1325
1326#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1418static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, 1327static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
1419 const struct i2c_device_id *id) 1328 const struct i2c_device_id *id)
1420{ 1329{
1421 struct wm9081_priv *wm9081; 1330 struct wm9081_priv *wm9081;
1422 struct snd_soc_codec *codec; 1331 int ret;
1423 1332
1424 wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL); 1333 wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
1425 if (wm9081 == NULL) 1334 if (wm9081 == NULL)
1426 return -ENOMEM; 1335 return -ENOMEM;
1427 1336
1428 codec = &wm9081->codec;
1429 codec->hw_write = (hw_write_t)i2c_master_send;
1430 wm9081->retune = i2c->dev.platform_data;
1431
1432 i2c_set_clientdata(i2c, wm9081); 1337 i2c_set_clientdata(i2c, wm9081);
1433 codec->control_data = i2c; 1338 wm9081->control_data = i2c;
1434
1435 codec->dev = &i2c->dev;
1436 1339
1437 return wm9081_register(wm9081, SND_SOC_I2C); 1340 ret = snd_soc_register_codec(&i2c->dev,
1341 &soc_codec_dev_wm9081, &wm9081_dai, 1);
1342 if (ret < 0)
1343 kfree(wm9081);
1344 return ret;
1438} 1345}
1439 1346
1440static __devexit int wm9081_i2c_remove(struct i2c_client *client) 1347static __devexit int wm9081_i2c_remove(struct i2c_client *client)
1441{ 1348{
1442 struct wm9081_priv *wm9081 = i2c_get_clientdata(client); 1349 snd_soc_unregister_codec(&client->dev);
1443 wm9081_unregister(wm9081); 1350 kfree(i2c_get_clientdata(client));
1444 return 0; 1351 return 0;
1445} 1352}
1446 1353
@@ -1452,31 +1359,34 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
1452 1359
1453static struct i2c_driver wm9081_i2c_driver = { 1360static struct i2c_driver wm9081_i2c_driver = {
1454 .driver = { 1361 .driver = {
1455 .name = "wm9081", 1362 .name = "wm9081-codec",
1456 .owner = THIS_MODULE, 1363 .owner = THIS_MODULE,
1457 }, 1364 },
1458 .probe = wm9081_i2c_probe, 1365 .probe = wm9081_i2c_probe,
1459 .remove = __devexit_p(wm9081_i2c_remove), 1366 .remove = __devexit_p(wm9081_i2c_remove),
1460 .id_table = wm9081_i2c_id, 1367 .id_table = wm9081_i2c_id,
1461}; 1368};
1369#endif
1462 1370
1463static int __init wm9081_modinit(void) 1371static int __init wm9081_modinit(void)
1464{ 1372{
1465 int ret; 1373 int ret = 0;
1466 1374#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1467 ret = i2c_add_driver(&wm9081_i2c_driver); 1375 ret = i2c_add_driver(&wm9081_i2c_driver);
1468 if (ret != 0) { 1376 if (ret != 0) {
1469 printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n", 1377 printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
1470 ret); 1378 ret);
1471 } 1379 }
1472 1380#endif
1473 return ret; 1381 return ret;
1474} 1382}
1475module_init(wm9081_modinit); 1383module_init(wm9081_modinit);
1476 1384
1477static void __exit wm9081_exit(void) 1385static void __exit wm9081_exit(void)
1478{ 1386{
1387#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1479 i2c_del_driver(&wm9081_i2c_driver); 1388 i2c_del_driver(&wm9081_i2c_driver);
1389#endif
1480} 1390}
1481module_exit(wm9081_exit); 1391module_exit(wm9081_exit);
1482 1392
diff --git a/sound/soc/codecs/wm9081.h b/sound/soc/codecs/wm9081.h
index 42d3bc757021..871cccb066dc 100644
--- a/sound/soc/codecs/wm9081.h
+++ b/sound/soc/codecs/wm9081.h
@@ -15,9 +15,6 @@
15 15
16#include <sound/soc.h> 16#include <sound/soc.h>
17 17
18extern struct snd_soc_dai wm9081_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm9081;
20
21/* 18/*
22 * SYSCLK sources 19 * SYSCLK sources
23 */ 20 */
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 1592250daec0..7a1825418ee4 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -34,8 +34,6 @@
34 34
35#include "wm9090.h" 35#include "wm9090.h"
36 36
37static struct snd_soc_codec *wm9090_codec;
38
39static const u16 wm9090_reg_defaults[] = { 37static const u16 wm9090_reg_defaults[] = {
40 0x9093, /* R0 - Software Reset */ 38 0x9093, /* R0 - Software Reset */
41 0x0006, /* R1 - Power Management (1) */ 39 0x0006, /* R1 - Power Management (1) */
@@ -142,15 +140,10 @@ static const u16 wm9090_reg_defaults[] = {
142 140
143/* This struct is used to save the context */ 141/* This struct is used to save the context */
144struct wm9090_priv { 142struct wm9090_priv {
145 /* We're not really registering as a CODEC since ASoC core
146 * does not yet support multiple CODECs but having the CODEC
147 * structure means we can reuse some of the ASoC core
148 * features.
149 */
150 struct snd_soc_codec codec;
151 struct mutex mutex; 143 struct mutex mutex;
152 u16 reg_cache[WM9090_MAX_REGISTER + 1]; 144 u16 reg_cache[WM9090_MAX_REGISTER + 1];
153 struct wm9090_platform_data pdata; 145 struct wm9090_platform_data pdata;
146 void *control_data;
154}; 147};
155 148
156static int wm9090_volatile(unsigned int reg) 149static int wm9090_volatile(unsigned int reg)
@@ -523,7 +516,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
523 case SND_SOC_BIAS_STANDBY: 516 case SND_SOC_BIAS_STANDBY:
524 if (codec->bias_level == SND_SOC_BIAS_OFF) { 517 if (codec->bias_level == SND_SOC_BIAS_OFF) {
525 /* Restore the register cache */ 518 /* Restore the register cache */
526 for (i = 1; i < codec->reg_cache_size; i++) { 519 for (i = 1; i < codec->driver->reg_cache_size; i++) {
527 if (reg_cache[i] == wm9090_reg_defaults[i]) 520 if (reg_cache[i] == wm9090_reg_defaults[i])
528 continue; 521 continue;
529 if (wm9090_volatile(i)) 522 if (wm9090_volatile(i))
@@ -556,51 +549,67 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
556 return 0; 549 return 0;
557} 550}
558 551
559static int wm9090_probe(struct platform_device *pdev) 552static int wm9090_probe(struct snd_soc_codec *codec)
560{ 553{
561 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 554 struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
562 struct snd_soc_codec *codec; 555 int ret;
563 int ret = 0;
564 556
565 if (wm9090_codec == NULL) { 557 codec->control_data = wm9090->control_data;
566 dev_err(&pdev->dev, "Codec device not registered\n"); 558 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
567 return -ENODEV; 559 if (ret != 0) {
560 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
561 return ret;
568 } 562 }
569 563
570 socdev->card->codec = wm9090_codec; 564 ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
571 codec = wm9090_codec; 565 if (ret < 0)
572 566 return ret;
573 /* register pcms */ 567 if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
574 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 568 dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
575 if (ret < 0) { 569 return -EINVAL;
576 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
577 goto pcm_err;
578 } 570 }
579 571
572 ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
573 if (ret < 0)
574 return ret;
575
576 /* Configure some defaults; they will be written out when we
577 * bring the bias up.
578 */
579 wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
580 | WM9090_IN1A_ZC;
581 wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
582 | WM9090_IN1B_ZC;
583 wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
584 | WM9090_IN2A_ZC;
585 wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
586 | WM9090_IN2B_ZC;
587 wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
588 WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
589 wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
590 WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
591 wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
592 WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
593
594 wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
595
596 wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
597
580 wm9090_add_controls(codec); 598 wm9090_add_controls(codec);
581 599
582 return 0; 600 return 0;
583
584pcm_err:
585 return ret;
586} 601}
587 602
588#ifdef CONFIG_PM 603#ifdef CONFIG_PM
589static int wm9090_suspend(struct platform_device *pdev, pm_message_t state) 604static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)
590{ 605{
591 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
592 struct snd_soc_codec *codec = socdev->card->codec;
593
594 wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF); 606 wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
595 607
596 return 0; 608 return 0;
597} 609}
598 610
599static int wm9090_resume(struct platform_device *pdev) 611static int wm9090_resume(struct snd_soc_codec *codec)
600{ 612{
601 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
602 struct snd_soc_codec *codec = socdev->card->codec;
603
604 wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 613 wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
605 614
606 return 0; 615 return 0;
@@ -610,29 +619,29 @@ static int wm9090_resume(struct platform_device *pdev)
610#define wm9090_resume NULL 619#define wm9090_resume NULL
611#endif 620#endif
612 621
613static int wm9090_remove(struct platform_device *pdev) 622static int wm9090_remove(struct snd_soc_codec *codec)
614{ 623{
615 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 624 wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
616
617 snd_soc_free_pcms(socdev);
618 snd_soc_dapm_free(socdev);
619 625
620 return 0; 626 return 0;
621} 627}
622 628
623struct snd_soc_codec_device soc_codec_dev_wm9090 = { 629static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
624 .probe = wm9090_probe, 630 .probe = wm9090_probe,
625 .remove = wm9090_remove, 631 .remove = wm9090_remove,
626 .suspend = wm9090_suspend, 632 .suspend = wm9090_suspend,
627 .resume = wm9090_resume, 633 .resume = wm9090_resume,
634 .set_bias_level = wm9090_set_bias_level,
635 .reg_cache_size = (WM9090_MAX_REGISTER + 1),
636 .reg_word_size = sizeof(u16),
637 .reg_cache_default = wm9090_reg_defaults,
638 .volatile_register = wm9090_volatile,
628}; 639};
629EXPORT_SYMBOL_GPL(soc_codec_dev_wm9090);
630 640
631static int wm9090_i2c_probe(struct i2c_client *i2c, 641static int wm9090_i2c_probe(struct i2c_client *i2c,
632 const struct i2c_device_id *id) 642 const struct i2c_device_id *id)
633{ 643{
634 struct wm9090_priv *wm9090; 644 struct wm9090_priv *wm9090;
635 struct snd_soc_codec *codec;
636 int ret; 645 int ret;
637 646
638 wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL); 647 wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL);
@@ -640,102 +649,28 @@ static int wm9090_i2c_probe(struct i2c_client *i2c,
640 dev_err(&i2c->dev, "Can not allocate memory\n"); 649 dev_err(&i2c->dev, "Can not allocate memory\n");
641 return -ENOMEM; 650 return -ENOMEM;
642 } 651 }
643 codec = &wm9090->codec;
644 652
645 if (i2c->dev.platform_data) 653 if (i2c->dev.platform_data)
646 memcpy(&wm9090->pdata, i2c->dev.platform_data, 654 memcpy(&wm9090->pdata, i2c->dev.platform_data,
647 sizeof(wm9090->pdata)); 655 sizeof(wm9090->pdata));
648 656
649 wm9090_codec = codec;
650
651 i2c_set_clientdata(i2c, wm9090); 657 i2c_set_clientdata(i2c, wm9090);
658 wm9090->control_data = i2c;
659 mutex_init(&wm9090->mutex);
652 660
653 mutex_init(&codec->mutex); 661 ret = snd_soc_register_codec(&i2c->dev,
654 INIT_LIST_HEAD(&codec->dapm_widgets); 662 &soc_codec_dev_wm9090, NULL, 0);
655 INIT_LIST_HEAD(&codec->dapm_paths);
656
657 codec->control_data = i2c;
658 snd_soc_codec_set_drvdata(codec, wm9090);
659 codec->dev = &i2c->dev;
660 codec->name = "WM9090";
661 codec->owner = THIS_MODULE;
662 codec->bias_level = SND_SOC_BIAS_OFF;
663 codec->set_bias_level = wm9090_set_bias_level,
664 codec->reg_cache_size = WM9090_MAX_REGISTER + 1;
665 codec->reg_cache = &wm9090->reg_cache;
666 codec->volatile_register = wm9090_volatile;
667
668 ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
669 if (ret != 0) {
670 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
671 goto err;
672 }
673
674 memcpy(&wm9090->reg_cache, wm9090_reg_defaults,
675 sizeof(wm9090->reg_cache));
676
677 ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
678 if (ret < 0)
679 goto err;
680 if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
681 dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", ret);
682 ret = -EINVAL;
683 goto err;
684 }
685
686 ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
687 if (ret < 0) 663 if (ret < 0)
688 goto err; 664 kfree(wm9090);
689
690 /* Configure some defaults; they will be written out when we
691 * bring the bias up.
692 */
693 wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
694 | WM9090_IN1A_ZC;
695 wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
696 | WM9090_IN1B_ZC;
697 wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
698 | WM9090_IN2A_ZC;
699 wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
700 | WM9090_IN2B_ZC;
701 wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
702 WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
703 wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
704 WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
705 wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
706 WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
707
708 wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
709
710 wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
711
712 ret = snd_soc_register_codec(codec);
713 if (ret != 0) {
714 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
715 goto err_bias;
716 }
717
718 return 0;
719
720err_bias:
721 wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
722err:
723 kfree(wm9090);
724 i2c_set_clientdata(i2c, NULL);
725 wm9090_codec = NULL;
726
727 return ret; 665 return ret;
728} 666}
729 667
730static int wm9090_i2c_remove(struct i2c_client *i2c) 668static int wm9090_i2c_remove(struct i2c_client *i2c)
731{ 669{
732 struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c); 670 struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
733 struct snd_soc_codec *codec = &wm9090->codec;
734 671
735 snd_soc_unregister_codec(codec); 672 snd_soc_unregister_codec(&i2c->dev);
736 wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
737 kfree(wm9090); 673 kfree(wm9090);
738 wm9090_codec = NULL;
739 674
740 return 0; 675 return 0;
741} 676}
@@ -748,7 +683,7 @@ MODULE_DEVICE_TABLE(i2c, wm9090_id);
748 683
749static struct i2c_driver wm9090_i2c_driver = { 684static struct i2c_driver wm9090_i2c_driver = {
750 .driver = { 685 .driver = {
751 .name = "wm9090", 686 .name = "wm9090-codec",
752 .owner = THIS_MODULE, 687 .owner = THIS_MODULE,
753 }, 688 },
754 .probe = wm9090_i2c_probe, 689 .probe = wm9090_i2c_probe,
diff --git a/sound/soc/codecs/wm9090.h b/sound/soc/codecs/wm9090.h
index b08eab932a5b..29b9d9fc70b4 100644
--- a/sound/soc/codecs/wm9090.h
+++ b/sound/soc/codecs/wm9090.h
@@ -23,8 +23,6 @@
23#ifndef __WM9090_H 23#ifndef __WM9090_H
24#define __WM9090_H 24#define __WM9090_H
25 25
26extern struct snd_soc_codec_device soc_codec_dev_wm9090;
27
28/* 26/*
29 * Register values. 27 * Register values.
30 */ 28 */
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 8793341849d1..a144acda751c 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -248,8 +248,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
248{ 248{
249 struct snd_pcm_runtime *runtime = substream->runtime; 249 struct snd_pcm_runtime *runtime = substream->runtime;
250 struct snd_soc_pcm_runtime *rtd = substream->private_data; 250 struct snd_soc_pcm_runtime *rtd = substream->private_data;
251 struct snd_soc_device *socdev = rtd->socdev; 251 struct snd_soc_codec *codec = rtd->codec;
252 struct snd_soc_codec *codec = socdev->card->codec;
253 int reg; 252 int reg;
254 u16 vra; 253 u16 vra;
255 254
@@ -273,9 +272,9 @@ static struct snd_soc_dai_ops wm9705_dai_ops = {
273 .prepare = ac97_prepare, 272 .prepare = ac97_prepare,
274}; 273};
275 274
276struct snd_soc_dai wm9705_dai[] = { 275static struct snd_soc_dai_driver wm9705_dai[] = {
277 { 276 {
278 .name = "AC97 HiFi", 277 .name = "wm9705-hifi",
279 .ac97_control = 1, 278 .ac97_control = 1,
280 .playback = { 279 .playback = {
281 .stream_name = "HiFi Playback", 280 .stream_name = "HiFi Playback",
@@ -294,7 +293,7 @@ struct snd_soc_dai wm9705_dai[] = {
294 .ops = &wm9705_dai_ops, 293 .ops = &wm9705_dai_ops,
295 }, 294 },
296 { 295 {
297 .name = "AC97 Aux", 296 .name = "wm9705-aux",
298 .playback = { 297 .playback = {
299 .stream_name = "Aux Playback", 298 .stream_name = "Aux Playback",
300 .channels_min = 1, 299 .channels_min = 1,
@@ -304,7 +303,6 @@ struct snd_soc_dai wm9705_dai[] = {
304 }, 303 },
305 } 304 }
306}; 305};
307EXPORT_SYMBOL_GPL(wm9705_dai);
308 306
309static int wm9705_reset(struct snd_soc_codec *codec) 307static int wm9705_reset(struct snd_soc_codec *codec)
310{ 308{
@@ -318,20 +316,15 @@ static int wm9705_reset(struct snd_soc_codec *codec)
318} 316}
319 317
320#ifdef CONFIG_PM 318#ifdef CONFIG_PM
321static int wm9705_soc_suspend(struct platform_device *pdev, pm_message_t msg) 319static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
322{ 320{
323 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
324 struct snd_soc_codec *codec = socdev->card->codec;
325
326 soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); 321 soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
327 322
328 return 0; 323 return 0;
329} 324}
330 325
331static int wm9705_soc_resume(struct platform_device *pdev) 326static int wm9705_soc_resume(struct snd_soc_codec *codec)
332{ 327{
333 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
334 struct snd_soc_codec *codec = socdev->card->codec;
335 int i, ret; 328 int i, ret;
336 u16 *cache = codec->reg_cache; 329 u16 *cache = codec->reg_cache;
337 330
@@ -352,49 +345,18 @@ static int wm9705_soc_resume(struct platform_device *pdev)
352#define wm9705_soc_resume NULL 345#define wm9705_soc_resume NULL
353#endif 346#endif
354 347
355static int wm9705_soc_probe(struct platform_device *pdev) 348static int wm9705_soc_probe(struct snd_soc_codec *codec)
356{ 349{
357 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
358 struct snd_soc_codec *codec;
359 int ret = 0; 350 int ret = 0;
360 351
361 printk(KERN_INFO "WM9705 SoC Audio Codec\n"); 352 printk(KERN_INFO "WM9705 SoC Audio Codec\n");
362 353
363 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
364 GFP_KERNEL);
365 if (socdev->card->codec == NULL)
366 return -ENOMEM;
367 codec = socdev->card->codec;
368 mutex_init(&codec->mutex);
369
370 codec->reg_cache = kmemdup(wm9705_reg, sizeof(wm9705_reg), GFP_KERNEL);
371 if (codec->reg_cache == NULL) {
372 ret = -ENOMEM;
373 goto cache_err;
374 }
375 codec->reg_cache_size = sizeof(wm9705_reg);
376 codec->reg_cache_step = 2;
377
378 codec->name = "WM9705";
379 codec->owner = THIS_MODULE;
380 codec->dai = wm9705_dai;
381 codec->num_dai = ARRAY_SIZE(wm9705_dai);
382 codec->write = ac97_write;
383 codec->read = ac97_read;
384 INIT_LIST_HEAD(&codec->dapm_widgets);
385 INIT_LIST_HEAD(&codec->dapm_paths);
386
387 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); 354 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
388 if (ret < 0) { 355 if (ret < 0) {
389 printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); 356 printk(KERN_ERR "wm9705: failed to register AC97 codec\n");
390 goto codec_err; 357 return ret;
391 } 358 }
392 359
393 /* register pcms */
394 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
395 if (ret < 0)
396 goto pcm_err;
397
398 ret = wm9705_reset(codec); 360 ret = wm9705_reset(codec);
399 if (ret) 361 if (ret)
400 goto reset_err; 362 goto reset_err;
@@ -406,40 +368,62 @@ static int wm9705_soc_probe(struct platform_device *pdev)
406 return 0; 368 return 0;
407 369
408reset_err: 370reset_err:
409 snd_soc_free_pcms(socdev);
410pcm_err:
411 snd_soc_free_ac97_codec(codec); 371 snd_soc_free_ac97_codec(codec);
412codec_err:
413 kfree(codec->reg_cache);
414cache_err:
415 kfree(socdev->card->codec);
416 socdev->card->codec = NULL;
417 return ret; 372 return ret;
418} 373}
419 374
420static int wm9705_soc_remove(struct platform_device *pdev) 375static int wm9705_soc_remove(struct snd_soc_codec *codec)
421{ 376{
422 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
423 struct snd_soc_codec *codec = socdev->card->codec;
424
425 if (codec == NULL)
426 return 0;
427
428 snd_soc_dapm_free(socdev);
429 snd_soc_free_pcms(socdev);
430 snd_soc_free_ac97_codec(codec); 377 snd_soc_free_ac97_codec(codec);
431 kfree(codec->reg_cache);
432 kfree(codec);
433 return 0; 378 return 0;
434} 379}
435 380
436struct snd_soc_codec_device soc_codec_dev_wm9705 = { 381static struct snd_soc_codec_driver soc_codec_dev_wm9705 = {
437 .probe = wm9705_soc_probe, 382 .probe = wm9705_soc_probe,
438 .remove = wm9705_soc_remove, 383 .remove = wm9705_soc_remove,
439 .suspend = wm9705_soc_suspend, 384 .suspend = wm9705_soc_suspend,
440 .resume = wm9705_soc_resume, 385 .resume = wm9705_soc_resume,
386 .read = ac97_read,
387 .write = ac97_write,
388 .reg_cache_size = ARRAY_SIZE(wm9705_reg),
389 .reg_word_size = sizeof(u16),
390 .reg_cache_step = 2,
391 .reg_cache_default = wm9705_reg,
392};
393
394static __devinit int wm9705_probe(struct platform_device *pdev)
395{
396 return snd_soc_register_codec(&pdev->dev,
397 &soc_codec_dev_wm9705, wm9705_dai, ARRAY_SIZE(wm9705_dai));
398}
399
400static int __devexit wm9705_remove(struct platform_device *pdev)
401{
402 snd_soc_unregister_codec(&pdev->dev);
403 return 0;
404}
405
406static struct platform_driver wm9705_codec_driver = {
407 .driver = {
408 .name = "wm9705-codec",
409 .owner = THIS_MODULE,
410 },
411
412 .probe = wm9705_probe,
413 .remove = __devexit_p(wm9705_remove),
441}; 414};
442EXPORT_SYMBOL_GPL(soc_codec_dev_wm9705); 415
416static int __init wm9705_init(void)
417{
418 return platform_driver_register(&wm9705_codec_driver);
419}
420module_init(wm9705_init);
421
422static void __exit wm9705_exit(void)
423{
424 platform_driver_unregister(&wm9705_codec_driver);
425}
426module_exit(wm9705_exit);
443 427
444MODULE_DESCRIPTION("ASoC WM9705 driver"); 428MODULE_DESCRIPTION("ASoC WM9705 driver");
445MODULE_AUTHOR("Ian Molton"); 429MODULE_AUTHOR("Ian Molton");
diff --git a/sound/soc/codecs/wm9705.h b/sound/soc/codecs/wm9705.h
index d380f110f9e2..23ea9ce47359 100644
--- a/sound/soc/codecs/wm9705.h
+++ b/sound/soc/codecs/wm9705.h
@@ -8,7 +8,4 @@
8#define WM9705_DAI_AC97_HIFI 0 8#define WM9705_DAI_AC97_HIFI 0
9#define WM9705_DAI_AC97_AUX 1 9#define WM9705_DAI_AC97_AUX 1
10 10
11extern struct snd_soc_dai wm9705_dai[2];
12extern struct snd_soc_codec_device soc_codec_dev_wm9705;
13
14#endif 11#endif
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 28790a2ffe8d..d2f224d62744 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -478,8 +478,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
478{ 478{
479 struct snd_pcm_runtime *runtime = substream->runtime; 479 struct snd_pcm_runtime *runtime = substream->runtime;
480 struct snd_soc_pcm_runtime *rtd = substream->private_data; 480 struct snd_soc_pcm_runtime *rtd = substream->private_data;
481 struct snd_soc_device *socdev = rtd->socdev; 481 struct snd_soc_codec *codec =rtd->codec;
482 struct snd_soc_codec *codec = socdev->card->codec;
483 int reg; 482 int reg;
484 u16 vra; 483 u16 vra;
485 484
@@ -499,8 +498,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
499{ 498{
500 struct snd_pcm_runtime *runtime = substream->runtime; 499 struct snd_pcm_runtime *runtime = substream->runtime;
501 struct snd_soc_pcm_runtime *rtd = substream->private_data; 500 struct snd_soc_pcm_runtime *rtd = substream->private_data;
502 struct snd_soc_device *socdev = rtd->socdev; 501 struct snd_soc_codec *codec = rtd->codec;
503 struct snd_soc_codec *codec = socdev->card->codec;
504 u16 vra, xsle; 502 u16 vra, xsle;
505 503
506 vra = ac97_read(codec, AC97_EXTENDED_STATUS); 504 vra = ac97_read(codec, AC97_EXTENDED_STATUS);
@@ -526,9 +524,9 @@ static struct snd_soc_dai_ops wm9712_dai_ops_aux = {
526 .prepare = ac97_aux_prepare, 524 .prepare = ac97_aux_prepare,
527}; 525};
528 526
529struct snd_soc_dai wm9712_dai[] = { 527static struct snd_soc_dai_driver wm9712_dai[] = {
530{ 528{
531 .name = "AC97 HiFi", 529 .name = "wm9712-hifi",
532 .ac97_control = 1, 530 .ac97_control = 1,
533 .playback = { 531 .playback = {
534 .stream_name = "HiFi Playback", 532 .stream_name = "HiFi Playback",
@@ -545,7 +543,7 @@ struct snd_soc_dai wm9712_dai[] = {
545 .ops = &wm9712_dai_ops_hifi, 543 .ops = &wm9712_dai_ops_hifi,
546}, 544},
547{ 545{
548 .name = "AC97 Aux", 546 .name = "wm9712-aux",
549 .playback = { 547 .playback = {
550 .stream_name = "Aux Playback", 548 .stream_name = "Aux Playback",
551 .channels_min = 1, 549 .channels_min = 1,
@@ -555,7 +553,6 @@ struct snd_soc_dai wm9712_dai[] = {
555 .ops = &wm9712_dai_ops_aux, 553 .ops = &wm9712_dai_ops_aux,
556} 554}
557}; 555};
558EXPORT_SYMBOL_GPL(wm9712_dai);
559 556
560static int wm9712_set_bias_level(struct snd_soc_codec *codec, 557static int wm9712_set_bias_level(struct snd_soc_codec *codec,
561 enum snd_soc_bias_level level) 558 enum snd_soc_bias_level level)
@@ -597,20 +594,15 @@ err:
597 return -EIO; 594 return -EIO;
598} 595}
599 596
600static int wm9712_soc_suspend(struct platform_device *pdev, 597static int wm9712_soc_suspend(struct snd_soc_codec *codec,
601 pm_message_t state) 598 pm_message_t state)
602{ 599{
603 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
604 struct snd_soc_codec *codec = socdev->card->codec;
605
606 wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF); 600 wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
607 return 0; 601 return 0;
608} 602}
609 603
610static int wm9712_soc_resume(struct platform_device *pdev) 604static int wm9712_soc_resume(struct snd_soc_codec *codec)
611{ 605{
612 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
613 struct snd_soc_codec *codec = socdev->card->codec;
614 int i, ret; 606 int i, ret;
615 u16 *cache = codec->reg_cache; 607 u16 *cache = codec->reg_cache;
616 608
@@ -635,51 +627,18 @@ static int wm9712_soc_resume(struct platform_device *pdev)
635 return ret; 627 return ret;
636} 628}
637 629
638static int wm9712_soc_probe(struct platform_device *pdev) 630static int wm9712_soc_probe(struct snd_soc_codec *codec)
639{ 631{
640 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
641 struct snd_soc_codec *codec;
642 int ret = 0; 632 int ret = 0;
643 633
644 printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION); 634 printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
645 635
646 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec),
647 GFP_KERNEL);
648 if (socdev->card->codec == NULL)
649 return -ENOMEM;
650 codec = socdev->card->codec;
651 mutex_init(&codec->mutex);
652
653 codec->reg_cache = kmemdup(wm9712_reg, sizeof(wm9712_reg), GFP_KERNEL);
654
655 if (codec->reg_cache == NULL) {
656 ret = -ENOMEM;
657 goto cache_err;
658 }
659 codec->reg_cache_size = sizeof(wm9712_reg);
660 codec->reg_cache_step = 2;
661
662 codec->name = "WM9712";
663 codec->owner = THIS_MODULE;
664 codec->dai = wm9712_dai;
665 codec->num_dai = ARRAY_SIZE(wm9712_dai);
666 codec->write = ac97_write;
667 codec->read = ac97_read;
668 codec->set_bias_level = wm9712_set_bias_level;
669 INIT_LIST_HEAD(&codec->dapm_widgets);
670 INIT_LIST_HEAD(&codec->dapm_paths);
671
672 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); 636 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
673 if (ret < 0) { 637 if (ret < 0) {
674 printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); 638 printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
675 goto codec_err; 639 return ret;
676 } 640 }
677 641
678 /* register pcms */
679 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
680 if (ret < 0)
681 goto pcm_err;
682
683 ret = wm9712_reset(codec, 0); 642 ret = wm9712_reset(codec, 0);
684 if (ret < 0) { 643 if (ret < 0) {
685 printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); 644 printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n");
@@ -697,42 +656,63 @@ static int wm9712_soc_probe(struct platform_device *pdev)
697 return 0; 656 return 0;
698 657
699reset_err: 658reset_err:
700 snd_soc_free_pcms(socdev);
701pcm_err:
702 snd_soc_free_ac97_codec(codec); 659 snd_soc_free_ac97_codec(codec);
703
704codec_err:
705 kfree(codec->reg_cache);
706
707cache_err:
708 kfree(socdev->card->codec);
709 socdev->card->codec = NULL;
710 return ret; 660 return ret;
711} 661}
712 662
713static int wm9712_soc_remove(struct platform_device *pdev) 663static int wm9712_soc_remove(struct snd_soc_codec *codec)
714{ 664{
715 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
716 struct snd_soc_codec *codec = socdev->card->codec;
717
718 if (codec == NULL)
719 return 0;
720
721 snd_soc_dapm_free(socdev);
722 snd_soc_free_pcms(socdev);
723 snd_soc_free_ac97_codec(codec); 665 snd_soc_free_ac97_codec(codec);
724 kfree(codec->reg_cache);
725 kfree(codec);
726 return 0; 666 return 0;
727} 667}
728 668
729struct snd_soc_codec_device soc_codec_dev_wm9712 = { 669static struct snd_soc_codec_driver soc_codec_dev_wm9712 = {
730 .probe = wm9712_soc_probe, 670 .probe = wm9712_soc_probe,
731 .remove = wm9712_soc_remove, 671 .remove = wm9712_soc_remove,
732 .suspend = wm9712_soc_suspend, 672 .suspend = wm9712_soc_suspend,
733 .resume = wm9712_soc_resume, 673 .resume = wm9712_soc_resume,
674 .read = ac97_read,
675 .write = ac97_write,
676 .set_bias_level = wm9712_set_bias_level,
677 .reg_cache_size = ARRAY_SIZE(wm9712_reg),
678 .reg_word_size = sizeof(u16),
679 .reg_cache_step = 2,
680 .reg_cache_default = wm9712_reg,
734}; 681};
735EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712); 682
683static __devinit int wm9712_probe(struct platform_device *pdev)
684{
685 return snd_soc_register_codec(&pdev->dev,
686 &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai));
687}
688
689static int __devexit wm9712_remove(struct platform_device *pdev)
690{
691 snd_soc_unregister_codec(&pdev->dev);
692 return 0;
693}
694
695static struct platform_driver wm9712_codec_driver = {
696 .driver = {
697 .name = "wm9712-codec",
698 .owner = THIS_MODULE,
699 },
700
701 .probe = wm9712_probe,
702 .remove = __devexit_p(wm9712_remove),
703};
704
705static int __init wm9712_init(void)
706{
707 return platform_driver_register(&wm9712_codec_driver);
708}
709module_init(wm9712_init);
710
711static void __exit wm9712_exit(void)
712{
713 platform_driver_unregister(&wm9712_codec_driver);
714}
715module_exit(wm9712_exit);
736 716
737MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver"); 717MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
738MODULE_AUTHOR("Liam Girdwood"); 718MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h
index d29e8a18ca6d..fb69c3aa4ed0 100644
--- a/sound/soc/codecs/wm9712.h
+++ b/sound/soc/codecs/wm9712.h
@@ -8,7 +8,4 @@
8#define WM9712_DAI_AC97_HIFI 0 8#define WM9712_DAI_AC97_HIFI 0
9#define WM9712_DAI_AC97_AUX 1 9#define WM9712_DAI_AC97_AUX 1
10 10
11extern struct snd_soc_dai wm9712_dai[2];
12extern struct snd_soc_codec_device soc_codec_dev_wm9712;
13
14#endif 11#endif
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 34e0c91092fa..7da13b07a53d 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1057,9 +1057,9 @@ static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
1057 .set_tristate = wm9713_set_dai_tristate, 1057 .set_tristate = wm9713_set_dai_tristate,
1058}; 1058};
1059 1059
1060struct snd_soc_dai wm9713_dai[] = { 1060static struct snd_soc_dai_driver wm9713_dai[] = {
1061{ 1061{
1062 .name = "AC97 HiFi", 1062 .name = "wm9713-hifi",
1063 .ac97_control = 1, 1063 .ac97_control = 1,
1064 .playback = { 1064 .playback = {
1065 .stream_name = "HiFi Playback", 1065 .stream_name = "HiFi Playback",
@@ -1076,7 +1076,7 @@ struct snd_soc_dai wm9713_dai[] = {
1076 .ops = &wm9713_dai_ops_hifi, 1076 .ops = &wm9713_dai_ops_hifi,
1077 }, 1077 },
1078 { 1078 {
1079 .name = "AC97 Aux", 1079 .name = "wm9713-aux",
1080 .playback = { 1080 .playback = {
1081 .stream_name = "Aux Playback", 1081 .stream_name = "Aux Playback",
1082 .channels_min = 1, 1082 .channels_min = 1,
@@ -1086,7 +1086,7 @@ struct snd_soc_dai wm9713_dai[] = {
1086 .ops = &wm9713_dai_ops_aux, 1086 .ops = &wm9713_dai_ops_aux,
1087 }, 1087 },
1088 { 1088 {
1089 .name = "WM9713 Voice", 1089 .name = "wm9713-voice",
1090 .playback = { 1090 .playback = {
1091 .stream_name = "Voice Playback", 1091 .stream_name = "Voice Playback",
1092 .channels_min = 1, 1092 .channels_min = 1,
@@ -1103,7 +1103,6 @@ struct snd_soc_dai wm9713_dai[] = {
1103 .symmetric_rates = 1, 1103 .symmetric_rates = 1,
1104 }, 1104 },
1105}; 1105};
1106EXPORT_SYMBOL_GPL(wm9713_dai);
1107 1106
1108int wm9713_reset(struct snd_soc_codec *codec, int try_warm) 1107int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
1109{ 1108{
@@ -1152,11 +1151,9 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec,
1152 return 0; 1151 return 0;
1153} 1152}
1154 1153
1155static int wm9713_soc_suspend(struct platform_device *pdev, 1154static int wm9713_soc_suspend(struct snd_soc_codec *codec,
1156 pm_message_t state) 1155 pm_message_t state)
1157{ 1156{
1158 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1159 struct snd_soc_codec *codec = socdev->card->codec;
1160 u16 reg; 1157 u16 reg;
1161 1158
1162 /* Disable everything except touchpanel - that will be handled 1159 /* Disable everything except touchpanel - that will be handled
@@ -1171,10 +1168,8 @@ static int wm9713_soc_suspend(struct platform_device *pdev,
1171 return 0; 1168 return 0;
1172} 1169}
1173 1170
1174static int wm9713_soc_resume(struct platform_device *pdev) 1171static int wm9713_soc_resume(struct snd_soc_codec *codec)
1175{ 1172{
1176 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1177 struct snd_soc_codec *codec = socdev->card->codec;
1178 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); 1173 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1179 int i, ret; 1174 int i, ret;
1180 u16 *cache = codec->reg_cache; 1175 u16 *cache = codec->reg_cache;
@@ -1204,53 +1199,20 @@ static int wm9713_soc_resume(struct platform_device *pdev)
1204 return ret; 1199 return ret;
1205} 1200}
1206 1201
1207static int wm9713_soc_probe(struct platform_device *pdev) 1202static int wm9713_soc_probe(struct snd_soc_codec *codec)
1208{ 1203{
1209 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1204 struct wm9713_priv *wm9713;
1210 struct snd_soc_codec *codec;
1211 int ret = 0, reg; 1205 int ret = 0, reg;
1212 1206
1213 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), 1207 wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL);
1214 GFP_KERNEL); 1208 if (wm9713 == NULL)
1215 if (socdev->card->codec == NULL)
1216 return -ENOMEM; 1209 return -ENOMEM;
1217 codec = socdev->card->codec; 1210 snd_soc_codec_set_drvdata(codec, wm9713);
1218 mutex_init(&codec->mutex);
1219
1220 codec->reg_cache = kmemdup(wm9713_reg, sizeof(wm9713_reg), GFP_KERNEL);
1221 if (codec->reg_cache == NULL) {
1222 ret = -ENOMEM;
1223 goto cache_err;
1224 }
1225 codec->reg_cache_size = sizeof(wm9713_reg);
1226 codec->reg_cache_step = 2;
1227
1228 snd_soc_codec_set_drvdata(codec, kzalloc(sizeof(struct wm9713_priv),
1229 GFP_KERNEL));
1230 if (snd_soc_codec_get_drvdata(codec) == NULL) {
1231 ret = -ENOMEM;
1232 goto priv_err;
1233 }
1234
1235 codec->name = "WM9713";
1236 codec->owner = THIS_MODULE;
1237 codec->dai = wm9713_dai;
1238 codec->num_dai = ARRAY_SIZE(wm9713_dai);
1239 codec->write = ac97_write;
1240 codec->read = ac97_read;
1241 codec->set_bias_level = wm9713_set_bias_level;
1242 INIT_LIST_HEAD(&codec->dapm_widgets);
1243 INIT_LIST_HEAD(&codec->dapm_paths);
1244 1211
1245 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); 1212 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
1246 if (ret < 0) 1213 if (ret < 0)
1247 goto codec_err; 1214 goto codec_err;
1248 1215
1249 /* register pcms */
1250 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1251 if (ret < 0)
1252 goto pcm_err;
1253
1254 /* do a cold reset for the controller and then try 1216 /* do a cold reset for the controller and then try
1255 * a warm reset followed by an optional cold reset for codec */ 1217 * a warm reset followed by an optional cold reset for codec */
1256 wm9713_reset(codec, 0); 1218 wm9713_reset(codec, 0);
@@ -1273,46 +1235,67 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1273 return 0; 1235 return 0;
1274 1236
1275reset_err: 1237reset_err:
1276 snd_soc_free_pcms(socdev);
1277pcm_err:
1278 snd_soc_free_ac97_codec(codec); 1238 snd_soc_free_ac97_codec(codec);
1279
1280codec_err: 1239codec_err:
1281 kfree(snd_soc_codec_get_drvdata(codec)); 1240 kfree(wm9713);
1282
1283priv_err:
1284 kfree(codec->reg_cache);
1285
1286cache_err:
1287 kfree(socdev->card->codec);
1288 socdev->card->codec = NULL;
1289 return ret; 1241 return ret;
1290} 1242}
1291 1243
1292static int wm9713_soc_remove(struct platform_device *pdev) 1244static int wm9713_soc_remove(struct snd_soc_codec *codec)
1293{ 1245{
1294 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1246 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1295 struct snd_soc_codec *codec = socdev->card->codec;
1296
1297 if (codec == NULL)
1298 return 0;
1299
1300 snd_soc_dapm_free(socdev);
1301 snd_soc_free_pcms(socdev);
1302 snd_soc_free_ac97_codec(codec); 1247 snd_soc_free_ac97_codec(codec);
1303 kfree(snd_soc_codec_get_drvdata(codec)); 1248 kfree(wm9713);
1304 kfree(codec->reg_cache);
1305 kfree(codec);
1306 return 0; 1249 return 0;
1307} 1250}
1308 1251
1309struct snd_soc_codec_device soc_codec_dev_wm9713 = { 1252static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
1310 .probe = wm9713_soc_probe, 1253 .probe = wm9713_soc_probe,
1311 .remove = wm9713_soc_remove, 1254 .remove = wm9713_soc_remove,
1312 .suspend = wm9713_soc_suspend, 1255 .suspend = wm9713_soc_suspend,
1313 .resume = wm9713_soc_resume, 1256 .resume = wm9713_soc_resume,
1257 .read = ac97_read,
1258 .write = ac97_write,
1259 .set_bias_level = wm9713_set_bias_level,
1260 .reg_cache_size = ARRAY_SIZE(wm9713_reg),
1261 .reg_word_size = sizeof(u16),
1262 .reg_cache_step = 2,
1263 .reg_cache_default = wm9713_reg,
1264};
1265
1266static __devinit int wm9713_probe(struct platform_device *pdev)
1267{
1268 return snd_soc_register_codec(&pdev->dev,
1269 &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
1270}
1271
1272static int __devexit wm9713_remove(struct platform_device *pdev)
1273{
1274 snd_soc_unregister_codec(&pdev->dev);
1275 return 0;
1276}
1277
1278static struct platform_driver wm9713_codec_driver = {
1279 .driver = {
1280 .name = "wm9713-codec",
1281 .owner = THIS_MODULE,
1282 },
1283
1284 .probe = wm9713_probe,
1285 .remove = __devexit_p(wm9713_remove),
1314}; 1286};
1315EXPORT_SYMBOL_GPL(soc_codec_dev_wm9713); 1287
1288static int __init wm9713_init(void)
1289{
1290 return platform_driver_register(&wm9713_codec_driver);
1291}
1292module_init(wm9713_init);
1293
1294static void __exit wm9713_exit(void)
1295{
1296 platform_driver_unregister(&wm9713_codec_driver);
1297}
1298module_exit(wm9713_exit);
1316 1299
1317MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver"); 1300MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
1318MODULE_AUTHOR("Liam Girdwood"); 1301MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm9713.h b/sound/soc/codecs/wm9713.h
index 63b8d81756e3..793da863a03d 100644
--- a/sound/soc/codecs/wm9713.h
+++ b/sound/soc/codecs/wm9713.h
@@ -45,9 +45,6 @@
45#define WM9713_DAI_AC97_AUX 1 45#define WM9713_DAI_AC97_AUX 1
46#define WM9713_DAI_PCM_VOICE 2 46#define WM9713_DAI_PCM_VOICE 2
47 47
48extern struct snd_soc_codec_device soc_codec_dev_wm9713;
49extern struct snd_soc_dai wm9713_dai[3];
50
51int wm9713_reset(struct snd_soc_codec *codec, int try_warm); 48int wm9713_reset(struct snd_soc_codec *codec, int try_warm);
52 49
53#endif 50#endif
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 97f74d6a33e6..2b07b17a6b2d 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -28,12 +28,9 @@
28#include <mach/mux.h> 28#include <mach/mux.h>
29 29
30#include "../codecs/tlv320aic3x.h" 30#include "../codecs/tlv320aic3x.h"
31#include "../codecs/cq93vc.h"
32#include "../codecs/spdif_transciever.h"
33#include "davinci-pcm.h" 31#include "davinci-pcm.h"
34#include "davinci-i2s.h" 32#include "davinci-i2s.h"
35#include "davinci-mcasp.h" 33#include "davinci-mcasp.h"
36#include "davinci-vcif.h"
37 34
38#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ 35#define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
39 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) 36 SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF)
@@ -41,8 +38,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params) 38 struct snd_pcm_hw_params *params)
42{ 39{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data; 40 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 41 struct snd_soc_dai *codec_dai = rtd->codec_dai;
45 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
46 int ret = 0; 43 int ret = 0;
47 unsigned sysclk; 44 unsigned sysclk;
48 45
@@ -87,7 +84,7 @@ static int evm_spdif_hw_params(struct snd_pcm_substream *substream,
87 struct snd_pcm_hw_params *params) 84 struct snd_pcm_hw_params *params)
88{ 85{
89 struct snd_soc_pcm_runtime *rtd = substream->private_data; 86 struct snd_soc_pcm_runtime *rtd = substream->private_data;
90 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 87 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
91 88
92 /* set cpu DAI configuration */ 89 /* set cpu DAI configuration */
93 return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); 90 return snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT);
@@ -132,8 +129,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
132}; 129};
133 130
134/* Logic for a aic3x as connected on a davinci-evm */ 131/* Logic for a aic3x as connected on a davinci-evm */
135static int evm_aic3x_init(struct snd_soc_codec *codec) 132static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
136{ 133{
134 struct snd_soc_codec *codec = rtd->codec;
135
137 /* Add davinci-evm specific widgets */ 136 /* Add davinci-evm specific widgets */
138 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, 137 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
139 ARRAY_SIZE(aic3x_dapm_widgets)); 138 ARRAY_SIZE(aic3x_dapm_widgets));
@@ -161,8 +160,10 @@ static int evm_aic3x_init(struct snd_soc_codec *codec)
161static struct snd_soc_dai_link evm_dai = { 160static struct snd_soc_dai_link evm_dai = {
162 .name = "TLV320AIC3X", 161 .name = "TLV320AIC3X",
163 .stream_name = "AIC3X", 162 .stream_name = "AIC3X",
164 .cpu_dai = &davinci_i2s_dai, 163 .cpu_dai_name = "davinci-mcasp.0",
165 .codec_dai = &aic3x_dai, 164 .codec_dai_name = "tlv320aic3x-hifi",
165 .codec_name = "tlv320aic3x-codec.0-001a",
166 .platform_name = "davinci-pcm-audio",
166 .init = evm_aic3x_init, 167 .init = evm_aic3x_init,
167 .ops = &evm_ops, 168 .ops = &evm_ops,
168}; 169};
@@ -171,40 +172,49 @@ static struct snd_soc_dai_link dm365_evm_dai = {
171#ifdef CONFIG_SND_DM365_AIC3X_CODEC 172#ifdef CONFIG_SND_DM365_AIC3X_CODEC
172 .name = "TLV320AIC3X", 173 .name = "TLV320AIC3X",
173 .stream_name = "AIC3X", 174 .stream_name = "AIC3X",
174 .cpu_dai = &davinci_i2s_dai, 175 .cpu_dai_name = "davinci-i2s",
175 .codec_dai = &aic3x_dai, 176 .codec_dai_name = "tlv320aic3x-hifi",
176 .init = evm_aic3x_init, 177 .init = evm_aic3x_init,
178 .codec_name = "tlv320aic3x-codec.0-001a",
177 .ops = &evm_ops, 179 .ops = &evm_ops,
178#elif defined(CONFIG_SND_DM365_VOICE_CODEC) 180#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
179 .name = "Voice Codec - CQ93VC", 181 .name = "Voice Codec - CQ93VC",
180 .stream_name = "CQ93", 182 .stream_name = "CQ93",
181 .cpu_dai = &davinci_vcif_dai, 183 .cpu_dai_name = "davinci-vcif",
182 .codec_dai = &cq93vc_dai, 184 .codec_dai_name = "cq93vc-hifi",
185 .codec_name = "cq93vc-codec",
183#endif 186#endif
187 .platform_name = "davinci-pcm-audio",
184}; 188};
185 189
186static struct snd_soc_dai_link dm6467_evm_dai[] = { 190static struct snd_soc_dai_link dm6467_evm_dai[] = {
187 { 191 {
188 .name = "TLV320AIC3X", 192 .name = "TLV320AIC3X",
189 .stream_name = "AIC3X", 193 .stream_name = "AIC3X",
190 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], 194 .cpu_dai_name= "davinci-mcasp.0",
191 .codec_dai = &aic3x_dai, 195 .codec_dai_name = "tlv320aic3x-hifi",
196 .platform_name ="davinci-pcm-audio",
197 .codec_name = "tlv320aic3x-codec.0-001a",
192 .init = evm_aic3x_init, 198 .init = evm_aic3x_init,
193 .ops = &evm_ops, 199 .ops = &evm_ops,
194 }, 200 },
195 { 201 {
196 .name = "McASP", 202 .name = "McASP",
197 .stream_name = "spdif", 203 .stream_name = "spdif",
198 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], 204 .cpu_dai_name= "davinci-mcasp.1",
199 .codec_dai = &dit_stub_dai, 205 .codec_dai_name = "dit-hifi",
206 .codec_name = "spdif_dit",
207 .platform_name = "davinci-pcm-audio",
200 .ops = &evm_spdif_ops, 208 .ops = &evm_spdif_ops,
201 }, 209 },
202}; 210};
203static struct snd_soc_dai_link da8xx_evm_dai = { 211static struct snd_soc_dai_link da8xx_evm_dai = {
204 .name = "TLV320AIC3X", 212 .name = "TLV320AIC3X",
205 .stream_name = "AIC3X", 213 .stream_name = "AIC3X",
206 .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], 214 .cpu_dai_name= "davinci-mcasp.0",
207 .codec_dai = &aic3x_dai, 215 .codec_dai_name = "tlv320aic3x-hifi",
216 .codec_name = "tlv320aic3x-codec.0-001a",
217 .platform_name = "davinci-pcm-audio",
208 .init = evm_aic3x_init, 218 .init = evm_aic3x_init,
209 .ops = &evm_ops, 219 .ops = &evm_ops,
210}; 220};
@@ -212,7 +222,6 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
212/* davinci dm6446, dm355 evm audio machine driver */ 222/* davinci dm6446, dm355 evm audio machine driver */
213static struct snd_soc_card snd_soc_card_evm = { 223static struct snd_soc_card snd_soc_card_evm = {
214 .name = "DaVinci EVM", 224 .name = "DaVinci EVM",
215 .platform = &davinci_soc_platform,
216 .dai_link = &evm_dai, 225 .dai_link = &evm_dai,
217 .num_links = 1, 226 .num_links = 1,
218}; 227};
@@ -220,16 +229,13 @@ static struct snd_soc_card snd_soc_card_evm = {
220/* davinci dm365 evm audio machine driver */ 229/* davinci dm365 evm audio machine driver */
221static struct snd_soc_card dm365_snd_soc_card_evm = { 230static struct snd_soc_card dm365_snd_soc_card_evm = {
222 .name = "DaVinci DM365 EVM", 231 .name = "DaVinci DM365 EVM",
223 .platform = &davinci_soc_platform,
224 .dai_link = &dm365_evm_dai, 232 .dai_link = &dm365_evm_dai,
225 .num_links = 1, 233 .num_links = 1,
226}; 234};
227 235
228
229/* davinci dm6467 evm audio machine driver */ 236/* davinci dm6467 evm audio machine driver */
230static struct snd_soc_card dm6467_snd_soc_card_evm = { 237static struct snd_soc_card dm6467_snd_soc_card_evm = {
231 .name = "DaVinci DM6467 EVM", 238 .name = "DaVinci DM6467 EVM",
232 .platform = &davinci_soc_platform,
233 .dai_link = dm6467_evm_dai, 239 .dai_link = dm6467_evm_dai,
234 .num_links = ARRAY_SIZE(dm6467_evm_dai), 240 .num_links = ARRAY_SIZE(dm6467_evm_dai),
235}; 241};
@@ -237,82 +243,40 @@ static struct snd_soc_card dm6467_snd_soc_card_evm = {
237static struct snd_soc_card da830_snd_soc_card = { 243static struct snd_soc_card da830_snd_soc_card = {
238 .name = "DA830/OMAP-L137 EVM", 244 .name = "DA830/OMAP-L137 EVM",
239 .dai_link = &da8xx_evm_dai, 245 .dai_link = &da8xx_evm_dai,
240 .platform = &davinci_soc_platform,
241 .num_links = 1, 246 .num_links = 1,
242}; 247};
243 248
244static struct snd_soc_card da850_snd_soc_card = { 249static struct snd_soc_card da850_snd_soc_card = {
245 .name = "DA850/OMAP-L138 EVM", 250 .name = "DA850/OMAP-L138 EVM",
246 .dai_link = &da8xx_evm_dai, 251 .dai_link = &da8xx_evm_dai,
247 .platform = &davinci_soc_platform,
248 .num_links = 1, 252 .num_links = 1,
249}; 253};
250 254
251static struct aic3x_setup_data aic3x_setup;
252
253/* evm audio subsystem */
254static struct snd_soc_device evm_snd_devdata = {
255 .card = &snd_soc_card_evm,
256 .codec_dev = &soc_codec_dev_aic3x,
257 .codec_data = &aic3x_setup,
258};
259
260/* evm audio subsystem */
261static struct snd_soc_device dm365_evm_snd_devdata = {
262 .card = &dm365_snd_soc_card_evm,
263#ifdef CONFIG_SND_DM365_AIC3X_CODEC
264 .codec_dev = &soc_codec_dev_aic3x,
265 .codec_data = &aic3x_setup,
266#elif defined(CONFIG_SND_DM365_VOICE_CODEC)
267 .codec_dev = &soc_codec_dev_cq93vc,
268#endif
269};
270
271/* evm audio subsystem */
272static struct snd_soc_device dm6467_evm_snd_devdata = {
273 .card = &dm6467_snd_soc_card_evm,
274 .codec_dev = &soc_codec_dev_aic3x,
275 .codec_data = &aic3x_setup,
276};
277
278/* evm audio subsystem */
279static struct snd_soc_device da830_evm_snd_devdata = {
280 .card = &da830_snd_soc_card,
281 .codec_dev = &soc_codec_dev_aic3x,
282 .codec_data = &aic3x_setup,
283};
284
285static struct snd_soc_device da850_evm_snd_devdata = {
286 .card = &da850_snd_soc_card,
287 .codec_dev = &soc_codec_dev_aic3x,
288 .codec_data = &aic3x_setup,
289};
290
291static struct platform_device *evm_snd_device; 255static struct platform_device *evm_snd_device;
292 256
293static int __init evm_init(void) 257static int __init evm_init(void)
294{ 258{
295 struct snd_soc_device *evm_snd_dev_data; 259 struct snd_soc_card *evm_snd_dev_data;
296 int index; 260 int index;
297 int ret; 261 int ret;
298 262
299 if (machine_is_davinci_evm()) { 263 if (machine_is_davinci_evm()) {
300 evm_snd_dev_data = &evm_snd_devdata; 264 evm_snd_dev_data = &snd_soc_card_evm;
301 index = 0; 265 index = 0;
302 } else if (machine_is_davinci_dm355_evm()) { 266 } else if (machine_is_davinci_dm355_evm()) {
303 evm_snd_dev_data = &evm_snd_devdata; 267 evm_snd_dev_data = &snd_soc_card_evm;
304 index = 1; 268 index = 1;
305 } else if (machine_is_davinci_dm365_evm()) { 269 } else if (machine_is_davinci_dm365_evm()) {
306 evm_snd_dev_data = &dm365_evm_snd_devdata; 270 evm_snd_dev_data = &dm365_snd_soc_card_evm;
307 index = 0; 271 index = 0;
308 } else if (machine_is_davinci_dm6467_evm()) { 272 } else if (machine_is_davinci_dm6467_evm()) {
309 evm_snd_dev_data = &dm6467_evm_snd_devdata; 273 evm_snd_dev_data = &dm6467_snd_soc_card_evm;
310 index = 0; 274 index = 0;
311 } else if (machine_is_davinci_da830_evm()) { 275 } else if (machine_is_davinci_da830_evm()) {
312 evm_snd_dev_data = &da830_evm_snd_devdata; 276 evm_snd_dev_data = &da830_snd_soc_card;
313 index = 1; 277 index = 1;
314 } else if (machine_is_davinci_da850_evm()) { 278 } else if (machine_is_davinci_da850_evm()) {
315 evm_snd_dev_data = &da850_evm_snd_devdata; 279 evm_snd_dev_data = &da850_snd_soc_card;
316 index = 0; 280 index = 0;
317 } else 281 } else
318 return -EINVAL; 282 return -EINVAL;
@@ -322,7 +286,6 @@ static int __init evm_init(void)
322 return -ENOMEM; 286 return -ENOMEM;
323 287
324 platform_set_drvdata(evm_snd_device, evm_snd_dev_data); 288 platform_set_drvdata(evm_snd_device, evm_snd_dev_data);
325 evm_snd_dev_data->dev = &evm_snd_device->dev;
326 ret = platform_device_add(evm_snd_device); 289 ret = platform_device_add(evm_snd_device);
327 if (ret) 290 if (ret)
328 platform_device_put(evm_snd_device); 291 platform_device_put(evm_snd_device);
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 9e8932abf158..d46b545d41f4 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -183,8 +183,7 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
183 struct snd_pcm_substream *substream) 183 struct snd_pcm_substream *substream)
184{ 184{
185 struct snd_soc_pcm_runtime *rtd = substream->private_data; 185 struct snd_soc_pcm_runtime *rtd = substream->private_data;
186 struct snd_soc_device *socdev = rtd->socdev; 186 struct snd_soc_platform *platform = rtd->platform;
187 struct snd_soc_platform *platform = socdev->card->platform;
188 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 187 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
189 u32 spcr; 188 u32 spcr;
190 u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; 189 u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
@@ -205,8 +204,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
205 if (playback) { 204 if (playback) {
206 /* Stop the DMA to avoid data loss */ 205 /* Stop the DMA to avoid data loss */
207 /* while the transmitter is out of reset to handle XSYNCERR */ 206 /* while the transmitter is out of reset to handle XSYNCERR */
208 if (platform->pcm_ops->trigger) { 207 if (platform->driver->ops->trigger) {
209 int ret = platform->pcm_ops->trigger(substream, 208 int ret = platform->driver->ops->trigger(substream,
210 SNDRV_PCM_TRIGGER_STOP); 209 SNDRV_PCM_TRIGGER_STOP);
211 if (ret < 0) 210 if (ret < 0)
212 printk(KERN_DEBUG "Playback DMA stop failed\n"); 211 printk(KERN_DEBUG "Playback DMA stop failed\n");
@@ -227,8 +226,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
227 toggle_clock(dev, playback); 226 toggle_clock(dev, playback);
228 227
229 /* Restart the DMA */ 228 /* Restart the DMA */
230 if (platform->pcm_ops->trigger) { 229 if (platform->driver->ops->trigger) {
231 int ret = platform->pcm_ops->trigger(substream, 230 int ret = platform->driver->ops->trigger(substream,
232 SNDRV_PCM_TRIGGER_START); 231 SNDRV_PCM_TRIGGER_START);
233 if (ret < 0) 232 if (ret < 0)
234 printk(KERN_DEBUG "Playback DMA start failed\n"); 233 printk(KERN_DEBUG "Playback DMA start failed\n");
@@ -263,7 +262,7 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
263static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 262static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
264 unsigned int fmt) 263 unsigned int fmt)
265{ 264{
266 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 265 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
267 unsigned int pcr; 266 unsigned int pcr;
268 unsigned int srgr; 267 unsigned int srgr;
269 /* Attention srgr is updated by hw_params! */ 268 /* Attention srgr is updated by hw_params! */
@@ -404,7 +403,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
404static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, 403static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
405 int div_id, int div) 404 int div_id, int div)
406{ 405{
407 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 406 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
408 407
409 if (div_id != DAVINCI_MCBSP_CLKGDV) 408 if (div_id != DAVINCI_MCBSP_CLKGDV)
410 return -ENODEV; 409 return -ENODEV;
@@ -417,7 +416,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
417 struct snd_pcm_hw_params *params, 416 struct snd_pcm_hw_params *params,
418 struct snd_soc_dai *dai) 417 struct snd_soc_dai *dai)
419{ 418{
420 struct davinci_mcbsp_dev *dev = dai->private_data; 419 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
421 struct davinci_pcm_dma_params *dma_params = 420 struct davinci_pcm_dma_params *dma_params =
422 &dev->dma_params[substream->stream]; 421 &dev->dma_params[substream->stream];
423 struct snd_interval *i = NULL; 422 struct snd_interval *i = NULL;
@@ -427,6 +426,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
427 snd_pcm_format_t fmt; 426 snd_pcm_format_t fmt;
428 unsigned element_cnt = 1; 427 unsigned element_cnt = 1;
429 428
429 dai->capture_dma_data = dev->dma_params;
430 dai->playback_dma_data = dev->dma_params;
431
430 /* general line settings */ 432 /* general line settings */
431 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 433 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
432 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 434 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -569,24 +571,18 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
569static int davinci_i2s_prepare(struct snd_pcm_substream *substream, 571static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
570 struct snd_soc_dai *dai) 572 struct snd_soc_dai *dai)
571{ 573{
572 struct davinci_mcbsp_dev *dev = dai->private_data; 574 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
573 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 575 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
574 davinci_mcbsp_stop(dev, playback); 576 davinci_mcbsp_stop(dev, playback);
575 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) {
576 /* codec is master */
577 davinci_mcbsp_start(dev, substream);
578 }
579 return 0; 577 return 0;
580} 578}
581 579
582static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 580static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
583 struct snd_soc_dai *dai) 581 struct snd_soc_dai *dai)
584{ 582{
585 struct davinci_mcbsp_dev *dev = dai->private_data; 583 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
586 int ret = 0; 584 int ret = 0;
587 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 585 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
588 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0)
589 return 0; /* return if codec is master */
590 586
591 switch (cmd) { 587 switch (cmd) {
592 case SNDRV_PCM_TRIGGER_START: 588 case SNDRV_PCM_TRIGGER_START:
@@ -608,7 +604,7 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
608static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, 604static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
609 struct snd_soc_dai *dai) 605 struct snd_soc_dai *dai)
610{ 606{
611 struct davinci_mcbsp_dev *dev = dai->private_data; 607 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
612 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 608 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
613 davinci_mcbsp_stop(dev, playback); 609 davinci_mcbsp_stop(dev, playback);
614} 610}
@@ -625,9 +621,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
625 621
626}; 622};
627 623
628struct snd_soc_dai davinci_i2s_dai = { 624static struct snd_soc_dai_driver davinci_i2s_dai = {
629 .name = "davinci-i2s",
630 .id = 0,
631 .playback = { 625 .playback = {
632 .channels_min = 2, 626 .channels_min = 2,
633 .channels_max = 2, 627 .channels_max = 2,
@@ -641,7 +635,6 @@ struct snd_soc_dai davinci_i2s_dai = {
641 .ops = &davinci_i2s_dai_ops, 635 .ops = &davinci_i2s_dai_ops,
642 636
643}; 637};
644EXPORT_SYMBOL_GPL(davinci_i2s_dai);
645 638
646static int davinci_i2s_probe(struct platform_device *pdev) 639static int davinci_i2s_probe(struct platform_device *pdev)
647{ 640{
@@ -720,10 +713,9 @@ static int davinci_i2s_probe(struct platform_device *pdev)
720 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; 713 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
721 dev->dev = &pdev->dev; 714 dev->dev = &pdev->dev;
722 715
723 davinci_i2s_dai.private_data = dev; 716 dev_set_drvdata(&pdev->dev, dev);
724 davinci_i2s_dai.capture.dma_data = dev->dma_params; 717
725 davinci_i2s_dai.playback.dma_data = dev->dma_params; 718 ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai);
726 ret = snd_soc_register_dai(&davinci_i2s_dai);
727 if (ret != 0) 719 if (ret != 0)
728 goto err_free_mem; 720 goto err_free_mem;
729 721
@@ -739,10 +731,10 @@ err_release_region:
739 731
740static int davinci_i2s_remove(struct platform_device *pdev) 732static int davinci_i2s_remove(struct platform_device *pdev)
741{ 733{
742 struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data; 734 struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);
743 struct resource *mem; 735 struct resource *mem;
744 736
745 snd_soc_unregister_dai(&davinci_i2s_dai); 737 snd_soc_unregister_dai(&pdev->dev);
746 clk_disable(dev->clk); 738 clk_disable(dev->clk);
747 clk_put(dev->clk); 739 clk_put(dev->clk);
748 dev->clk = NULL; 740 dev->clk = NULL;
@@ -757,7 +749,7 @@ static struct platform_driver davinci_mcbsp_driver = {
757 .probe = davinci_i2s_probe, 749 .probe = davinci_i2s_probe,
758 .remove = davinci_i2s_remove, 750 .remove = davinci_i2s_remove,
759 .driver = { 751 .driver = {
760 .name = "davinci-asp", 752 .name = "davinci-i2s",
761 .owner = THIS_MODULE, 753 .owner = THIS_MODULE,
762 }, 754 },
763}; 755};
diff --git a/sound/soc/davinci/davinci-i2s.h b/sound/soc/davinci/davinci-i2s.h
index 0b1e77b8c279..48dac3e2521a 100644
--- a/sound/soc/davinci/davinci-i2s.h
+++ b/sound/soc/davinci/davinci-i2s.h
@@ -17,6 +17,4 @@ enum davinci_mcbsp_div {
17 DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */ 17 DAVINCI_MCBSP_CLKGDV, /* Sample rate generator divider */
18}; 18};
19 19
20extern struct snd_soc_dai davinci_i2s_dai;
21
22#endif 20#endif
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index b24720894af6..86918ee12419 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -422,7 +422,7 @@ static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream)
422static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, 422static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
423 unsigned int fmt) 423 unsigned int fmt)
424{ 424{
425 struct davinci_audio_dev *dev = cpu_dai->private_data; 425 struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
426 void __iomem *base = dev->base; 426 void __iomem *base = dev->base;
427 427
428 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 428 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -709,12 +709,15 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
709 struct snd_pcm_hw_params *params, 709 struct snd_pcm_hw_params *params,
710 struct snd_soc_dai *cpu_dai) 710 struct snd_soc_dai *cpu_dai)
711{ 711{
712 struct davinci_audio_dev *dev = cpu_dai->private_data; 712 struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
713 struct davinci_pcm_dma_params *dma_params = 713 struct davinci_pcm_dma_params *dma_params =
714 &dev->dma_params[substream->stream]; 714 &dev->dma_params[substream->stream];
715 int word_length; 715 int word_length;
716 u8 fifo_level; 716 u8 fifo_level;
717 717
718 cpu_dai->capture_dma_data = dev->dma_params;
719 cpu_dai->playback_dma_data = dev->dma_params;
720
718 davinci_hw_common_param(dev, substream->stream); 721 davinci_hw_common_param(dev, substream->stream);
719 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 722 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
720 fifo_level = dev->txnumevt; 723 fifo_level = dev->txnumevt;
@@ -761,8 +764,7 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
761static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, 764static int davinci_mcasp_trigger(struct snd_pcm_substream *substream,
762 int cmd, struct snd_soc_dai *cpu_dai) 765 int cmd, struct snd_soc_dai *cpu_dai)
763{ 766{
764 struct snd_soc_pcm_runtime *rtd = substream->private_data; 767 struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
765 struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data;
766 int ret = 0; 768 int ret = 0;
767 769
768 switch (cmd) { 770 switch (cmd) {
@@ -804,10 +806,9 @@ static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
804 806
805}; 807};
806 808
807struct snd_soc_dai davinci_mcasp_dai[] = { 809static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
808 { 810 {
809 .name = "davinci-i2s", 811 .name = "davinci-mcasp.0",
810 .id = 0,
811 .playback = { 812 .playback = {
812 .channels_min = 2, 813 .channels_min = 2,
813 .channels_max = 2, 814 .channels_max = 2,
@@ -828,8 +829,7 @@ struct snd_soc_dai davinci_mcasp_dai[] = {
828 829
829 }, 830 },
830 { 831 {
831 .name = "davinci-dit", 832 "davinci-mcasp.1",
832 .id = 1,
833 .playback = { 833 .playback = {
834 .channels_min = 1, 834 .channels_min = 1,
835 .channels_max = 384, 835 .channels_max = 384,
@@ -840,7 +840,6 @@ struct snd_soc_dai davinci_mcasp_dai[] = {
840 }, 840 },
841 841
842}; 842};
843EXPORT_SYMBOL_GPL(davinci_mcasp_dai);
844 843
845static int davinci_mcasp_probe(struct platform_device *pdev) 844static int davinci_mcasp_probe(struct platform_device *pdev)
846{ 845{
@@ -899,6 +898,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
899 res = platform_get_resource(pdev, IORESOURCE_DMA, 0); 898 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
900 if (!res) { 899 if (!res) {
901 dev_err(&pdev->dev, "no DMA resource\n"); 900 dev_err(&pdev->dev, "no DMA resource\n");
901 ret = -ENODEV;
902 goto err_release_region; 902 goto err_release_region;
903 } 903 }
904 904
@@ -913,15 +913,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
913 res = platform_get_resource(pdev, IORESOURCE_DMA, 1); 913 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
914 if (!res) { 914 if (!res) {
915 dev_err(&pdev->dev, "no DMA resource\n"); 915 dev_err(&pdev->dev, "no DMA resource\n");
916 ret = -ENODEV;
916 goto err_release_region; 917 goto err_release_region;
917 } 918 }
918 919
919 dma_data->channel = res->start; 920 dma_data->channel = res->start;
920 davinci_mcasp_dai[pdata->op_mode].private_data = dev; 921 dev_set_drvdata(&pdev->dev, dev);
921 davinci_mcasp_dai[pdata->op_mode].capture.dma_data = dev->dma_params; 922 ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]);
922 davinci_mcasp_dai[pdata->op_mode].playback.dma_data = dev->dma_params;
923 davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
924 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
925 923
926 if (ret != 0) 924 if (ret != 0)
927 goto err_release_region; 925 goto err_release_region;
@@ -937,12 +935,10 @@ err_release_data:
937 935
938static int davinci_mcasp_remove(struct platform_device *pdev) 936static int davinci_mcasp_remove(struct platform_device *pdev)
939{ 937{
940 struct snd_platform_data *pdata = pdev->dev.platform_data; 938 struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev);
941 struct davinci_audio_dev *dev;
942 struct resource *mem; 939 struct resource *mem;
943 940
944 snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]); 941 snd_soc_unregister_dai(&pdev->dev);
945 dev = davinci_mcasp_dai[pdata->op_mode].private_data;
946 clk_disable(dev->clk); 942 clk_disable(dev->clk);
947 clk_put(dev->clk); 943 clk_put(dev->clk);
948 dev->clk = NULL; 944 dev->clk = NULL;
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index e755b5121ec7..4681acc63606 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -22,8 +22,6 @@
22#include <mach/asp.h> 22#include <mach/asp.h>
23#include "davinci-pcm.h" 23#include "davinci-pcm.h"
24 24
25extern struct snd_soc_dai davinci_mcasp_dai[];
26
27#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 25#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000
28#define DAVINCI_MCASP_I2S_DAI 0 26#define DAVINCI_MCASP_I2S_DAI 0
29#define DAVINCI_MCASP_DIT_DAI 1 27#define DAVINCI_MCASP_DIT_DAI 1
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index a7124116d2e0..9d35b8c1a624 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -653,7 +653,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
653 struct davinci_pcm_dma_params *pa; 653 struct davinci_pcm_dma_params *pa;
654 struct davinci_pcm_dma_params *params; 654 struct davinci_pcm_dma_params *params;
655 655
656 pa = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 656 pa = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
657 if (!pa) 657 if (!pa)
658 return -ENODEV; 658 return -ENODEV;
659 params = &pa[substream->stream]; 659 params = &pa[substream->stream];
@@ -821,7 +821,7 @@ static int davinci_pcm_new(struct snd_card *card,
821 if (!card->dev->coherent_dma_mask) 821 if (!card->dev->coherent_dma_mask)
822 card->dev->coherent_dma_mask = 0xffffffff; 822 card->dev->coherent_dma_mask = 0xffffffff;
823 823
824 if (dai->playback.channels_min) { 824 if (dai->driver->playback.channels_min) {
825 ret = davinci_pcm_preallocate_dma_buffer(pcm, 825 ret = davinci_pcm_preallocate_dma_buffer(pcm,
826 SNDRV_PCM_STREAM_PLAYBACK, 826 SNDRV_PCM_STREAM_PLAYBACK,
827 pcm_hardware_playback.buffer_bytes_max); 827 pcm_hardware_playback.buffer_bytes_max);
@@ -829,7 +829,7 @@ static int davinci_pcm_new(struct snd_card *card,
829 return ret; 829 return ret;
830 } 830 }
831 831
832 if (dai->capture.channels_min) { 832 if (dai->driver->capture.channels_min) {
833 ret = davinci_pcm_preallocate_dma_buffer(pcm, 833 ret = davinci_pcm_preallocate_dma_buffer(pcm,
834 SNDRV_PCM_STREAM_CAPTURE, 834 SNDRV_PCM_STREAM_CAPTURE,
835 pcm_hardware_capture.buffer_bytes_max); 835 pcm_hardware_capture.buffer_bytes_max);
@@ -840,25 +840,44 @@ static int davinci_pcm_new(struct snd_card *card,
840 return 0; 840 return 0;
841} 841}
842 842
843struct snd_soc_platform davinci_soc_platform = { 843static struct snd_soc_platform_driver davinci_soc_platform = {
844 .name = "davinci-audio", 844 .ops = &davinci_pcm_ops,
845 .pcm_ops = &davinci_pcm_ops,
846 .pcm_new = davinci_pcm_new, 845 .pcm_new = davinci_pcm_new,
847 .pcm_free = davinci_pcm_free, 846 .pcm_free = davinci_pcm_free,
848}; 847};
849EXPORT_SYMBOL_GPL(davinci_soc_platform);
850 848
851static int __init davinci_soc_platform_init(void) 849static int __devinit davinci_soc_platform_probe(struct platform_device *pdev)
852{ 850{
853 return snd_soc_register_platform(&davinci_soc_platform); 851 return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform);
854} 852}
855module_init(davinci_soc_platform_init);
856 853
857static void __exit davinci_soc_platform_exit(void) 854static int __devexit davinci_soc_platform_remove(struct platform_device *pdev)
858{ 855{
859 snd_soc_unregister_platform(&davinci_soc_platform); 856 snd_soc_unregister_platform(&pdev->dev);
857 return 0;
858}
859
860static struct platform_driver davinci_pcm_driver = {
861 .driver = {
862 .name = "davinci-pcm-audio",
863 .owner = THIS_MODULE,
864 },
865
866 .probe = davinci_soc_platform_probe,
867 .remove = __devexit_p(davinci_soc_platform_remove),
868};
869
870static int __init snd_davinci_pcm_init(void)
871{
872 return platform_driver_register(&davinci_pcm_driver);
873}
874module_init(snd_davinci_pcm_init);
875
876static void __exit snd_davinci_pcm_exit(void)
877{
878 platform_driver_unregister(&davinci_pcm_driver);
860} 879}
861module_exit(davinci_soc_platform_exit); 880module_exit(snd_davinci_pcm_exit);
862 881
863MODULE_AUTHOR("Vladimir Barinov"); 882MODULE_AUTHOR("Vladimir Barinov");
864MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); 883MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index b799a02333d8..c0d6c9be4b4d 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -28,7 +28,4 @@ struct davinci_pcm_dma_params {
28 unsigned int fifo_level; 28 unsigned int fifo_level;
29}; 29};
30 30
31
32extern struct snd_soc_platform davinci_soc_platform;
33
34#endif 31#endif
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
index 40eccfe9e358..009b6521a1bf 100644
--- a/sound/soc/davinci/davinci-sffsdr.c
+++ b/sound/soc/davinci/davinci-sffsdr.c
@@ -29,7 +29,6 @@
29#include <asm/plat-sffsdr/sffsdr-fpga.h> 29#include <asm/plat-sffsdr/sffsdr-fpga.h>
30#endif 30#endif
31 31
32#include <mach/mcbsp.h>
33#include <mach/edma.h> 32#include <mach/edma.h>
34 33
35#include "../codecs/pcm3008.h" 34#include "../codecs/pcm3008.h"
@@ -48,7 +47,7 @@ static int sffsdr_hw_params(struct snd_pcm_substream *substream,
48 struct snd_pcm_hw_params *params) 47 struct snd_pcm_hw_params *params)
49{ 48{
50 struct snd_soc_pcm_runtime *rtd = substream->private_data; 49 struct snd_soc_pcm_runtime *rtd = substream->private_data;
51 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 50 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
52 int fs; 51 int fs;
53 int ret = 0; 52 int ret = 0;
54 53
@@ -85,15 +84,16 @@ static struct snd_soc_ops sffsdr_ops = {
85static struct snd_soc_dai_link sffsdr_dai = { 84static struct snd_soc_dai_link sffsdr_dai = {
86 .name = "PCM3008", /* Codec name */ 85 .name = "PCM3008", /* Codec name */
87 .stream_name = "PCM3008 HiFi", 86 .stream_name = "PCM3008 HiFi",
88 .cpu_dai = &davinci_i2s_dai, 87 .cpu_dai_name = "davinci-asp.0",
89 .codec_dai = &pcm3008_dai, 88 .codec_dai_name = "pcm3008-hifi",
89 .codec_name = "pcm3008-codec",
90 .platform_name = "davinci-pcm-audio",
90 .ops = &sffsdr_ops, 91 .ops = &sffsdr_ops,
91}; 92};
92 93
93/* davinci-sffsdr audio machine driver */ 94/* davinci-sffsdr audio machine driver */
94static struct snd_soc_card snd_soc_sffsdr = { 95static struct snd_soc_card snd_soc_sffsdr = {
95 .name = "DaVinci SFFSDR", 96 .name = "DaVinci SFFSDR",
96 .platform = &davinci_soc_platform,
97 .dai_link = &sffsdr_dai, 97 .dai_link = &sffsdr_dai,
98 .num_links = 1, 98 .num_links = 1,
99}; 99};
@@ -106,11 +106,12 @@ static struct pcm3008_setup_data sffsdr_pcm3008_setup = {
106 .pdda_pin = GPIO(38), 106 .pdda_pin = GPIO(38),
107}; 107};
108 108
109/* sffsdr audio subsystem */ 109struct platform_device pcm3008_codec = {
110static struct snd_soc_device sffsdr_snd_devdata = { 110 .name = "pcm3008-codec",
111 .card = &snd_soc_sffsdr, 111 .id = 0,
112 .codec_dev = &soc_codec_dev_pcm3008, 112 .dev = {
113 .codec_data = &sffsdr_pcm3008_setup, 113 .platform_data = &sffsdr_pcm3008_setup,
114 },
114}; 115};
115 116
116static struct resource sffsdr_snd_resources[] = { 117static struct resource sffsdr_snd_resources[] = {
@@ -135,14 +136,15 @@ static int __init sffsdr_init(void)
135 if (!machine_is_sffsdr()) 136 if (!machine_is_sffsdr())
136 return -EINVAL; 137 return -EINVAL;
137 138
139 platform_device_register(&pcm3008_codec);
140
138 sffsdr_snd_device = platform_device_alloc("soc-audio", 0); 141 sffsdr_snd_device = platform_device_alloc("soc-audio", 0);
139 if (!sffsdr_snd_device) { 142 if (!sffsdr_snd_device) {
140 printk(KERN_ERR "platform device allocation failed\n"); 143 printk(KERN_ERR "platform device allocation failed\n");
141 return -ENOMEM; 144 return -ENOMEM;
142 } 145 }
143 146
144 platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata); 147 platform_set_drvdata(sffsdr_snd_device, &snd_soc_sffsdr);
145 sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev;
146 platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data, 148 platform_device_add_data(sffsdr_snd_device, &sffsdr_snd_data,
147 sizeof(sffsdr_snd_data)); 149 sizeof(sffsdr_snd_data));
148 150
@@ -150,7 +152,7 @@ static int __init sffsdr_init(void)
150 sffsdr_snd_resources, 152 sffsdr_snd_resources,
151 ARRAY_SIZE(sffsdr_snd_resources)); 153 ARRAY_SIZE(sffsdr_snd_resources));
152 if (ret) { 154 if (ret) {
153 printk(KERN_ERR "platform device add ressources failed\n"); 155 printk(KERN_ERR "platform device add resources failed\n");
154 goto error; 156 goto error;
155 } 157 }
156 158
@@ -168,6 +170,7 @@ error:
168static void __exit sffsdr_exit(void) 170static void __exit sffsdr_exit(void)
169{ 171{
170 platform_device_unregister(sffsdr_snd_device); 172 platform_device_unregister(sffsdr_snd_device);
173 platform_device_unregister(&pcm3008_codec);
171} 174}
172 175
173module_init(sffsdr_init); 176module_init(sffsdr_init);
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 48678533da7a..ea232f6a2c21 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -36,7 +36,6 @@
36 36
37#include "davinci-pcm.h" 37#include "davinci-pcm.h"
38#include "davinci-i2s.h" 38#include "davinci-i2s.h"
39#include "davinci-vcif.h"
40 39
41#define MOD_REG_BIT(val, mask, set) do { \ 40#define MOD_REG_BIT(val, mask, set) do { \
42 if (set) { \ 41 if (set) { \
@@ -55,7 +54,7 @@ static void davinci_vcif_start(struct snd_pcm_substream *substream)
55{ 54{
56 struct snd_soc_pcm_runtime *rtd = substream->private_data; 55 struct snd_soc_pcm_runtime *rtd = substream->private_data;
57 struct davinci_vcif_dev *davinci_vcif_dev = 56 struct davinci_vcif_dev *davinci_vcif_dev =
58 rtd->dai->cpu_dai->private_data; 57 snd_soc_dai_get_drvdata(rtd->cpu_dai);
59 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; 58 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
60 u32 w; 59 u32 w;
61 60
@@ -74,7 +73,7 @@ static void davinci_vcif_stop(struct snd_pcm_substream *substream)
74{ 73{
75 struct snd_soc_pcm_runtime *rtd = substream->private_data; 74 struct snd_soc_pcm_runtime *rtd = substream->private_data;
76 struct davinci_vcif_dev *davinci_vcif_dev = 75 struct davinci_vcif_dev *davinci_vcif_dev =
77 rtd->dai->cpu_dai->private_data; 76 snd_soc_dai_get_drvdata(rtd->cpu_dai);
78 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; 77 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
79 u32 w; 78 u32 w;
80 79
@@ -92,12 +91,15 @@ static int davinci_vcif_hw_params(struct snd_pcm_substream *substream,
92 struct snd_pcm_hw_params *params, 91 struct snd_pcm_hw_params *params,
93 struct snd_soc_dai *dai) 92 struct snd_soc_dai *dai)
94{ 93{
95 struct davinci_vcif_dev *davinci_vcif_dev = dai->private_data; 94 struct davinci_vcif_dev *davinci_vcif_dev = snd_soc_dai_get_drvdata(dai);
96 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc; 95 struct davinci_vc *davinci_vc = davinci_vcif_dev->davinci_vc;
97 struct davinci_pcm_dma_params *dma_params = 96 struct davinci_pcm_dma_params *dma_params =
98 &davinci_vcif_dev->dma_params[substream->stream]; 97 &davinci_vcif_dev->dma_params[substream->stream];
99 u32 w; 98 u32 w;
100 99
100 dai->capture_dma_data = davinci_vcif_dev->dma_params;
101 dai->playback_dma_data = davinci_vcif_dev->dma_params;
102
101 /* Restart the codec before setup */ 103 /* Restart the codec before setup */
102 davinci_vcif_stop(substream); 104 davinci_vcif_stop(substream);
103 davinci_vcif_start(substream); 105 davinci_vcif_start(substream);
@@ -179,8 +181,7 @@ static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
179 .hw_params = davinci_vcif_hw_params, 181 .hw_params = davinci_vcif_hw_params,
180}; 182};
181 183
182struct snd_soc_dai davinci_vcif_dai = { 184static struct snd_soc_dai_driver davinci_vcif_dai = {
183 .name = "davinci-vcif",
184 .playback = { 185 .playback = {
185 .channels_min = 1, 186 .channels_min = 1,
186 .channels_max = 2, 187 .channels_max = 2,
@@ -194,7 +195,6 @@ struct snd_soc_dai davinci_vcif_dai = {
194 .ops = &davinci_vcif_dai_ops, 195 .ops = &davinci_vcif_dai_ops,
195 196
196}; 197};
197EXPORT_SYMBOL_GPL(davinci_vcif_dai);
198 198
199static int davinci_vcif_probe(struct platform_device *pdev) 199static int davinci_vcif_probe(struct platform_device *pdev)
200{ 200{
@@ -222,12 +222,9 @@ static int davinci_vcif_probe(struct platform_device *pdev)
222 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr = 222 davinci_vcif_dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].dma_addr =
223 davinci_vc->davinci_vcif.dma_rx_addr; 223 davinci_vc->davinci_vcif.dma_rx_addr;
224 224
225 davinci_vcif_dai.dev = &pdev->dev; 225 dev_set_drvdata(&pdev->dev, davinci_vcif_dev);
226 davinci_vcif_dai.capture.dma_data = davinci_vcif_dev->dma_params;
227 davinci_vcif_dai.playback.dma_data = davinci_vcif_dev->dma_params;
228 davinci_vcif_dai.private_data = davinci_vcif_dev;
229 226
230 ret = snd_soc_register_dai(&davinci_vcif_dai); 227 ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai);
231 if (ret != 0) { 228 if (ret != 0) {
232 dev_err(&pdev->dev, "could not register dai\n"); 229 dev_err(&pdev->dev, "could not register dai\n");
233 goto fail; 230 goto fail;
@@ -243,7 +240,7 @@ fail:
243 240
244static int davinci_vcif_remove(struct platform_device *pdev) 241static int davinci_vcif_remove(struct platform_device *pdev)
245{ 242{
246 snd_soc_unregister_dai(&davinci_vcif_dai); 243 snd_soc_unregister_dai(&pdev->dev);
247 244
248 return 0; 245 return 0;
249} 246}
@@ -252,7 +249,7 @@ static struct platform_driver davinci_vcif_driver = {
252 .probe = davinci_vcif_probe, 249 .probe = davinci_vcif_probe,
253 .remove = davinci_vcif_remove, 250 .remove = davinci_vcif_remove,
254 .driver = { 251 .driver = {
255 .name = "davinci_vcif", 252 .name = "davinci-vcif",
256 .owner = THIS_MODULE, 253 .owner = THIS_MODULE,
257 }, 254 },
258}; 255};
diff --git a/sound/soc/davinci/davinci-vcif.h b/sound/soc/davinci/davinci-vcif.h
deleted file mode 100644
index 571c9948724f..000000000000
--- a/sound/soc/davinci/davinci-vcif.h
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * ALSA SoC Voice Codec Interface for TI DAVINCI processor
3 *
4 * Copyright (C) 2010 Texas Instruments.
5 *
6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#ifndef _DAVINCI_VCIF_H
24#define _DAVINCI_VCIF_H
25
26extern struct snd_soc_dai davinci_vcif_dai;
27
28#endif
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index f617f560f46b..57429041189c 100644
--- a/sound/soc/ep93xx/Kconfig
+++ b/sound/soc/ep93xx/Kconfig
@@ -3,11 +3,16 @@ config SND_EP93XX_SOC
3 depends on ARCH_EP93XX && SND_SOC 3 depends on ARCH_EP93XX && SND_SOC
4 help 4 help
5 Say Y or M if you want to add support for codecs attached to 5 Say Y or M if you want to add support for codecs attached to
6 the EP93xx I2S interface. 6 the EP93xx I2S or AC97 interfaces.
7 7
8config SND_EP93XX_SOC_I2S 8config SND_EP93XX_SOC_I2S
9 tristate 9 tristate
10 10
11config SND_EP93XX_SOC_AC97
12 tristate
13 select AC97_BUS
14 select SND_SOC_AC97_BUS
15
11config SND_EP93XX_SOC_SNAPPERCL15 16config SND_EP93XX_SOC_SNAPPERCL15
12 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module" 17 tristate "SoC Audio support for Bluewater Systems Snapper CL15 module"
13 depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15 18 depends on SND_EP93XX_SOC && MACH_SNAPPER_CL15
@@ -16,3 +21,12 @@ config SND_EP93XX_SOC_SNAPPERCL15
16 help 21 help
17 Say Y or M here if you want to add support for I2S audio on the 22 Say Y or M here if you want to add support for I2S audio on the
18 Bluewater Systems Snapper CL15 module. 23 Bluewater Systems Snapper CL15 module.
24
25config SND_EP93XX_SOC_SIMONE
26 tristate "SoC Audio support for Simplemachines Sim.One board"
27 depends on SND_EP93XX_SOC && MACH_SIM_ONE
28 select SND_EP93XX_SOC_AC97
29 select SND_SOC_AC97_CODEC
30 help
31 Say Y or M here if you want to add support for AC97 audio on the
32 Simplemachines Sim.One board.
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/ep93xx/Makefile
index 272e60f57b9a..8e7977fb6b7d 100644
--- a/sound/soc/ep93xx/Makefile
+++ b/sound/soc/ep93xx/Makefile
@@ -1,11 +1,15 @@
1# EP93xx Platform Support 1# EP93xx Platform Support
2snd-soc-ep93xx-objs := ep93xx-pcm.o 2snd-soc-ep93xx-objs := ep93xx-pcm.o
3snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o 3snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o
4snd-soc-ep93xx-ac97-objs := ep93xx-ac97.o
4 5
5obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o 6obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o
6obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o 7obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o
8obj-$(CONFIG_SND_EP93XX_SOC_AC97) += snd-soc-ep93xx-ac97.o
7 9
8# EP93XX Machine Support 10# EP93XX Machine Support
9snd-soc-snappercl15-objs := snappercl15.o 11snd-soc-snappercl15-objs := snappercl15.o
12snd-soc-simone-objs := simone.o
10 13
11obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o 14obj-$(CONFIG_SND_EP93XX_SOC_SNAPPERCL15) += snd-soc-snappercl15.o
15obj-$(CONFIG_SND_EP93XX_SOC_SIMONE) += snd-soc-simone.o
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
new file mode 100644
index 000000000000..68a0bae1208a
--- /dev/null
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -0,0 +1,468 @@
1/*
2 * ASoC driver for Cirrus Logic EP93xx AC97 controller.
3 *
4 * Copyright (c) 2010 Mika Westerberg
5 *
6 * Based on s3c-ac97 ASoC driver by Jaswinder Singh.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/delay.h>
14#include <linux/io.h>
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/slab.h>
19
20#include <sound/core.h>
21#include <sound/ac97_codec.h>
22#include <sound/soc.h>
23
24#include <mach/dma.h>
25#include "ep93xx-pcm.h"
26
27/*
28 * Per channel (1-4) registers.
29 */
30#define AC97CH(n) (((n) - 1) * 0x20)
31
32#define AC97DR(n) (AC97CH(n) + 0x0000)
33
34#define AC97RXCR(n) (AC97CH(n) + 0x0004)
35#define AC97RXCR_REN BIT(0)
36#define AC97RXCR_RX3 BIT(3)
37#define AC97RXCR_RX4 BIT(4)
38#define AC97RXCR_CM BIT(15)
39
40#define AC97TXCR(n) (AC97CH(n) + 0x0008)
41#define AC97TXCR_TEN BIT(0)
42#define AC97TXCR_TX3 BIT(3)
43#define AC97TXCR_TX4 BIT(4)
44#define AC97TXCR_CM BIT(15)
45
46#define AC97SR(n) (AC97CH(n) + 0x000c)
47#define AC97SR_TXFE BIT(1)
48#define AC97SR_TXUE BIT(6)
49
50#define AC97RISR(n) (AC97CH(n) + 0x0010)
51#define AC97ISR(n) (AC97CH(n) + 0x0014)
52#define AC97IE(n) (AC97CH(n) + 0x0018)
53
54/*
55 * Global AC97 controller registers.
56 */
57#define AC97S1DATA 0x0080
58#define AC97S2DATA 0x0084
59#define AC97S12DATA 0x0088
60
61#define AC97RGIS 0x008c
62#define AC97GIS 0x0090
63#define AC97IM 0x0094
64/*
65 * Common bits for RGIS, GIS and IM registers.
66 */
67#define AC97_SLOT2RXVALID BIT(1)
68#define AC97_CODECREADY BIT(5)
69#define AC97_SLOT2TXCOMPLETE BIT(6)
70
71#define AC97EOI 0x0098
72#define AC97EOI_WINT BIT(0)
73#define AC97EOI_CODECREADY BIT(1)
74
75#define AC97GCR 0x009c
76#define AC97GCR_AC97IFE BIT(0)
77
78#define AC97RESET 0x00a0
79#define AC97RESET_TIMEDRESET BIT(0)
80
81#define AC97SYNC 0x00a4
82#define AC97SYNC_TIMEDSYNC BIT(0)
83
84#define AC97_TIMEOUT msecs_to_jiffies(5)
85
86/**
87 * struct ep93xx_ac97_info - EP93xx AC97 controller info structure
88 * @lock: mutex serializing access to the bus (slot 1 & 2 ops)
89 * @dev: pointer to the platform device dev structure
90 * @mem: physical memory resource for the registers
91 * @regs: mapped AC97 controller registers
92 * @irq: AC97 interrupt number
93 * @done: bus ops wait here for an interrupt
94 */
95struct ep93xx_ac97_info {
96 struct mutex lock;
97 struct device *dev;
98 struct resource *mem;
99 void __iomem *regs;
100 int irq;
101 struct completion done;
102};
103
104/* currently ALSA only supports a single AC97 device */
105static struct ep93xx_ac97_info *ep93xx_ac97_info;
106
107static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_out = {
108 .name = "ac97-pcm-out",
109 .dma_port = EP93XX_DMA_M2P_PORT_AAC1,
110};
111
112static struct ep93xx_pcm_dma_params ep93xx_ac97_pcm_in = {
113 .name = "ac97-pcm-in",
114 .dma_port = EP93XX_DMA_M2P_PORT_AAC1,
115};
116
117static inline unsigned ep93xx_ac97_read_reg(struct ep93xx_ac97_info *info,
118 unsigned reg)
119{
120 return __raw_readl(info->regs + reg);
121}
122
123static inline void ep93xx_ac97_write_reg(struct ep93xx_ac97_info *info,
124 unsigned reg, unsigned val)
125{
126 __raw_writel(val, info->regs + reg);
127}
128
129static unsigned short ep93xx_ac97_read(struct snd_ac97 *ac97,
130 unsigned short reg)
131{
132 struct ep93xx_ac97_info *info = ep93xx_ac97_info;
133 unsigned short val;
134
135 mutex_lock(&info->lock);
136
137 ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
138 ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2RXVALID);
139 if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT)) {
140 dev_warn(info->dev, "timeout reading register %x\n", reg);
141 mutex_unlock(&info->lock);
142 return -ETIMEDOUT;
143 }
144 val = (unsigned short)ep93xx_ac97_read_reg(info, AC97S2DATA);
145
146 mutex_unlock(&info->lock);
147 return val;
148}
149
150static void ep93xx_ac97_write(struct snd_ac97 *ac97,
151 unsigned short reg,
152 unsigned short val)
153{
154 struct ep93xx_ac97_info *info = ep93xx_ac97_info;
155
156 mutex_lock(&info->lock);
157
158 /*
159 * Writes to the codec need to be done so that slot 2 is filled in
160 * before slot 1.
161 */
162 ep93xx_ac97_write_reg(info, AC97S2DATA, val);
163 ep93xx_ac97_write_reg(info, AC97S1DATA, reg);
164
165 ep93xx_ac97_write_reg(info, AC97IM, AC97_SLOT2TXCOMPLETE);
166 if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
167 dev_warn(info->dev, "timeout writing register %x\n", reg);
168
169 mutex_unlock(&info->lock);
170}
171
172static void ep93xx_ac97_warm_reset(struct snd_ac97 *ac97)
173{
174 struct ep93xx_ac97_info *info = ep93xx_ac97_info;
175
176 mutex_lock(&info->lock);
177
178 /*
179 * We are assuming that before this functions gets called, the codec
180 * BIT_CLK is stopped by forcing the codec into powerdown mode. We can
181 * control the SYNC signal directly via AC97SYNC register. Using
182 * TIMEDSYNC the controller will keep the SYNC high > 1us.
183 */
184 ep93xx_ac97_write_reg(info, AC97SYNC, AC97SYNC_TIMEDSYNC);
185 ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
186 if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
187 dev_warn(info->dev, "codec warm reset timeout\n");
188
189 mutex_unlock(&info->lock);
190}
191
192static void ep93xx_ac97_cold_reset(struct snd_ac97 *ac97)
193{
194 struct ep93xx_ac97_info *info = ep93xx_ac97_info;
195
196 mutex_lock(&info->lock);
197
198 /*
199 * For doing cold reset, we disable the AC97 controller interface, clear
200 * WINT and CODECREADY bits, and finally enable the interface again.
201 */
202 ep93xx_ac97_write_reg(info, AC97GCR, 0);
203 ep93xx_ac97_write_reg(info, AC97EOI, AC97EOI_CODECREADY | AC97EOI_WINT);
204 ep93xx_ac97_write_reg(info, AC97GCR, AC97GCR_AC97IFE);
205
206 /*
207 * Now, assert the reset and wait for the codec to become ready.
208 */
209 ep93xx_ac97_write_reg(info, AC97RESET, AC97RESET_TIMEDRESET);
210 ep93xx_ac97_write_reg(info, AC97IM, AC97_CODECREADY);
211 if (!wait_for_completion_timeout(&info->done, AC97_TIMEOUT))
212 dev_warn(info->dev, "codec cold reset timeout\n");
213
214 /*
215 * Give the codec some time to come fully out from the reset. This way
216 * we ensure that the subsequent reads/writes will work.
217 */
218 usleep_range(15000, 20000);
219
220 mutex_unlock(&info->lock);
221}
222
223static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id)
224{
225 struct ep93xx_ac97_info *info = dev_id;
226 unsigned status, mask;
227
228 /*
229 * Just mask out the interrupt and wake up the waiting thread.
230 * Interrupts are cleared via reading/writing to slot 1 & 2 registers by
231 * the waiting thread.
232 */
233 status = ep93xx_ac97_read_reg(info, AC97GIS);
234 mask = ep93xx_ac97_read_reg(info, AC97IM);
235 mask &= ~status;
236 ep93xx_ac97_write_reg(info, AC97IM, mask);
237
238 complete(&info->done);
239 return IRQ_HANDLED;
240}
241
242struct snd_ac97_bus_ops soc_ac97_ops = {
243 .read = ep93xx_ac97_read,
244 .write = ep93xx_ac97_write,
245 .reset = ep93xx_ac97_cold_reset,
246 .warm_reset = ep93xx_ac97_warm_reset,
247};
248EXPORT_SYMBOL_GPL(soc_ac97_ops);
249
250static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
251 int cmd, struct snd_soc_dai *dai)
252{
253 struct ep93xx_ac97_info *info = snd_soc_dai_get_drvdata(dai);
254 unsigned v = 0;
255
256
257 switch (cmd) {
258 case SNDRV_PCM_TRIGGER_START:
259 case SNDRV_PCM_TRIGGER_RESUME:
260 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
261 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
262 /*
263 * Enable compact mode, TX slots 3 & 4, and the TX FIFO
264 * itself.
265 */
266 v |= AC97TXCR_CM;
267 v |= AC97TXCR_TX3 | AC97TXCR_TX4;
268 v |= AC97TXCR_TEN;
269 ep93xx_ac97_write_reg(info, AC97TXCR(1), v);
270 } else {
271 /*
272 * Enable compact mode, RX slots 3 & 4, and the RX FIFO
273 * itself.
274 */
275 v |= AC97RXCR_CM;
276 v |= AC97RXCR_RX3 | AC97RXCR_RX4;
277 v |= AC97RXCR_REN;
278 ep93xx_ac97_write_reg(info, AC97RXCR(1), v);
279 }
280 break;
281
282 case SNDRV_PCM_TRIGGER_STOP:
283 case SNDRV_PCM_TRIGGER_SUSPEND:
284 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
285 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
286 /*
287 * As per Cirrus EP93xx errata described below:
288 *
289 * http://www.cirrus.com/en/pubs/errata/ER667E2B.pdf
290 *
291 * we will wait for the TX FIFO to be empty before
292 * clearing the TEN bit.
293 */
294 unsigned long timeout = jiffies + AC97_TIMEOUT;
295
296 do {
297 v = ep93xx_ac97_read_reg(info, AC97SR(1));
298 if (time_after(jiffies, timeout)) {
299 dev_warn(info->dev, "TX timeout\n");
300 break;
301 }
302 } while (!(v & (AC97SR_TXFE | AC97SR_TXUE)));
303
304 /* disable the TX FIFO */
305 ep93xx_ac97_write_reg(info, AC97TXCR(1), 0);
306 } else {
307 /* disable the RX FIFO */
308 ep93xx_ac97_write_reg(info, AC97RXCR(1), 0);
309 }
310 break;
311
312 default:
313 dev_warn(info->dev, "unknown command %d\n", cmd);
314 return -EINVAL;
315 }
316
317 return 0;
318}
319
320static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
321 struct snd_soc_dai *dai)
322{
323 struct ep93xx_pcm_dma_params *dma_data;
324
325 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
326 dma_data = &ep93xx_ac97_pcm_out;
327 else
328 dma_data = &ep93xx_ac97_pcm_in;
329
330 snd_soc_dai_set_dma_data(dai, substream, dma_data);
331 return 0;
332}
333
334static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
335 .startup = ep93xx_ac97_startup,
336 .trigger = ep93xx_ac97_trigger,
337};
338
339struct snd_soc_dai_driver ep93xx_ac97_dai = {
340 .name = "ep93xx-ac97",
341 .id = 0,
342 .ac97_control = 1,
343 .playback = {
344 .stream_name = "AC97 Playback",
345 .channels_min = 2,
346 .channels_max = 2,
347 .rates = SNDRV_PCM_RATE_8000_48000,
348 .formats = SNDRV_PCM_FMTBIT_S16_LE,
349 },
350 .capture = {
351 .stream_name = "AC97 Capture",
352 .channels_min = 2,
353 .channels_max = 2,
354 .rates = SNDRV_PCM_RATE_8000_48000,
355 .formats = SNDRV_PCM_FMTBIT_S16_LE,
356 },
357 .ops = &ep93xx_ac97_dai_ops,
358};
359
360static int __devinit ep93xx_ac97_probe(struct platform_device *pdev)
361{
362 struct ep93xx_ac97_info *info;
363 int ret;
364
365 info = kzalloc(sizeof(struct ep93xx_ac97_info), GFP_KERNEL);
366 if (!info)
367 return -ENOMEM;
368
369 dev_set_drvdata(&pdev->dev, info);
370
371 mutex_init(&info->lock);
372 init_completion(&info->done);
373 info->dev = &pdev->dev;
374
375 info->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
376 if (!info->mem) {
377 ret = -ENXIO;
378 goto fail_free_info;
379 }
380
381 info->irq = platform_get_irq(pdev, 0);
382 if (!info->irq) {
383 ret = -ENXIO;
384 goto fail_free_info;
385 }
386
387 if (!request_mem_region(info->mem->start, resource_size(info->mem),
388 pdev->name)) {
389 ret = -EBUSY;
390 goto fail_free_info;
391 }
392
393 info->regs = ioremap(info->mem->start, resource_size(info->mem));
394 if (!info->regs) {
395 ret = -ENOMEM;
396 goto fail_release_mem;
397 }
398
399 ret = request_irq(info->irq, ep93xx_ac97_interrupt, IRQF_TRIGGER_HIGH,
400 pdev->name, info);
401 if (ret)
402 goto fail_unmap_mem;
403
404 ep93xx_ac97_info = info;
405 platform_set_drvdata(pdev, info);
406
407 ret = snd_soc_register_dai(&pdev->dev, &ep93xx_ac97_dai);
408 if (ret)
409 goto fail_free_irq;
410
411 return 0;
412
413fail_free_irq:
414 platform_set_drvdata(pdev, NULL);
415 free_irq(info->irq, info);
416fail_unmap_mem:
417 iounmap(info->regs);
418fail_release_mem:
419 release_mem_region(info->mem->start, resource_size(info->mem));
420fail_free_info:
421 kfree(info);
422
423 return ret;
424}
425
426static int __devexit ep93xx_ac97_remove(struct platform_device *pdev)
427{
428 struct ep93xx_ac97_info *info = platform_get_drvdata(pdev);
429
430 snd_soc_unregister_dai(&pdev->dev);
431
432 /* disable the AC97 controller */
433 ep93xx_ac97_write_reg(info, AC97GCR, 0);
434
435 free_irq(info->irq, info);
436 iounmap(info->regs);
437 release_mem_region(info->mem->start, resource_size(info->mem));
438 platform_set_drvdata(pdev, NULL);
439 kfree(info);
440
441 return 0;
442}
443
444static struct platform_driver ep93xx_ac97_driver = {
445 .probe = ep93xx_ac97_probe,
446 .remove = __devexit_p(ep93xx_ac97_remove),
447 .driver = {
448 .name = "ep93xx-ac97",
449 .owner = THIS_MODULE,
450 },
451};
452
453static int __init ep93xx_ac97_init(void)
454{
455 return platform_driver_register(&ep93xx_ac97_driver);
456}
457module_init(ep93xx_ac97_init);
458
459static void __exit ep93xx_ac97_exit(void)
460{
461 platform_driver_unregister(&ep93xx_ac97_driver);
462}
463module_exit(ep93xx_ac97_exit);
464
465MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
466MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
467MODULE_LICENSE("GPL");
468MODULE_ALIAS("platform:ep93xx-ac97");
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index 00b946632184..4f4873359613 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -31,7 +31,6 @@
31#include <mach/dma.h> 31#include <mach/dma.h>
32 32
33#include "ep93xx-pcm.h" 33#include "ep93xx-pcm.h"
34#include "ep93xx-i2s.h"
35 34
36#define EP93XX_I2S_TXCLKCFG 0x00 35#define EP93XX_I2S_TXCLKCFG 0x00
37#define EP93XX_I2S_RXCLKCFG 0x04 36#define EP93XX_I2S_RXCLKCFG 0x04
@@ -145,8 +144,8 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
145 struct snd_soc_dai *dai) 144 struct snd_soc_dai *dai)
146{ 145{
147 struct snd_soc_pcm_runtime *rtd = substream->private_data; 146 struct snd_soc_pcm_runtime *rtd = substream->private_data;
148 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 147 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
149 struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data; 148 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
150 149
151 snd_soc_dai_set_dma_data(cpu_dai, substream, 150 snd_soc_dai_set_dma_data(cpu_dai, substream,
152 &info->dma_params[substream->stream]); 151 &info->dma_params[substream->stream]);
@@ -156,8 +155,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
156static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream, 155static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
157 struct snd_soc_dai *dai) 156 struct snd_soc_dai *dai)
158{ 157{
159 struct snd_soc_pcm_runtime *rtd = substream->private_data; 158 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
160 struct ep93xx_i2s_info *info = rtd->dai->cpu_dai->private_data;
161 159
162 ep93xx_i2s_disable(info, substream->stream); 160 ep93xx_i2s_disable(info, substream->stream);
163} 161}
@@ -165,7 +163,7 @@ static void ep93xx_i2s_shutdown(struct snd_pcm_substream *substream,
165static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 163static int ep93xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
166 unsigned int fmt) 164 unsigned int fmt)
167{ 165{
168 struct ep93xx_i2s_info *info = cpu_dai->private_data; 166 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
169 unsigned int clk_cfg, lin_ctrl; 167 unsigned int clk_cfg, lin_ctrl;
170 168
171 clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG); 169 clk_cfg = ep93xx_i2s_read_reg(info, EP93XX_I2S_RXCLKCFG);
@@ -242,9 +240,7 @@ static int ep93xx_i2s_hw_params(struct snd_pcm_substream *substream,
242 struct snd_pcm_hw_params *params, 240 struct snd_pcm_hw_params *params,
243 struct snd_soc_dai *dai) 241 struct snd_soc_dai *dai)
244{ 242{
245 struct snd_soc_pcm_runtime *rtd = substream->private_data; 243 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
246 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
247 struct ep93xx_i2s_info *info = cpu_dai->private_data;
248 unsigned word_len, div, sdiv, lrdiv; 244 unsigned word_len, div, sdiv, lrdiv;
249 int found = 0, err; 245 int found = 0, err;
250 246
@@ -302,7 +298,7 @@ out:
302static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, 298static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
303 unsigned int freq, int dir) 299 unsigned int freq, int dir)
304{ 300{
305 struct ep93xx_i2s_info *info = cpu_dai->private_data; 301 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(cpu_dai);
306 302
307 if (dir == SND_SOC_CLOCK_IN || clk_id != 0) 303 if (dir == SND_SOC_CLOCK_IN || clk_id != 0)
308 return -EINVAL; 304 return -EINVAL;
@@ -313,7 +309,7 @@ static int ep93xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
313#ifdef CONFIG_PM 309#ifdef CONFIG_PM
314static int ep93xx_i2s_suspend(struct snd_soc_dai *dai) 310static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
315{ 311{
316 struct ep93xx_i2s_info *info = dai->private_data; 312 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
317 313
318 if (!dai->active) 314 if (!dai->active)
319 return; 315 return;
@@ -324,7 +320,7 @@ static int ep93xx_i2s_suspend(struct snd_soc_dai *dai)
324 320
325static int ep93xx_i2s_resume(struct snd_soc_dai *dai) 321static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
326{ 322{
327 struct ep93xx_i2s_info *info = dai->private_data; 323 struct ep93xx_i2s_info *info = snd_soc_dai_get_drvdata(dai);
328 324
329 if (!dai->active) 325 if (!dai->active)
330 return; 326 return;
@@ -349,9 +345,7 @@ static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
349 SNDRV_PCM_FMTBIT_S24_LE | \ 345 SNDRV_PCM_FMTBIT_S24_LE | \
350 SNDRV_PCM_FMTBIT_S32_LE) 346 SNDRV_PCM_FMTBIT_S32_LE)
351 347
352struct snd_soc_dai ep93xx_i2s_dai = { 348static struct snd_soc_dai_driver ep93xx_i2s_dai = {
353 .name = "ep93xx-i2s",
354 .id = 0,
355 .symmetric_rates= 1, 349 .symmetric_rates= 1,
356 .suspend = ep93xx_i2s_suspend, 350 .suspend = ep93xx_i2s_suspend,
357 .resume = ep93xx_i2s_resume, 351 .resume = ep93xx_i2s_resume,
@@ -369,7 +363,6 @@ struct snd_soc_dai ep93xx_i2s_dai = {
369 }, 363 },
370 .ops = &ep93xx_i2s_dai_ops, 364 .ops = &ep93xx_i2s_dai_ops,
371}; 365};
372EXPORT_SYMBOL_GPL(ep93xx_i2s_dai);
373 366
374static int ep93xx_i2s_probe(struct platform_device *pdev) 367static int ep93xx_i2s_probe(struct platform_device *pdev)
375{ 368{
@@ -383,8 +376,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
383 goto fail; 376 goto fail;
384 } 377 }
385 378
386 ep93xx_i2s_dai.dev = &pdev->dev; 379 dev_set_drvdata(&pdev->dev, info);
387 ep93xx_i2s_dai.private_data = info;
388 info->dma_params = ep93xx_i2s_dma_params; 380 info->dma_params = ep93xx_i2s_dma_params;
389 381
390 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 382 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -424,7 +416,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
424 goto fail_put_sclk; 416 goto fail_put_sclk;
425 } 417 }
426 418
427 err = snd_soc_register_dai(&ep93xx_i2s_dai); 419 err = snd_soc_register_dai(&pdev->dev, &ep93xx_i2s_dai);
428 if (err) 420 if (err)
429 goto fail_put_lrclk; 421 goto fail_put_lrclk;
430 422
@@ -447,9 +439,9 @@ fail:
447 439
448static int __devexit ep93xx_i2s_remove(struct platform_device *pdev) 440static int __devexit ep93xx_i2s_remove(struct platform_device *pdev)
449{ 441{
450 struct ep93xx_i2s_info *info = ep93xx_i2s_dai.private_data; 442 struct ep93xx_i2s_info *info = dev_get_drvdata(&pdev->dev);
451 443
452 snd_soc_unregister_dai(&ep93xx_i2s_dai); 444 snd_soc_unregister_dai(&pdev->dev);
453 clk_put(info->lrclk); 445 clk_put(info->lrclk);
454 clk_put(info->sclk); 446 clk_put(info->sclk);
455 clk_put(info->mclk); 447 clk_put(info->mclk);
diff --git a/sound/soc/ep93xx/ep93xx-i2s.h b/sound/soc/ep93xx/ep93xx-i2s.h
deleted file mode 100644
index 3bd4ebfaa1de..000000000000
--- a/sound/soc/ep93xx/ep93xx-i2s.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/*
2 * linux/sound/soc/ep93xx-i2s.h
3 * EP93xx I2S driver
4 *
5 * Copyright (C) 2010 Ryan Mallon <ryan@bluewatersys.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 */
12
13#ifndef _EP93XX_SND_SOC_I2S_H
14#define _EP93XX_SND_SOC_I2S_H
15
16extern struct snd_soc_dai ep93xx_i2s_dai;
17
18#endif /* _EP93XX_SND_SOC_I2S_H */
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index 4ba938400791..2f121ddbe4bb 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -95,7 +95,7 @@ static void ep93xx_pcm_buffer_finished(void *cookie,
95static int ep93xx_pcm_open(struct snd_pcm_substream *substream) 95static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
96{ 96{
97 struct snd_soc_pcm_runtime *soc_rtd = substream->private_data; 97 struct snd_soc_pcm_runtime *soc_rtd = substream->private_data;
98 struct snd_soc_dai *cpu_dai = soc_rtd->dai->cpu_dai; 98 struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai;
99 struct ep93xx_pcm_dma_params *dma_params; 99 struct ep93xx_pcm_dma_params *dma_params;
100 struct ep93xx_runtime_data *rtd; 100 struct ep93xx_runtime_data *rtd;
101 int ret; 101 int ret;
@@ -276,14 +276,14 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
276 if (!card->dev->coherent_dma_mask) 276 if (!card->dev->coherent_dma_mask)
277 card->dev->coherent_dma_mask = 0xffffffff; 277 card->dev->coherent_dma_mask = 0xffffffff;
278 278
279 if (dai->playback.channels_min) { 279 if (dai->driver->playback.channels_min) {
280 ret = ep93xx_pcm_preallocate_dma_buffer(pcm, 280 ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
281 SNDRV_PCM_STREAM_PLAYBACK); 281 SNDRV_PCM_STREAM_PLAYBACK);
282 if (ret) 282 if (ret)
283 return ret; 283 return ret;
284 } 284 }
285 285
286 if (dai->capture.channels_min) { 286 if (dai->driver->capture.channels_min) {
287 ret = ep93xx_pcm_preallocate_dma_buffer(pcm, 287 ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
288 SNDRV_PCM_STREAM_CAPTURE); 288 SNDRV_PCM_STREAM_CAPTURE);
289 if (ret) 289 if (ret)
@@ -293,22 +293,41 @@ static int ep93xx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
293 return 0; 293 return 0;
294} 294}
295 295
296struct snd_soc_platform ep93xx_soc_platform = { 296static struct snd_soc_platform_driver ep93xx_soc_platform = {
297 .name = "ep93xx-audio", 297 .ops = &ep93xx_pcm_ops,
298 .pcm_ops = &ep93xx_pcm_ops,
299 .pcm_new = &ep93xx_pcm_new, 298 .pcm_new = &ep93xx_pcm_new,
300 .pcm_free = &ep93xx_pcm_free_dma_buffers, 299 .pcm_free = &ep93xx_pcm_free_dma_buffers,
301}; 300};
302EXPORT_SYMBOL_GPL(ep93xx_soc_platform); 301
302static int __devinit ep93xx_soc_platform_probe(struct platform_device *pdev)
303{
304 return snd_soc_register_platform(&pdev->dev, &ep93xx_soc_platform);
305}
306
307static int __devexit ep93xx_soc_platform_remove(struct platform_device *pdev)
308{
309 snd_soc_unregister_platform(&pdev->dev);
310 return 0;
311}
312
313static struct platform_driver ep93xx_pcm_driver = {
314 .driver = {
315 .name = "ep93xx-pcm-audio",
316 .owner = THIS_MODULE,
317 },
318
319 .probe = ep93xx_soc_platform_probe,
320 .remove = __devexit_p(ep93xx_soc_platform_remove),
321};
303 322
304static int __init ep93xx_soc_platform_init(void) 323static int __init ep93xx_soc_platform_init(void)
305{ 324{
306 return snd_soc_register_platform(&ep93xx_soc_platform); 325 return platform_driver_register(&ep93xx_pcm_driver);
307} 326}
308 327
309static void __exit ep93xx_soc_platform_exit(void) 328static void __exit ep93xx_soc_platform_exit(void)
310{ 329{
311 snd_soc_unregister_platform(&ep93xx_soc_platform); 330 platform_driver_unregister(&ep93xx_pcm_driver);
312} 331}
313 332
314module_init(ep93xx_soc_platform_init); 333module_init(ep93xx_soc_platform_init);
diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/ep93xx/ep93xx-pcm.h
index 4ffdd3f62fe9..111e1121ecb8 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.h
+++ b/sound/soc/ep93xx/ep93xx-pcm.h
@@ -17,6 +17,4 @@ struct ep93xx_pcm_dma_params {
17 int dma_port; 17 int dma_port;
18}; 18};
19 19
20extern struct snd_soc_platform ep93xx_soc_platform;
21
22#endif /* _EP93XX_SND_SOC_PCM_H */ 20#endif /* _EP93XX_SND_SOC_PCM_H */
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/ep93xx/simone.c
new file mode 100644
index 000000000000..4b0d19913728
--- /dev/null
+++ b/sound/soc/ep93xx/simone.c
@@ -0,0 +1,89 @@
1/*
2 * simone.c -- ASoC audio for Simplemachines Sim.One board
3 *
4 * Copyright (c) 2010 Mika Westerberg
5 *
6 * Based on snappercl15 machine driver by Ryan Mallon.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20
21#include <asm/mach-types.h>
22#include <mach/hardware.h>
23
24#include "ep93xx-pcm.h"
25
26static struct snd_soc_dai_link simone_dai = {
27 .name = "AC97",
28 .stream_name = "AC97 HiFi",
29 .cpu_dai_name = "ep93xx-ac97",
30 .codec_dai_name = "ac97-hifi",
31 .codec_name = "ac97-codec",
32 .platform_name = "ep93xx-pcm-audio",
33};
34
35static struct snd_soc_card snd_soc_simone = {
36 .name = "Sim.One",
37 .dai_link = &simone_dai,
38 .num_links = 1,
39};
40
41static struct platform_device *simone_snd_ac97_device;
42static struct platform_device *simone_snd_device;
43
44static int __init simone_init(void)
45{
46 int ret;
47
48 if (!machine_is_sim_one())
49 return -ENODEV;
50
51 simone_snd_ac97_device = platform_device_alloc("ac97-codec", -1);
52 if (!simone_snd_ac97_device)
53 return -ENOMEM;
54
55 ret = platform_device_add(simone_snd_ac97_device);
56 if (ret)
57 goto fail;
58
59 simone_snd_device = platform_device_alloc("soc-audio", -1);
60 if (!simone_snd_device) {
61 ret = -ENOMEM;
62 goto fail;
63 }
64
65 platform_set_drvdata(simone_snd_device, &snd_soc_simone);
66 ret = platform_device_add(simone_snd_device);
67 if (ret) {
68 platform_device_put(simone_snd_device);
69 goto fail;
70 }
71
72 return ret;
73
74fail:
75 platform_device_put(simone_snd_ac97_device);
76 return ret;
77}
78module_init(simone_init);
79
80static void __exit simone_exit(void)
81{
82 platform_device_unregister(simone_snd_device);
83 platform_device_unregister(simone_snd_ac97_device);
84}
85module_exit(simone_exit);
86
87MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
88MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
89MODULE_LICENSE("GPL");
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index 64955340ff75..28ab5ff772ac 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -22,7 +22,6 @@
22 22
23#include "../codecs/tlv320aic23.h" 23#include "../codecs/tlv320aic23.h"
24#include "ep93xx-pcm.h" 24#include "ep93xx-pcm.h"
25#include "ep93xx-i2s.h"
26 25
27#define CODEC_CLOCK 5644800 26#define CODEC_CLOCK 5644800
28 27
@@ -30,8 +29,8 @@ static int snappercl15_hw_params(struct snd_pcm_substream *substream,
30 struct snd_pcm_hw_params *params) 29 struct snd_pcm_hw_params *params)
31{ 30{
32 struct snd_soc_pcm_runtime *rtd = substream->private_data; 31 struct snd_soc_pcm_runtime *rtd = substream->private_data;
33 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 32 struct snd_soc_dai *codec_dai = rtd->codec_dai;
34 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 33 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
35 int err; 34 int err;
36 35
37 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | 36 err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
@@ -77,8 +76,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
77 {"MICIN", NULL, "Mic Jack"}, 76 {"MICIN", NULL, "Mic Jack"},
78}; 77};
79 78
80static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec) 79static int snappercl15_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
81{ 80{
81 struct snd_soc_codec *codec = rtd->codec;
82
82 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, 83 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
83 ARRAY_SIZE(tlv320aic23_dapm_widgets)); 84 ARRAY_SIZE(tlv320aic23_dapm_widgets));
84 85
@@ -89,24 +90,20 @@ static int snappercl15_tlv320aic23_init(struct snd_soc_codec *codec)
89static struct snd_soc_dai_link snappercl15_dai = { 90static struct snd_soc_dai_link snappercl15_dai = {
90 .name = "tlv320aic23", 91 .name = "tlv320aic23",
91 .stream_name = "AIC23", 92 .stream_name = "AIC23",
92 .cpu_dai = &ep93xx_i2s_dai, 93 .cpu_dai_name = "ep93xx-i2s",
93 .codec_dai = &tlv320aic23_dai, 94 .codec_dai_name = "tlv320aic23-hifi",
95 .codec_name = "tlv320aic23-codec.0-001a",
96 .platform_name = "ep93xx-pcm-audio",
94 .init = snappercl15_tlv320aic23_init, 97 .init = snappercl15_tlv320aic23_init,
95 .ops = &snappercl15_ops, 98 .ops = &snappercl15_ops,
96}; 99};
97 100
98static struct snd_soc_card snd_soc_snappercl15 = { 101static struct snd_soc_card snd_soc_snappercl15 = {
99 .name = "Snapper CL15", 102 .name = "Snapper CL15",
100 .platform = &ep93xx_soc_platform,
101 .dai_link = &snappercl15_dai, 103 .dai_link = &snappercl15_dai,
102 .num_links = 1, 104 .num_links = 1,
103}; 105};
104 106
105static struct snd_soc_device snappercl15_snd_devdata = {
106 .card = &snd_soc_snappercl15,
107 .codec_dev = &soc_codec_dev_tlv320aic23,
108};
109
110static struct platform_device *snappercl15_snd_device; 107static struct platform_device *snappercl15_snd_device;
111 108
112static int __init snappercl15_init(void) 109static int __init snappercl15_init(void)
@@ -126,8 +123,7 @@ static int __init snappercl15_init(void)
126 if (!snappercl15_snd_device) 123 if (!snappercl15_snd_device)
127 return -ENOMEM; 124 return -ENOMEM;
128 125
129 platform_set_drvdata(snappercl15_snd_device, &snappercl15_snd_devdata); 126 platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15);
130 snappercl15_snd_devdata.dev = &snappercl15_snd_device->dev;
131 ret = platform_device_add(snappercl15_snd_device); 127 ret = platform_device_add(snappercl15_snd_device);
132 if (ret) 128 if (ret)
133 platform_device_put(snappercl15_snd_device); 129 platform_device_put(snappercl15_snd_device);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 8cb65ccad35f..d754d34d68a6 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -1,27 +1,36 @@
1config SND_SOC_OF_SIMPLE
2 tristate
3
4config SND_MPC52xx_DMA 1config SND_MPC52xx_DMA
5 tristate 2 tristate
6 3
7# ASoC platform support for the Freescale MPC8610 SOC. This compiles drivers 4# ASoC platform support for the Freescale PowerPC SOCs that have an SSI and
8# for the SSI and the Elo DMA controller. You will still need to select 5# an Elo DMA controller, such as the MPC8610 and P1022. You will still need to
9# a platform driver and a codec driver. 6# select a platform driver and a codec driver.
10config SND_SOC_MPC8610 7config SND_SOC_POWERPC_SSI
11 tristate 8 tristate
12 depends on MPC8610 9 depends on FSL_SOC
13 10
14config SND_SOC_MPC8610_HPCD 11config SND_SOC_MPC8610_HPCD
15 tristate "ALSA SoC support for the Freescale MPC8610 HPCD board" 12 tristate "ALSA SoC support for the Freescale MPC8610 HPCD board"
16 # I2C is necessary for the CS4270 driver 13 # I2C is necessary for the CS4270 driver
17 depends on MPC8610_HPCD && I2C 14 depends on MPC8610_HPCD && I2C
18 select SND_SOC_MPC8610 15 select SND_SOC_POWERPC_SSI
19 select SND_SOC_CS4270 16 select SND_SOC_CS4270
20 select SND_SOC_CS4270_VD33_ERRATA 17 select SND_SOC_CS4270_VD33_ERRATA
21 default y if MPC8610_HPCD 18 default y if MPC8610_HPCD
22 help 19 help
23 Say Y if you want to enable audio on the Freescale MPC8610 HPCD. 20 Say Y if you want to enable audio on the Freescale MPC8610 HPCD.
24 21
22config SND_SOC_P1022_DS
23 tristate "ALSA SoC support for the Freescale P1022 DS board"
24 # I2C is necessary for the WM8776 driver
25 depends on P1022_DS && I2C
26 select SND_SOC_POWERPC_SSI
27 select SND_SOC_WM8776
28 default y if P1022_DS
29 help
30 Say Y if you want to enable audio on the Freescale P1022 DS board.
31 This will also include the Wolfson Microelectronics WM8776 codec
32 driver.
33
25config SND_SOC_MPC5200_I2S 34config SND_SOC_MPC5200_I2S
26 tristate "Freescale MPC5200 PSC in I2S mode driver" 35 tristate "Freescale MPC5200 PSC in I2S mode driver"
27 depends on PPC_MPC52xx && PPC_BESTCOMM 36 depends on PPC_MPC52xx && PPC_BESTCOMM
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index a83a73967ec6..b4a38c0ac58c 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -1,14 +1,15 @@
1# Simple machine driver that extracts configuration from the OF device tree
2obj-$(CONFIG_SND_SOC_OF_SIMPLE) += soc-of-simple.o
3
4# MPC8610 HPCD Machine Support 1# MPC8610 HPCD Machine Support
5snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o 2snd-soc-mpc8610-hpcd-objs := mpc8610_hpcd.o
6obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o 3obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
7 4
8# MPC8610 Platform Support 5# P1022 DS Machine Support
6snd-soc-p1022-ds-objs := p1022_ds.o
7obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
8
9# Freescale PowerPC SSI/DMA Platform Support
9snd-soc-fsl-ssi-objs := fsl_ssi.o 10snd-soc-fsl-ssi-objs := fsl_ssi.o
10snd-soc-fsl-dma-objs := fsl_dma.o 11snd-soc-fsl-dma-objs := fsl_dma.o
11obj-$(CONFIG_SND_SOC_MPC8610) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o 12obj-$(CONFIG_SND_SOC_POWERPC_SSI) += snd-soc-fsl-ssi.o snd-soc-fsl-dma.o
12 13
13# MPC5200 Platform Support 14# MPC5200 Platform Support
14obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o 15obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o
diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c
index 1a5b8e0d6a34..53251e6b5bd5 100644
--- a/sound/soc/fsl/efika-audio-fabric.c
+++ b/sound/soc/fsl/efika-audio-fabric.c
@@ -24,7 +24,6 @@
24#include <sound/pcm_params.h> 24#include <sound/pcm_params.h>
25#include <sound/initval.h> 25#include <sound/initval.h>
26#include <sound/soc.h> 26#include <sound/soc.h>
27#include <sound/soc-of-simple.h>
28 27
29#include "mpc5200_dma.h" 28#include "mpc5200_dma.h"
30#include "mpc5200_psc_ac97.h" 29#include "mpc5200_psc_ac97.h"
@@ -32,21 +31,24 @@
32 31
33#define DRV_NAME "efika-audio-fabric" 32#define DRV_NAME "efika-audio-fabric"
34 33
35static struct snd_soc_device device;
36static struct snd_soc_card card; 34static struct snd_soc_card card;
37 35
38static struct snd_soc_dai_link efika_fabric_dai[] = { 36static struct snd_soc_dai_link efika_fabric_dai[] = {
39{ 37{
40 .name = "AC97", 38 .name = "AC97",
41 .stream_name = "AC97 Analog", 39 .stream_name = "AC97 Analog",
42 .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_ANALOG], 40 .codec_dai_name = "stac9766-hifi-analog",
43 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], 41 .cpu_dai_name = "mpc5200-psc-ac97.0",
42 .platform_name = "mpc5200-pcm-audio",
43 .codec_name = "stac9766-codec",
44}, 44},
45{ 45{
46 .name = "AC97", 46 .name = "AC97",
47 .stream_name = "AC97 IEC958", 47 .stream_name = "AC97 IEC958",
48 .codec_dai = &stac9766_dai[STAC9766_DAI_AC97_DIGITAL], 48 .codec_dai_name = "stac9766-hifi-IEC958",
49 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], 49 .cpu_dai_name = "mpc5200-psc-ac97.1",
50 .platform_name = "mpc5200-pcm-audio",
51 .codec_name = "stac9766-codec",
50}, 52},
51}; 53};
52 54
@@ -58,13 +60,10 @@ static __init int efika_fabric_init(void)
58 if (!of_machine_is_compatible("bplan,efika")) 60 if (!of_machine_is_compatible("bplan,efika"))
59 return -ENODEV; 61 return -ENODEV;
60 62
61 card.platform = &mpc5200_audio_dma_platform;
62 card.name = "Efika"; 63 card.name = "Efika";
63 card.dai_link = efika_fabric_dai; 64 card.dai_link = efika_fabric_dai;
64 card.num_links = ARRAY_SIZE(efika_fabric_dai); 65 card.num_links = ARRAY_SIZE(efika_fabric_dai);
65 66
66 device.card = &card;
67 device.codec_dev = &soc_codec_dev_stac9766;
68 67
69 pdev = platform_device_alloc("soc-audio", 1); 68 pdev = platform_device_alloc("soc-audio", 1);
70 if (!pdev) { 69 if (!pdev) {
@@ -72,8 +71,7 @@ static __init int efika_fabric_init(void)
72 return -ENODEV; 71 return -ENODEV;
73 } 72 }
74 73
75 platform_set_drvdata(pdev, &device); 74 platform_set_drvdata(pdev, &card);
76 device.dev = &pdev->dev;
77 75
78 rc = platform_device_add(pdev); 76 rc = platform_device_add(pdev);
79 if (rc) { 77 if (rc) {
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 410c7496a18d..4cf98c03af22 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -3,10 +3,11 @@
3 * 3 *
4 * Author: Timur Tabi <timur@freescale.com> 4 * Author: Timur Tabi <timur@freescale.com>
5 * 5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed 6 * Copyright 2007-2010 Freescale Semiconductor, Inc.
7 * under the terms of the GNU General Public License version 2. This 7 *
8 * program is licensed "as is" without any warranty of any kind, whether 8 * This file is licensed under the terms of the GNU General Public License
9 * express or implied. 9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
10 * 11 *
11 * This driver implements ASoC support for the Elo DMA controller, which is 12 * This driver implements ASoC support for the Elo DMA controller, which is
12 * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms, 13 * the DMA controller on Freescale 83xx, 85xx, and 86xx SOCs. In ALSA terms,
@@ -20,6 +21,9 @@
20#include <linux/interrupt.h> 21#include <linux/interrupt.h>
21#include <linux/delay.h> 22#include <linux/delay.h>
22#include <linux/gfp.h> 23#include <linux/gfp.h>
24#include <linux/of_platform.h>
25#include <linux/list.h>
26#include <linux/slab.h>
23 27
24#include <sound/core.h> 28#include <sound/core.h>
25#include <sound/pcm.h> 29#include <sound/pcm.h>
@@ -29,6 +33,7 @@
29#include <asm/io.h> 33#include <asm/io.h>
30 34
31#include "fsl_dma.h" 35#include "fsl_dma.h"
36#include "fsl_ssi.h" /* For the offset of stx0 and srx0 */
32 37
33/* 38/*
34 * The formats that the DMA controller supports, which is anything 39 * The formats that the DMA controller supports, which is anything
@@ -52,26 +57,16 @@
52#define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \ 57#define FSLDMA_PCM_RATES (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_192000 | \
53 SNDRV_PCM_RATE_CONTINUOUS) 58 SNDRV_PCM_RATE_CONTINUOUS)
54 59
55/* DMA global data. This structure is used by fsl_dma_open() to determine 60struct dma_object {
56 * which DMA channels to assign to a substream. Unfortunately, ASoC V1 does 61 struct snd_soc_platform_driver dai;
57 * not allow the machine driver to provide this information to the PCM
58 * driver in advance, and there's no way to differentiate between the two
59 * DMA controllers. So for now, this driver only supports one SSI device
60 * using two DMA channels. We cannot support multiple DMA devices.
61 *
62 * ssi_stx_phys: bus address of SSI STX register
63 * ssi_srx_phys: bus address of SSI SRX register
64 * dma_channel: pointer to the DMA channel's registers
65 * irq: IRQ for this DMA channel
66 * assigned: set to 1 if that DMA channel is assigned to a substream
67 */
68static struct {
69 dma_addr_t ssi_stx_phys; 62 dma_addr_t ssi_stx_phys;
70 dma_addr_t ssi_srx_phys; 63 dma_addr_t ssi_srx_phys;
71 struct ccsr_dma_channel __iomem *dma_channel[2]; 64 unsigned int ssi_fifo_depth;
72 unsigned int irq[2]; 65 struct ccsr_dma_channel __iomem *channel;
73 unsigned int assigned[2]; 66 unsigned int irq;
74} dma_global_data; 67 bool assigned;
68 char path[1];
69};
75 70
76/* 71/*
77 * The number of DMA links to use. Two is the bare minimum, but if you 72 * The number of DMA links to use. Two is the bare minimum, but if you
@@ -88,8 +83,6 @@ static struct {
88 * structure. 83 * structure.
89 * 84 *
90 * @link[]: array of link descriptors 85 * @link[]: array of link descriptors
91 * @controller_id: which DMA controller (0, 1, ...)
92 * @channel_id: which DMA channel on the controller (0, 1, 2, ...)
93 * @dma_channel: pointer to the DMA channel's registers 86 * @dma_channel: pointer to the DMA channel's registers
94 * @irq: IRQ for this DMA channel 87 * @irq: IRQ for this DMA channel
95 * @substream: pointer to the substream object, needed by the ISR 88 * @substream: pointer to the substream object, needed by the ISR
@@ -104,12 +97,11 @@ static struct {
104 */ 97 */
105struct fsl_dma_private { 98struct fsl_dma_private {
106 struct fsl_dma_link_descriptor link[NUM_DMA_LINKS]; 99 struct fsl_dma_link_descriptor link[NUM_DMA_LINKS];
107 unsigned int controller_id;
108 unsigned int channel_id;
109 struct ccsr_dma_channel __iomem *dma_channel; 100 struct ccsr_dma_channel __iomem *dma_channel;
110 unsigned int irq; 101 unsigned int irq;
111 struct snd_pcm_substream *substream; 102 struct snd_pcm_substream *substream;
112 dma_addr_t ssi_sxx_phys; 103 dma_addr_t ssi_sxx_phys;
104 unsigned int ssi_fifo_depth;
113 dma_addr_t ld_buf_phys; 105 dma_addr_t ld_buf_phys;
114 unsigned int current_link; 106 unsigned int current_link;
115 dma_addr_t dma_buf_phys; 107 dma_addr_t dma_buf_phys;
@@ -185,13 +177,23 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)
185 struct fsl_dma_link_descriptor *link = 177 struct fsl_dma_link_descriptor *link =
186 &dma_private->link[dma_private->current_link]; 178 &dma_private->link[dma_private->current_link];
187 179
188 /* Update our link descriptors to point to the next period */ 180 /* Update our link descriptors to point to the next period. On a 36-bit
189 if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 181 * system, we also need to update the ESAD bits. We also set (keep) the
190 link->source_addr = 182 * snoop bits. See the comments in fsl_dma_hw_params() about snooping.
191 cpu_to_be32(dma_private->dma_buf_next); 183 */
192 else 184 if (dma_private->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
193 link->dest_addr = 185 link->source_addr = cpu_to_be32(dma_private->dma_buf_next);
194 cpu_to_be32(dma_private->dma_buf_next); 186#ifdef CONFIG_PHYS_64BIT
187 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
188 upper_32_bits(dma_private->dma_buf_next));
189#endif
190 } else {
191 link->dest_addr = cpu_to_be32(dma_private->dma_buf_next);
192#ifdef CONFIG_PHYS_64BIT
193 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
194 upper_32_bits(dma_private->dma_buf_next));
195#endif
196 }
195 197
196 /* Update our variables for next time */ 198 /* Update our variables for next time */
197 dma_private->dma_buf_next += dma_private->period_size; 199 dma_private->dma_buf_next += dma_private->period_size;
@@ -212,6 +214,9 @@ static void fsl_dma_update_pointers(struct fsl_dma_private *dma_private)
212static irqreturn_t fsl_dma_isr(int irq, void *dev_id) 214static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
213{ 215{
214 struct fsl_dma_private *dma_private = dev_id; 216 struct fsl_dma_private *dma_private = dev_id;
217 struct snd_pcm_substream *substream = dma_private->substream;
218 struct snd_soc_pcm_runtime *rtd = substream->private_data;
219 struct device *dev = rtd->platform->dev;
215 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; 220 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
216 irqreturn_t ret = IRQ_NONE; 221 irqreturn_t ret = IRQ_NONE;
217 u32 sr, sr2 = 0; 222 u32 sr, sr2 = 0;
@@ -222,11 +227,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
222 sr = in_be32(&dma_channel->sr); 227 sr = in_be32(&dma_channel->sr);
223 228
224 if (sr & CCSR_DMA_SR_TE) { 229 if (sr & CCSR_DMA_SR_TE) {
225 dev_err(dma_private->substream->pcm->card->dev, 230 dev_err(dev, "dma transmit error\n");
226 "DMA transmit error (controller=%u channel=%u irq=%u\n", 231 fsl_dma_abort_stream(substream);
227 dma_private->controller_id,
228 dma_private->channel_id, irq);
229 fsl_dma_abort_stream(dma_private->substream);
230 sr2 |= CCSR_DMA_SR_TE; 232 sr2 |= CCSR_DMA_SR_TE;
231 ret = IRQ_HANDLED; 233 ret = IRQ_HANDLED;
232 } 234 }
@@ -235,11 +237,8 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
235 ret = IRQ_HANDLED; 237 ret = IRQ_HANDLED;
236 238
237 if (sr & CCSR_DMA_SR_PE) { 239 if (sr & CCSR_DMA_SR_PE) {
238 dev_err(dma_private->substream->pcm->card->dev, 240 dev_err(dev, "dma programming error\n");
239 "DMA%u programming error (channel=%u irq=%u)\n", 241 fsl_dma_abort_stream(substream);
240 dma_private->controller_id,
241 dma_private->channel_id, irq);
242 fsl_dma_abort_stream(dma_private->substream);
243 sr2 |= CCSR_DMA_SR_PE; 242 sr2 |= CCSR_DMA_SR_PE;
244 ret = IRQ_HANDLED; 243 ret = IRQ_HANDLED;
245 } 244 }
@@ -253,8 +252,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
253 ret = IRQ_HANDLED; 252 ret = IRQ_HANDLED;
254 253
255 if (sr & CCSR_DMA_SR_EOSI) { 254 if (sr & CCSR_DMA_SR_EOSI) {
256 struct snd_pcm_substream *substream = dma_private->substream;
257
258 /* Tell ALSA we completed a period. */ 255 /* Tell ALSA we completed a period. */
259 snd_pcm_period_elapsed(substream); 256 snd_pcm_period_elapsed(substream);
260 257
@@ -288,11 +285,19 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
288 * This function is called when the codec driver calls snd_soc_new_pcms(), 285 * This function is called when the codec driver calls snd_soc_new_pcms(),
289 * once for each .dai_link in the machine driver's snd_soc_card 286 * once for each .dai_link in the machine driver's snd_soc_card
290 * structure. 287 * structure.
288 *
289 * snd_dma_alloc_pages() is just a front-end to dma_alloc_coherent(), which
290 * (currently) always allocates the DMA buffer in lowmem, even if GFP_HIGHMEM
291 * is specified. Therefore, any DMA buffers we allocate will always be in low
292 * memory, but we support for 36-bit physical addresses anyway.
293 *
294 * Regardless of where the memory is actually allocated, since the device can
295 * technically DMA to any 36-bit address, we do need to set the DMA mask to 36.
291 */ 296 */
292static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, 297static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
293 struct snd_pcm *pcm) 298 struct snd_pcm *pcm)
294{ 299{
295 static u64 fsl_dma_dmamask = DMA_BIT_MASK(32); 300 static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
296 int ret; 301 int ret;
297 302
298 if (!card->dev->dma_mask) 303 if (!card->dev->dma_mask)
@@ -301,25 +306,29 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
301 if (!card->dev->coherent_dma_mask) 306 if (!card->dev->coherent_dma_mask)
302 card->dev->coherent_dma_mask = fsl_dma_dmamask; 307 card->dev->coherent_dma_mask = fsl_dma_dmamask;
303 308
304 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, 309 /* Some codecs have separate DAIs for playback and capture, so we
305 fsl_dma_hardware.buffer_bytes_max, 310 * should allocate a DMA buffer only for the streams that are valid.
306 &pcm->streams[0].substream->dma_buffer); 311 */
307 if (ret) { 312
308 dev_err(card->dev, 313 if (dai->driver->playback.channels_min) {
309 "Can't allocate playback DMA buffer (size=%u)\n", 314 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
310 fsl_dma_hardware.buffer_bytes_max); 315 fsl_dma_hardware.buffer_bytes_max,
311 return -ENOMEM; 316 &pcm->streams[0].substream->dma_buffer);
317 if (ret) {
318 dev_err(card->dev, "can't alloc playback dma buffer\n");
319 return ret;
320 }
312 } 321 }
313 322
314 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev, 323 if (dai->driver->capture.channels_min) {
315 fsl_dma_hardware.buffer_bytes_max, 324 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
316 &pcm->streams[1].substream->dma_buffer); 325 fsl_dma_hardware.buffer_bytes_max,
317 if (ret) { 326 &pcm->streams[1].substream->dma_buffer);
318 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer); 327 if (ret) {
319 dev_err(card->dev, 328 snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
320 "Can't allocate capture DMA buffer (size=%u)\n", 329 dev_err(card->dev, "can't alloc capture dma buffer\n");
321 fsl_dma_hardware.buffer_bytes_max); 330 return ret;
322 return -ENOMEM; 331 }
323 } 332 }
324 333
325 return 0; 334 return 0;
@@ -390,6 +399,10 @@ static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
390static int fsl_dma_open(struct snd_pcm_substream *substream) 399static int fsl_dma_open(struct snd_pcm_substream *substream)
391{ 400{
392 struct snd_pcm_runtime *runtime = substream->runtime; 401 struct snd_pcm_runtime *runtime = substream->runtime;
402 struct snd_soc_pcm_runtime *rtd = substream->private_data;
403 struct device *dev = rtd->platform->dev;
404 struct dma_object *dma =
405 container_of(rtd->platform->driver, struct dma_object, dai);
393 struct fsl_dma_private *dma_private; 406 struct fsl_dma_private *dma_private;
394 struct ccsr_dma_channel __iomem *dma_channel; 407 struct ccsr_dma_channel __iomem *dma_channel;
395 dma_addr_t ld_buf_phys; 408 dma_addr_t ld_buf_phys;
@@ -407,52 +420,45 @@ static int fsl_dma_open(struct snd_pcm_substream *substream)
407 ret = snd_pcm_hw_constraint_integer(runtime, 420 ret = snd_pcm_hw_constraint_integer(runtime,
408 SNDRV_PCM_HW_PARAM_PERIODS); 421 SNDRV_PCM_HW_PARAM_PERIODS);
409 if (ret < 0) { 422 if (ret < 0) {
410 dev_err(substream->pcm->card->dev, "invalid buffer size\n"); 423 dev_err(dev, "invalid buffer size\n");
411 return ret; 424 return ret;
412 } 425 }
413 426
414 channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; 427 channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
415 428
416 if (dma_global_data.assigned[channel]) { 429 if (dma->assigned) {
417 dev_err(substream->pcm->card->dev, 430 dev_err(dev, "dma channel already assigned\n");
418 "DMA channel already assigned\n");
419 return -EBUSY; 431 return -EBUSY;
420 } 432 }
421 433
422 dma_private = dma_alloc_coherent(substream->pcm->card->dev, 434 dma_private = dma_alloc_coherent(dev, sizeof(struct fsl_dma_private),
423 sizeof(struct fsl_dma_private), &ld_buf_phys, GFP_KERNEL); 435 &ld_buf_phys, GFP_KERNEL);
424 if (!dma_private) { 436 if (!dma_private) {
425 dev_err(substream->pcm->card->dev, 437 dev_err(dev, "can't allocate dma private data\n");
426 "can't allocate DMA private data\n");
427 return -ENOMEM; 438 return -ENOMEM;
428 } 439 }
429 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 440 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
430 dma_private->ssi_sxx_phys = dma_global_data.ssi_stx_phys; 441 dma_private->ssi_sxx_phys = dma->ssi_stx_phys;
431 else 442 else
432 dma_private->ssi_sxx_phys = dma_global_data.ssi_srx_phys; 443 dma_private->ssi_sxx_phys = dma->ssi_srx_phys;
433 444
434 dma_private->dma_channel = dma_global_data.dma_channel[channel]; 445 dma_private->ssi_fifo_depth = dma->ssi_fifo_depth;
435 dma_private->irq = dma_global_data.irq[channel]; 446 dma_private->dma_channel = dma->channel;
447 dma_private->irq = dma->irq;
436 dma_private->substream = substream; 448 dma_private->substream = substream;
437 dma_private->ld_buf_phys = ld_buf_phys; 449 dma_private->ld_buf_phys = ld_buf_phys;
438 dma_private->dma_buf_phys = substream->dma_buffer.addr; 450 dma_private->dma_buf_phys = substream->dma_buffer.addr;
439 451
440 /* We only support one DMA controller for now */
441 dma_private->controller_id = 0;
442 dma_private->channel_id = channel;
443
444 ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private); 452 ret = request_irq(dma_private->irq, fsl_dma_isr, 0, "DMA", dma_private);
445 if (ret) { 453 if (ret) {
446 dev_err(substream->pcm->card->dev, 454 dev_err(dev, "can't register ISR for IRQ %u (ret=%i)\n",
447 "can't register ISR for IRQ %u (ret=%i)\n",
448 dma_private->irq, ret); 455 dma_private->irq, ret);
449 dma_free_coherent(substream->pcm->card->dev, 456 dma_free_coherent(dev, sizeof(struct fsl_dma_private),
450 sizeof(struct fsl_dma_private),
451 dma_private, dma_private->ld_buf_phys); 457 dma_private, dma_private->ld_buf_phys);
452 return ret; 458 return ret;
453 } 459 }
454 460
455 dma_global_data.assigned[channel] = 1; 461 dma->assigned = 1;
456 462
457 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 463 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
458 snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware); 464 snd_soc_set_runtime_hwparams(substream, &fsl_dma_hardware);
@@ -546,13 +552,15 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
546{ 552{
547 struct snd_pcm_runtime *runtime = substream->runtime; 553 struct snd_pcm_runtime *runtime = substream->runtime;
548 struct fsl_dma_private *dma_private = runtime->private_data; 554 struct fsl_dma_private *dma_private = runtime->private_data;
555 struct snd_soc_pcm_runtime *rtd = substream->private_data;
556 struct device *dev = rtd->platform->dev;
549 557
550 /* Number of bits per sample */ 558 /* Number of bits per sample */
551 unsigned int sample_size = 559 unsigned int sample_bits =
552 snd_pcm_format_physical_width(params_format(hw_params)); 560 snd_pcm_format_physical_width(params_format(hw_params));
553 561
554 /* Number of bytes per frame */ 562 /* Number of bytes per frame */
555 unsigned int frame_size = 2 * (sample_size / 8); 563 unsigned int sample_bytes = sample_bits / 8;
556 564
557 /* Bus address of SSI STX register */ 565 /* Bus address of SSI STX register */
558 dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys; 566 dma_addr_t ssi_sxx_phys = dma_private->ssi_sxx_phys;
@@ -592,7 +600,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
592 * that offset here. While we're at it, also tell the DMA controller 600 * that offset here. While we're at it, also tell the DMA controller
593 * how much data to transfer per sample. 601 * how much data to transfer per sample.
594 */ 602 */
595 switch (sample_size) { 603 switch (sample_bits) {
596 case 8: 604 case 8:
597 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1; 605 mr |= CCSR_DMA_MR_DAHTS_1 | CCSR_DMA_MR_SAHTS_1;
598 ssi_sxx_phys += 3; 606 ssi_sxx_phys += 3;
@@ -606,23 +614,42 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
606 break; 614 break;
607 default: 615 default:
608 /* We should never get here */ 616 /* We should never get here */
609 dev_err(substream->pcm->card->dev, 617 dev_err(dev, "unsupported sample size %u\n", sample_bits);
610 "unsupported sample size %u\n", sample_size);
611 return -EINVAL; 618 return -EINVAL;
612 } 619 }
613 620
614 /* 621 /*
615 * BWC should always be a multiple of the frame size. BWC determines 622 * BWC determines how many bytes are sent/received before the DMA
616 * how many bytes are sent/received before the DMA controller checks the 623 * controller checks the SSI to see if it needs to stop. BWC should
617 * SSI to see if it needs to stop. For playback, the transmit FIFO can 624 * always be a multiple of the frame size, so that we always transmit
618 * hold three frames, so we want to send two frames at a time. For 625 * whole frames. Each frame occupies two slots in the FIFO. The
619 * capture, the receive FIFO is triggered when it contains one frame, so 626 * parameter for CCSR_DMA_MR_BWC() is rounded down the next power of two
620 * we want to receive one frame at a time. 627 * (MR[BWC] can only represent even powers of two).
628 *
629 * To simplify the process, we set BWC to the largest value that is
630 * less than or equal to the FIFO watermark. For playback, this ensures
631 * that we transfer the maximum amount without overrunning the FIFO.
632 * For capture, this ensures that we transfer the maximum amount without
633 * underrunning the FIFO.
634 *
635 * f = SSI FIFO depth
636 * w = SSI watermark value (which equals f - 2)
637 * b = DMA bandwidth count (in bytes)
638 * s = sample size (in bytes, which equals frame_size * 2)
639 *
640 * For playback, we never transmit more than the transmit FIFO
641 * watermark, otherwise we might write more data than the FIFO can hold.
642 * The watermark is equal to the FIFO depth minus two.
643 *
644 * For capture, two equations must hold:
645 * w > f - (b / s)
646 * w >= b / s
647 *
648 * So, b > 2 * s, but b must also be <= s * w. To simplify, we set
649 * b = s * w, which is equal to
650 * (dma_private->ssi_fifo_depth - 2) * sample_bytes.
621 */ 651 */
622 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 652 mr |= CCSR_DMA_MR_BWC((dma_private->ssi_fifo_depth - 2) * sample_bytes);
623 mr |= CCSR_DMA_MR_BWC(2 * frame_size);
624 else
625 mr |= CCSR_DMA_MR_BWC(frame_size);
626 653
627 out_be32(&dma_channel->mr, mr); 654 out_be32(&dma_channel->mr, mr);
628 655
@@ -631,12 +658,7 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
631 658
632 link->count = cpu_to_be32(period_size); 659 link->count = cpu_to_be32(period_size);
633 660
634 /* Even though the DMA controller supports 36-bit addressing, 661 /* The snoop bit tells the DMA controller whether it should tell
635 * for simplicity we allow only 32-bit addresses for the audio
636 * buffer itself. This was enforced in fsl_dma_new() with the
637 * DMA mask.
638 *
639 * The snoop bit tells the DMA controller whether it should tell
640 * the ECM to snoop during a read or write to an address. For 662 * the ECM to snoop during a read or write to an address. For
641 * audio, we use DMA to transfer data between memory and an I/O 663 * audio, we use DMA to transfer data between memory and an I/O
642 * device (the SSI's STX0 or SRX0 register). Snooping is only 664 * device (the SSI's STX0 or SRX0 register). Snooping is only
@@ -651,20 +673,24 @@ static int fsl_dma_hw_params(struct snd_pcm_substream *substream,
651 * flush out the data for the previous period. So if you 673 * flush out the data for the previous period. So if you
652 * increased period_bytes_min to a large enough size, you might 674 * increased period_bytes_min to a large enough size, you might
653 * get more performance by not snooping, and you'll still be 675 * get more performance by not snooping, and you'll still be
654 * okay. 676 * okay. You'll need to update fsl_dma_update_pointers() also.
655 */ 677 */
656 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 678 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
657 link->source_addr = cpu_to_be32(temp_addr); 679 link->source_addr = cpu_to_be32(temp_addr);
658 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); 680 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
681 upper_32_bits(temp_addr));
659 682
660 link->dest_addr = cpu_to_be32(ssi_sxx_phys); 683 link->dest_addr = cpu_to_be32(ssi_sxx_phys);
661 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); 684 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP |
685 upper_32_bits(ssi_sxx_phys));
662 } else { 686 } else {
663 link->source_addr = cpu_to_be32(ssi_sxx_phys); 687 link->source_addr = cpu_to_be32(ssi_sxx_phys);
664 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP); 688 link->source_attr = cpu_to_be32(CCSR_DMA_ATR_NOSNOOP |
689 upper_32_bits(ssi_sxx_phys));
665 690
666 link->dest_addr = cpu_to_be32(temp_addr); 691 link->dest_addr = cpu_to_be32(temp_addr);
667 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP); 692 link->dest_attr = cpu_to_be32(CCSR_DMA_ATR_SNOOP |
693 upper_32_bits(temp_addr));
668 } 694 }
669 695
670 temp_addr += period_size; 696 temp_addr += period_size;
@@ -689,14 +715,29 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
689{ 715{
690 struct snd_pcm_runtime *runtime = substream->runtime; 716 struct snd_pcm_runtime *runtime = substream->runtime;
691 struct fsl_dma_private *dma_private = runtime->private_data; 717 struct fsl_dma_private *dma_private = runtime->private_data;
718 struct snd_soc_pcm_runtime *rtd = substream->private_data;
719 struct device *dev = rtd->platform->dev;
692 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel; 720 struct ccsr_dma_channel __iomem *dma_channel = dma_private->dma_channel;
693 dma_addr_t position; 721 dma_addr_t position;
694 snd_pcm_uframes_t frames; 722 snd_pcm_uframes_t frames;
695 723
696 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 724 /* Obtain the current DMA pointer, but don't read the ESAD bits if we
725 * only have 32-bit DMA addresses. This function is typically called
726 * in interrupt context, so we need to optimize it.
727 */
728 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
697 position = in_be32(&dma_channel->sar); 729 position = in_be32(&dma_channel->sar);
698 else 730#ifdef CONFIG_PHYS_64BIT
731 position |= (u64)(in_be32(&dma_channel->satr) &
732 CCSR_DMA_ATR_ESAD_MASK) << 32;
733#endif
734 } else {
699 position = in_be32(&dma_channel->dar); 735 position = in_be32(&dma_channel->dar);
736#ifdef CONFIG_PHYS_64BIT
737 position |= (u64)(in_be32(&dma_channel->datr) &
738 CCSR_DMA_ATR_ESAD_MASK) << 32;
739#endif
740 }
700 741
701 /* 742 /*
702 * When capture is started, the SSI immediately starts to fill its FIFO. 743 * When capture is started, the SSI immediately starts to fill its FIFO.
@@ -710,8 +751,7 @@ static snd_pcm_uframes_t fsl_dma_pointer(struct snd_pcm_substream *substream)
710 751
711 if ((position < dma_private->dma_buf_phys) || 752 if ((position < dma_private->dma_buf_phys) ||
712 (position > dma_private->dma_buf_end)) { 753 (position > dma_private->dma_buf_end)) {
713 dev_err(substream->pcm->card->dev, 754 dev_err(dev, "dma pointer is out of range, halting stream\n");
714 "dma pointer is out of range, halting stream\n");
715 return SNDRV_PCM_POS_XRUN; 755 return SNDRV_PCM_POS_XRUN;
716 } 756 }
717 757
@@ -772,26 +812,28 @@ static int fsl_dma_close(struct snd_pcm_substream *substream)
772{ 812{
773 struct snd_pcm_runtime *runtime = substream->runtime; 813 struct snd_pcm_runtime *runtime = substream->runtime;
774 struct fsl_dma_private *dma_private = runtime->private_data; 814 struct fsl_dma_private *dma_private = runtime->private_data;
775 int dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; 815 struct snd_soc_pcm_runtime *rtd = substream->private_data;
816 struct device *dev = rtd->platform->dev;
817 struct dma_object *dma =
818 container_of(rtd->platform->driver, struct dma_object, dai);
776 819
777 if (dma_private) { 820 if (dma_private) {
778 if (dma_private->irq) 821 if (dma_private->irq)
779 free_irq(dma_private->irq, dma_private); 822 free_irq(dma_private->irq, dma_private);
780 823
781 if (dma_private->ld_buf_phys) { 824 if (dma_private->ld_buf_phys) {
782 dma_unmap_single(substream->pcm->card->dev, 825 dma_unmap_single(dev, dma_private->ld_buf_phys,
783 dma_private->ld_buf_phys, 826 sizeof(dma_private->link),
784 sizeof(dma_private->link), DMA_TO_DEVICE); 827 DMA_TO_DEVICE);
785 } 828 }
786 829
787 /* Deallocate the fsl_dma_private structure */ 830 /* Deallocate the fsl_dma_private structure */
788 dma_free_coherent(substream->pcm->card->dev, 831 dma_free_coherent(dev, sizeof(struct fsl_dma_private),
789 sizeof(struct fsl_dma_private), 832 dma_private, dma_private->ld_buf_phys);
790 dma_private, dma_private->ld_buf_phys);
791 substream->runtime->private_data = NULL; 833 substream->runtime->private_data = NULL;
792 } 834 }
793 835
794 dma_global_data.assigned[dir] = 0; 836 dma->assigned = 0;
795 837
796 return 0; 838 return 0;
797} 839}
@@ -814,6 +856,37 @@ static void fsl_dma_free_dma_buffers(struct snd_pcm *pcm)
814 } 856 }
815} 857}
816 858
859/**
860 * find_ssi_node -- returns the SSI node that points to his DMA channel node
861 *
862 * Although this DMA driver attempts to operate independently of the other
863 * devices, it still needs to determine some information about the SSI device
864 * that it's working with. Unfortunately, the device tree does not contain
865 * a pointer from the DMA channel node to the SSI node -- the pointer goes the
866 * other way. So we need to scan the device tree for SSI nodes until we find
867 * the one that points to the given DMA channel node. It's ugly, but at least
868 * it's contained in this one function.
869 */
870static struct device_node *find_ssi_node(struct device_node *dma_channel_np)
871{
872 struct device_node *ssi_np, *np;
873
874 for_each_compatible_node(ssi_np, NULL, "fsl,mpc8610-ssi") {
875 /* Check each DMA phandle to see if it points to us. We
876 * assume that device_node pointers are a valid comparison.
877 */
878 np = of_parse_phandle(ssi_np, "fsl,playback-dma", 0);
879 if (np == dma_channel_np)
880 return ssi_np;
881
882 np = of_parse_phandle(ssi_np, "fsl,capture-dma", 0);
883 if (np == dma_channel_np)
884 return ssi_np;
885 }
886
887 return NULL;
888}
889
817static struct snd_pcm_ops fsl_dma_ops = { 890static struct snd_pcm_ops fsl_dma_ops = {
818 .open = fsl_dma_open, 891 .open = fsl_dma_open,
819 .close = fsl_dma_close, 892 .close = fsl_dma_close,
@@ -823,59 +896,114 @@ static struct snd_pcm_ops fsl_dma_ops = {
823 .pointer = fsl_dma_pointer, 896 .pointer = fsl_dma_pointer,
824}; 897};
825 898
826struct snd_soc_platform fsl_soc_platform = { 899static int __devinit fsl_soc_dma_probe(struct platform_device *pdev,
827 .name = "fsl-dma", 900 const struct of_device_id *match)
828 .pcm_ops = &fsl_dma_ops, 901 {
829 .pcm_new = fsl_dma_new, 902 struct dma_object *dma;
830 .pcm_free = fsl_dma_free_dma_buffers, 903 struct device_node *np = pdev->dev.of_node;
831}; 904 struct device_node *ssi_np;
832EXPORT_SYMBOL_GPL(fsl_soc_platform); 905 struct resource res;
906 const uint32_t *iprop;
907 int ret;
833 908
834/** 909 /* Find the SSI node that points to us. */
835 * fsl_dma_configure: store the DMA parameters from the fabric driver. 910 ssi_np = find_ssi_node(np);
836 * 911 if (!ssi_np) {
837 * This function is called by the ASoC fabric driver to give us the DMA and 912 dev_err(&pdev->dev, "cannot find parent SSI node\n");
838 * SSI channel information. 913 return -ENODEV;
839 * 914 }
840 * Unfortunately, ASoC V1 does make it possible to determine the DMA/SSI 915
841 * data when a substream is created, so for now we need to store this data 916 ret = of_address_to_resource(ssi_np, 0, &res);
842 * into a global variable. This means that we can only support one DMA 917 if (ret) {
843 * controller, and hence only one SSI. 918 dev_err(&pdev->dev, "could not determine resources for %s\n",
844 */ 919 ssi_np->full_name);
845int fsl_dma_configure(struct fsl_dma_info *dma_info) 920 of_node_put(ssi_np);
921 return ret;
922 }
923
924 dma = kzalloc(sizeof(*dma) + strlen(np->full_name), GFP_KERNEL);
925 if (!dma) {
926 dev_err(&pdev->dev, "could not allocate dma object\n");
927 of_node_put(ssi_np);
928 return -ENOMEM;
929 }
930
931 strcpy(dma->path, np->full_name);
932 dma->dai.ops = &fsl_dma_ops;
933 dma->dai.pcm_new = fsl_dma_new;
934 dma->dai.pcm_free = fsl_dma_free_dma_buffers;
935
936 /* Store the SSI-specific information that we need */
937 dma->ssi_stx_phys = res.start + offsetof(struct ccsr_ssi, stx0);
938 dma->ssi_srx_phys = res.start + offsetof(struct ccsr_ssi, srx0);
939
940 iprop = of_get_property(ssi_np, "fsl,fifo-depth", NULL);
941 if (iprop)
942 dma->ssi_fifo_depth = *iprop;
943 else
944 /* Older 8610 DTs didn't have the fifo-depth property */
945 dma->ssi_fifo_depth = 8;
946
947 of_node_put(ssi_np);
948
949 ret = snd_soc_register_platform(&pdev->dev, &dma->dai);
950 if (ret) {
951 dev_err(&pdev->dev, "could not register platform\n");
952 kfree(dma);
953 return ret;
954 }
955
956 dma->channel = of_iomap(np, 0);
957 dma->irq = irq_of_parse_and_map(np, 0);
958
959 dev_set_drvdata(&pdev->dev, dma);
960
961 return 0;
962}
963
964static int __devexit fsl_soc_dma_remove(struct platform_device *pdev)
846{ 965{
847 static int initialized; 966 struct dma_object *dma = dev_get_drvdata(&pdev->dev);
848 967
849 /* We only support one DMA controller for now */ 968 snd_soc_unregister_platform(&pdev->dev);
850 if (initialized) 969 iounmap(dma->channel);
851 return 0; 970 irq_dispose_mapping(dma->irq);
971 kfree(dma);
852 972
853 dma_global_data.ssi_stx_phys = dma_info->ssi_stx_phys; 973 return 0;
854 dma_global_data.ssi_srx_phys = dma_info->ssi_srx_phys;
855 dma_global_data.dma_channel[0] = dma_info->dma_channel[0];
856 dma_global_data.dma_channel[1] = dma_info->dma_channel[1];
857 dma_global_data.irq[0] = dma_info->dma_irq[0];
858 dma_global_data.irq[1] = dma_info->dma_irq[1];
859 dma_global_data.assigned[0] = 0;
860 dma_global_data.assigned[1] = 0;
861
862 initialized = 1;
863 return 1;
864} 974}
865EXPORT_SYMBOL_GPL(fsl_dma_configure);
866 975
867static int __init fsl_soc_platform_init(void) 976static const struct of_device_id fsl_soc_dma_ids[] = {
977 { .compatible = "fsl,ssi-dma-channel", },
978 {}
979};
980MODULE_DEVICE_TABLE(of, fsl_soc_dma_ids);
981
982static struct of_platform_driver fsl_soc_dma_driver = {
983 .driver = {
984 .name = "fsl-pcm-audio",
985 .owner = THIS_MODULE,
986 .of_match_table = fsl_soc_dma_ids,
987 },
988 .probe = fsl_soc_dma_probe,
989 .remove = __devexit_p(fsl_soc_dma_remove),
990};
991
992static int __init fsl_soc_dma_init(void)
868{ 993{
869 return snd_soc_register_platform(&fsl_soc_platform); 994 pr_info("Freescale Elo DMA ASoC PCM Driver\n");
995
996 return of_register_platform_driver(&fsl_soc_dma_driver);
870} 997}
871module_init(fsl_soc_platform_init);
872 998
873static void __exit fsl_soc_platform_exit(void) 999static void __exit fsl_soc_dma_exit(void)
874{ 1000{
875 snd_soc_unregister_platform(&fsl_soc_platform); 1001 of_unregister_platform_driver(&fsl_soc_dma_driver);
876} 1002}
877module_exit(fsl_soc_platform_exit); 1003
1004module_init(fsl_soc_dma_init);
1005module_exit(fsl_soc_dma_exit);
878 1006
879MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 1007MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
880MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module"); 1008MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver");
881MODULE_LICENSE("GPL"); 1009MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_dma.h b/sound/soc/fsl/fsl_dma.h
index 385d4a42603c..78fee97e8036 100644
--- a/sound/soc/fsl/fsl_dma.h
+++ b/sound/soc/fsl/fsl_dma.h
@@ -126,24 +126,4 @@ struct fsl_dma_link_descriptor {
126 u8 res[4]; /* Reserved */ 126 u8 res[4]; /* Reserved */
127} __attribute__ ((aligned(32), packed)); 127} __attribute__ ((aligned(32), packed));
128 128
129/* DMA information needed to create a snd_soc_dai object
130 *
131 * ssi_stx_phys: bus address of SSI STX register to use
132 * ssi_srx_phys: bus address of SSI SRX register to use
133 * dma[0]: points to the DMA channel to use for playback
134 * dma[1]: points to the DMA channel to use for capture
135 * dma_irq[0]: IRQ of the DMA channel to use for playback
136 * dma_irq[1]: IRQ of the DMA channel to use for capture
137 */
138struct fsl_dma_info {
139 dma_addr_t ssi_stx_phys;
140 dma_addr_t ssi_srx_phys;
141 struct ccsr_dma_channel __iomem *dma_channel[2];
142 unsigned int dma_irq[2];
143};
144
145extern struct snd_soc_platform fsl_soc_platform;
146
147int fsl_dma_configure(struct fsl_dma_info *dma_info);
148
149#endif 129#endif
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 762c1b8e8e4e..4cc167a7aeb8 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -3,10 +3,11 @@
3 * 3 *
4 * Author: Timur Tabi <timur@freescale.com> 4 * Author: Timur Tabi <timur@freescale.com>
5 * 5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed 6 * Copyright 2007-2010 Freescale Semiconductor, Inc.
7 * under the terms of the GNU General Public License version 2. This 7 *
8 * program is licensed "as is" without any warranty of any kind, whether 8 * This file is licensed under the terms of the GNU General Public License
9 * express or implied. 9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
10 */ 11 */
11 12
12#include <linux/init.h> 13#include <linux/init.h>
@@ -15,6 +16,7 @@
15#include <linux/device.h> 16#include <linux/device.h>
16#include <linux/delay.h> 17#include <linux/delay.h>
17#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/of_platform.h>
18 20
19#include <sound/core.h> 21#include <sound/core.h>
20#include <sound/pcm.h> 22#include <sound/pcm.h>
@@ -22,8 +24,6 @@
22#include <sound/initval.h> 24#include <sound/initval.h>
23#include <sound/soc.h> 25#include <sound/soc.h>
24 26
25#include <asm/immap_86xx.h>
26
27#include "fsl_ssi.h" 27#include "fsl_ssi.h"
28 28
29/** 29/**
@@ -71,33 +71,32 @@
71/** 71/**
72 * fsl_ssi_private: per-SSI private data 72 * fsl_ssi_private: per-SSI private data
73 * 73 *
74 * @name: short name for this device ("SSI0", "SSI1", etc)
75 * @ssi: pointer to the SSI's registers 74 * @ssi: pointer to the SSI's registers
76 * @ssi_phys: physical address of the SSI registers 75 * @ssi_phys: physical address of the SSI registers
77 * @irq: IRQ of this SSI 76 * @irq: IRQ of this SSI
78 * @first_stream: pointer to the stream that was opened first 77 * @first_stream: pointer to the stream that was opened first
79 * @second_stream: pointer to second stream 78 * @second_stream: pointer to second stream
80 * @dev: struct device pointer
81 * @playback: the number of playback streams opened 79 * @playback: the number of playback streams opened
82 * @capture: the number of capture streams opened 80 * @capture: the number of capture streams opened
83 * @asynchronous: 0=synchronous mode, 1=asynchronous mode 81 * @asynchronous: 0=synchronous mode, 1=asynchronous mode
84 * @cpu_dai: the CPU DAI for this device 82 * @cpu_dai: the CPU DAI for this device
85 * @dev_attr: the sysfs device attribute structure 83 * @dev_attr: the sysfs device attribute structure
86 * @stats: SSI statistics 84 * @stats: SSI statistics
85 * @name: name for this device
87 */ 86 */
88struct fsl_ssi_private { 87struct fsl_ssi_private {
89 char name[8];
90 struct ccsr_ssi __iomem *ssi; 88 struct ccsr_ssi __iomem *ssi;
91 dma_addr_t ssi_phys; 89 dma_addr_t ssi_phys;
92 unsigned int irq; 90 unsigned int irq;
93 struct snd_pcm_substream *first_stream; 91 struct snd_pcm_substream *first_stream;
94 struct snd_pcm_substream *second_stream; 92 struct snd_pcm_substream *second_stream;
95 struct device *dev;
96 unsigned int playback; 93 unsigned int playback;
97 unsigned int capture; 94 unsigned int capture;
98 int asynchronous; 95 int asynchronous;
99 struct snd_soc_dai cpu_dai; 96 unsigned int fifo_depth;
97 struct snd_soc_dai_driver cpu_dai_drv;
100 struct device_attribute dev_attr; 98 struct device_attribute dev_attr;
99 struct platform_device *pdev;
101 100
102 struct { 101 struct {
103 unsigned int rfrc; 102 unsigned int rfrc;
@@ -122,6 +121,8 @@ struct fsl_ssi_private {
122 unsigned int tfe1; 121 unsigned int tfe1;
123 unsigned int tfe0; 122 unsigned int tfe0;
124 } stats; 123 } stats;
124
125 char name[1];
125}; 126};
126 127
127/** 128/**
@@ -280,7 +281,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
280 struct snd_soc_dai *dai) 281 struct snd_soc_dai *dai)
281{ 282{
282 struct snd_soc_pcm_runtime *rtd = substream->private_data; 283 struct snd_soc_pcm_runtime *rtd = substream->private_data;
283 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 284 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
284 285
285 /* 286 /*
286 * If this is the first stream opened, then request the IRQ 287 * If this is the first stream opened, then request the IRQ
@@ -290,6 +291,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
290 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 291 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
291 int ret; 292 int ret;
292 293
294 /* The 'name' should not have any slashes in it. */
293 ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, 295 ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0,
294 ssi_private->name, ssi_private); 296 ssi_private->name, ssi_private);
295 if (ret < 0) { 297 if (ret < 0) {
@@ -336,11 +338,20 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
336 338
337 /* 339 /*
338 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We 340 * Set the watermark for transmit FIFI 0 and receive FIFO 0. We
339 * don't use FIFO 1. Since the SSI only supports stereo, the 341 * don't use FIFO 1. We program the transmit water to signal a
340 * watermark should never be an odd number. 342 * DMA transfer if there are only two (or fewer) elements left
343 * in the FIFO. Two elements equals one frame (left channel,
344 * right channel). This value, however, depends on the depth of
345 * the transmit buffer.
346 *
347 * We program the receive FIFO to notify us if at least two
348 * elements (one frame) have been written to the FIFO. We could
349 * make this value larger (and maybe we should), but this way
350 * data will be written to memory as soon as it's available.
341 */ 351 */
342 out_be32(&ssi->sfcsr, 352 out_be32(&ssi->sfcsr,
343 CCSR_SSI_SFCSR_TFWM0(6) | CCSR_SSI_SFCSR_RFWM0(2)); 353 CCSR_SSI_SFCSR_TFWM0(ssi_private->fifo_depth - 2) |
354 CCSR_SSI_SFCSR_RFWM0(ssi_private->fifo_depth - 2));
344 355
345 /* 356 /*
346 * We keep the SSI disabled because if we enable it, then the 357 * We keep the SSI disabled because if we enable it, then the
@@ -422,7 +433,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
422static int fsl_ssi_hw_params(struct snd_pcm_substream *substream, 433static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
423 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai) 434 struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
424{ 435{
425 struct fsl_ssi_private *ssi_private = cpu_dai->private_data; 436 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
426 437
427 if (substream == ssi_private->first_stream) { 438 if (substream == ssi_private->first_stream) {
428 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 439 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
@@ -458,7 +469,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
458 struct snd_soc_dai *dai) 469 struct snd_soc_dai *dai)
459{ 470{
460 struct snd_soc_pcm_runtime *rtd = substream->private_data; 471 struct snd_soc_pcm_runtime *rtd = substream->private_data;
461 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 472 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
462 struct ccsr_ssi __iomem *ssi = ssi_private->ssi; 473 struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
463 474
464 switch (cmd) { 475 switch (cmd) {
@@ -497,7 +508,7 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
497 struct snd_soc_dai *dai) 508 struct snd_soc_dai *dai)
498{ 509{
499 struct snd_soc_pcm_runtime *rtd = substream->private_data; 510 struct snd_soc_pcm_runtime *rtd = substream->private_data;
500 struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; 511 struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
501 512
502 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 513 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
503 ssi_private->playback--; 514 ssi_private->playback--;
@@ -523,56 +534,15 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
523 } 534 }
524} 535}
525 536
526/**
527 * fsl_ssi_set_sysclk: set the clock frequency and direction
528 *
529 * This function is called by the machine driver to tell us what the clock
530 * frequency and direction are.
531 *
532 * Currently, we only support operating as a clock slave (SND_SOC_CLOCK_IN),
533 * and we don't care about the frequency. Return an error if the direction
534 * is not SND_SOC_CLOCK_IN.
535 *
536 * @clk_id: reserved, should be zero
537 * @freq: the frequency of the given clock ID, currently ignored
538 * @dir: SND_SOC_CLOCK_IN (clock slave) or SND_SOC_CLOCK_OUT (clock master)
539 */
540static int fsl_ssi_set_sysclk(struct snd_soc_dai *cpu_dai,
541 int clk_id, unsigned int freq, int dir)
542{
543
544 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
545}
546
547/**
548 * fsl_ssi_set_fmt: set the serial format.
549 *
550 * This function is called by the machine driver to tell us what serial
551 * format to use.
552 *
553 * Currently, we only support I2S mode. Return an error if the format is
554 * not SND_SOC_DAIFMT_I2S.
555 *
556 * @format: one of SND_SOC_DAIFMT_xxx
557 */
558static int fsl_ssi_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
559{
560 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
561}
562
563/**
564 * fsl_ssi_dai_template: template CPU DAI for the SSI
565 */
566static struct snd_soc_dai_ops fsl_ssi_dai_ops = { 537static struct snd_soc_dai_ops fsl_ssi_dai_ops = {
567 .startup = fsl_ssi_startup, 538 .startup = fsl_ssi_startup,
568 .hw_params = fsl_ssi_hw_params, 539 .hw_params = fsl_ssi_hw_params,
569 .shutdown = fsl_ssi_shutdown, 540 .shutdown = fsl_ssi_shutdown,
570 .trigger = fsl_ssi_trigger, 541 .trigger = fsl_ssi_trigger,
571 .set_sysclk = fsl_ssi_set_sysclk,
572 .set_fmt = fsl_ssi_set_fmt,
573}; 542};
574 543
575static struct snd_soc_dai fsl_ssi_dai_template = { 544/* Template for the CPU dai driver structure */
545static struct snd_soc_dai_driver fsl_ssi_dai_template = {
576 .playback = { 546 .playback = {
577 /* The SSI does not support monaural audio. */ 547 /* The SSI does not support monaural audio. */
578 .channels_min = 2, 548 .channels_min = 2,
@@ -640,95 +610,195 @@ static ssize_t fsl_sysfs_ssi_show(struct device *dev,
640} 610}
641 611
642/** 612/**
643 * fsl_ssi_create_dai: create a snd_soc_dai structure 613 * Make every character in a string lower-case
644 *
645 * This function is called by the machine driver to create a snd_soc_dai
646 * structure. The function creates an ssi_private object, which contains
647 * the snd_soc_dai. It also creates the sysfs statistics device.
648 */ 614 */
649struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) 615static void make_lowercase(char *s)
616{
617 char *p = s;
618 char c;
619
620 while ((c = *p)) {
621 if ((c >= 'A') && (c <= 'Z'))
622 *p = c + ('a' - 'A');
623 p++;
624 }
625}
626
627static int __devinit fsl_ssi_probe(struct platform_device *pdev,
628 const struct of_device_id *match)
650{ 629{
651 struct snd_soc_dai *fsl_ssi_dai;
652 struct fsl_ssi_private *ssi_private; 630 struct fsl_ssi_private *ssi_private;
653 int ret = 0; 631 int ret = 0;
654 struct device_attribute *dev_attr; 632 struct device_attribute *dev_attr = NULL;
633 struct device_node *np = pdev->dev.of_node;
634 const char *p, *sprop;
635 const uint32_t *iprop;
636 struct resource res;
637 char name[64];
638
639 /* SSIs that are not connected on the board should have a
640 * status = "disabled"
641 * property in their device tree nodes.
642 */
643 if (!of_device_is_available(np))
644 return -ENODEV;
645
646 /* Check for a codec-handle property. */
647 if (!of_get_property(np, "codec-handle", NULL)) {
648 dev_err(&pdev->dev, "missing codec-handle property\n");
649 return -ENODEV;
650 }
655 651
656 ssi_private = kzalloc(sizeof(struct fsl_ssi_private), GFP_KERNEL); 652 /* We only support the SSI in "I2S Slave" mode */
653 sprop = of_get_property(np, "fsl,mode", NULL);
654 if (!sprop || strcmp(sprop, "i2s-slave")) {
655 dev_notice(&pdev->dev, "mode %s is unsupported\n", sprop);
656 return -ENODEV;
657 }
658
659 /* The DAI name is the last part of the full name of the node. */
660 p = strrchr(np->full_name, '/') + 1;
661 ssi_private = kzalloc(sizeof(struct fsl_ssi_private) + strlen(p),
662 GFP_KERNEL);
657 if (!ssi_private) { 663 if (!ssi_private) {
658 dev_err(ssi_info->dev, "could not allocate DAI object\n"); 664 dev_err(&pdev->dev, "could not allocate DAI object\n");
659 return NULL; 665 return -ENOMEM;
660 } 666 }
661 memcpy(&ssi_private->cpu_dai, &fsl_ssi_dai_template,
662 sizeof(struct snd_soc_dai));
663 667
664 fsl_ssi_dai = &ssi_private->cpu_dai; 668 strcpy(ssi_private->name, p);
665 dev_attr = &ssi_private->dev_attr;
666 669
667 sprintf(ssi_private->name, "ssi%u", (u8) ssi_info->id); 670 /* Initialize this copy of the CPU DAI driver structure */
668 ssi_private->ssi = ssi_info->ssi; 671 memcpy(&ssi_private->cpu_dai_drv, &fsl_ssi_dai_template,
669 ssi_private->ssi_phys = ssi_info->ssi_phys; 672 sizeof(fsl_ssi_dai_template));
670 ssi_private->irq = ssi_info->irq; 673 ssi_private->cpu_dai_drv.name = ssi_private->name;
671 ssi_private->dev = ssi_info->dev;
672 ssi_private->asynchronous = ssi_info->asynchronous;
673 674
674 dev_set_drvdata(ssi_private->dev, fsl_ssi_dai); 675 /* Get the addresses and IRQ */
676 ret = of_address_to_resource(np, 0, &res);
677 if (ret) {
678 dev_err(&pdev->dev, "could not determine device resources\n");
679 kfree(ssi_private);
680 return ret;
681 }
682 ssi_private->ssi = ioremap(res.start, 1 + res.end - res.start);
683 ssi_private->ssi_phys = res.start;
684 ssi_private->irq = irq_of_parse_and_map(np, 0);
685
686 /* Are the RX and the TX clocks locked? */
687 if (of_find_property(np, "fsl,ssi-asynchronous", NULL))
688 ssi_private->asynchronous = 1;
689 else
690 ssi_private->cpu_dai_drv.symmetric_rates = 1;
691
692 /* Determine the FIFO depth. */
693 iprop = of_get_property(np, "fsl,fifo-depth", NULL);
694 if (iprop)
695 ssi_private->fifo_depth = *iprop;
696 else
697 /* Older 8610 DTs didn't have the fifo-depth property */
698 ssi_private->fifo_depth = 8;
675 699
676 /* Initialize the the device_attribute structure */ 700 /* Initialize the the device_attribute structure */
677 dev_attr->attr.name = "ssi-stats"; 701 dev_attr = &ssi_private->dev_attr;
702 dev_attr->attr.name = "statistics";
678 dev_attr->attr.mode = S_IRUGO; 703 dev_attr->attr.mode = S_IRUGO;
679 dev_attr->show = fsl_sysfs_ssi_show; 704 dev_attr->show = fsl_sysfs_ssi_show;
680 705
681 ret = device_create_file(ssi_private->dev, dev_attr); 706 ret = device_create_file(&pdev->dev, dev_attr);
682 if (ret) { 707 if (ret) {
683 dev_err(ssi_info->dev, "could not create sysfs %s file\n", 708 dev_err(&pdev->dev, "could not create sysfs %s file\n",
684 ssi_private->dev_attr.attr.name); 709 ssi_private->dev_attr.attr.name);
685 kfree(fsl_ssi_dai); 710 goto error;
686 return NULL;
687 } 711 }
688 712
689 fsl_ssi_dai->private_data = ssi_private; 713 /* Register with ASoC */
690 fsl_ssi_dai->name = ssi_private->name; 714 dev_set_drvdata(&pdev->dev, ssi_private);
691 fsl_ssi_dai->id = ssi_info->id; 715
692 fsl_ssi_dai->dev = ssi_info->dev; 716 ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv);
693 fsl_ssi_dai->symmetric_rates = 1; 717 if (ret) {
718 dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
719 goto error;
720 }
694 721
695 ret = snd_soc_register_dai(fsl_ssi_dai); 722 /* Trigger the machine driver's probe function. The platform driver
696 if (ret != 0) { 723 * name of the machine driver is taken from the /model property of the
697 dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret); 724 * device tree. We also pass the address of the CPU DAI driver
698 kfree(fsl_ssi_dai); 725 * structure.
699 return NULL; 726 */
727 sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
728 /* Sometimes the model name has a "fsl," prefix, so we strip that. */
729 p = strrchr(sprop, ',');
730 if (p)
731 sprop = p + 1;
732 snprintf(name, sizeof(name), "snd-soc-%s", sprop);
733 make_lowercase(name);
734
735 ssi_private->pdev =
736 platform_device_register_data(&pdev->dev, name, 0, NULL, 0);
737 if (IS_ERR(ssi_private->pdev)) {
738 ret = PTR_ERR(ssi_private->pdev);
739 dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
740 goto error;
700 } 741 }
701 742
702 return fsl_ssi_dai; 743 return 0;
744
745error:
746 snd_soc_unregister_dai(&pdev->dev);
747 dev_set_drvdata(&pdev->dev, NULL);
748 if (dev_attr)
749 device_remove_file(&pdev->dev, dev_attr);
750 irq_dispose_mapping(ssi_private->irq);
751 iounmap(ssi_private->ssi);
752 kfree(ssi_private);
753
754 return ret;
703} 755}
704EXPORT_SYMBOL_GPL(fsl_ssi_create_dai);
705 756
706/** 757static int fsl_ssi_remove(struct platform_device *pdev)
707 * fsl_ssi_destroy_dai: destroy the snd_soc_dai object
708 *
709 * This function undoes the operations of fsl_ssi_create_dai()
710 */
711void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
712{ 758{
713 struct fsl_ssi_private *ssi_private = 759 struct fsl_ssi_private *ssi_private = dev_get_drvdata(&pdev->dev);
714 container_of(fsl_ssi_dai, struct fsl_ssi_private, cpu_dai);
715
716 device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
717 760
718 snd_soc_unregister_dai(&ssi_private->cpu_dai); 761 platform_device_unregister(ssi_private->pdev);
762 snd_soc_unregister_dai(&pdev->dev);
763 device_remove_file(&pdev->dev, &ssi_private->dev_attr);
719 764
720 kfree(ssi_private); 765 kfree(ssi_private);
766 dev_set_drvdata(&pdev->dev, NULL);
767
768 return 0;
721} 769}
722EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); 770
771static const struct of_device_id fsl_ssi_ids[] = {
772 { .compatible = "fsl,mpc8610-ssi", },
773 {}
774};
775MODULE_DEVICE_TABLE(of, fsl_ssi_ids);
776
777static struct of_platform_driver fsl_ssi_driver = {
778 .driver = {
779 .name = "fsl-ssi-dai",
780 .owner = THIS_MODULE,
781 .of_match_table = fsl_ssi_ids,
782 },
783 .probe = fsl_ssi_probe,
784 .remove = fsl_ssi_remove,
785};
723 786
724static int __init fsl_ssi_init(void) 787static int __init fsl_ssi_init(void)
725{ 788{
726 printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n"); 789 printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
727 790
728 return 0; 791 return of_register_platform_driver(&fsl_ssi_driver);
729} 792}
793
794static void __exit fsl_ssi_exit(void)
795{
796 of_unregister_platform_driver(&fsl_ssi_driver);
797}
798
730module_init(fsl_ssi_init); 799module_init(fsl_ssi_init);
800module_exit(fsl_ssi_exit);
731 801
732MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 802MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
733MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver"); 803MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
734MODULE_LICENSE("GPL"); 804MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/fsl_ssi.h b/sound/soc/fsl/fsl_ssi.h
index eade01feaab6..217300029b5b 100644
--- a/sound/soc/fsl/fsl_ssi.h
+++ b/sound/soc/fsl/fsl_ssi.h
@@ -196,31 +196,5 @@ struct ccsr_ssi {
196#define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT) 196#define CCSR_SSI_SOR_WAIT(x) (((x) & 3) << CCSR_SSI_SOR_WAIT_SHIFT)
197#define CCSR_SSI_SOR_SYNRST 0x00000001 197#define CCSR_SSI_SOR_SYNRST 0x00000001
198 198
199/* Instantiation data for an SSI interface
200 *
201 * This structure contains all the information that the the SSI driver needs
202 * to instantiate an SSI interface with ALSA. The machine driver should
203 * create this structure, fill it in, call fsl_ssi_create_dai(), and then
204 * delete the structure.
205 *
206 * id: which SSI this is (0, 1, etc. )
207 * ssi: pointer to the SSI's registers
208 * ssi_phys: physical address of the SSI registers
209 * irq: IRQ of this SSI
210 * dev: struct device, used to create the sysfs statistics file
211 * asynchronous: 0=synchronous mode, 1=asynchronous mode
212*/
213struct fsl_ssi_info {
214 unsigned int id;
215 struct ccsr_ssi __iomem *ssi;
216 dma_addr_t ssi_phys;
217 unsigned int irq;
218 struct device *dev;
219 int asynchronous;
220};
221
222struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info);
223void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai);
224
225#endif 199#endif
226 200
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 3dcd1469f283..dce6b551cd78 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -9,6 +9,8 @@
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/of_device.h> 10#include <linux/of_device.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/of_device.h>
13#include <linux/of_platform.h>
12 14
13#include <sound/soc.h> 15#include <sound/soc.h>
14 16
@@ -107,7 +109,7 @@ static int psc_dma_hw_free(struct snd_pcm_substream *substream)
107static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd) 109static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
108{ 110{
109 struct snd_soc_pcm_runtime *rtd = substream->private_data; 111 struct snd_soc_pcm_runtime *rtd = substream->private_data;
110 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 112 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
111 struct snd_pcm_runtime *runtime = substream->runtime; 113 struct snd_pcm_runtime *runtime = substream->runtime;
112 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); 114 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
113 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 115 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
@@ -212,7 +214,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream)
212{ 214{
213 struct snd_pcm_runtime *runtime = substream->runtime; 215 struct snd_pcm_runtime *runtime = substream->runtime;
214 struct snd_soc_pcm_runtime *rtd = substream->private_data; 216 struct snd_soc_pcm_runtime *rtd = substream->private_data;
215 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 217 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
216 struct psc_dma_stream *s; 218 struct psc_dma_stream *s;
217 int rc; 219 int rc;
218 220
@@ -239,7 +241,7 @@ static int psc_dma_open(struct snd_pcm_substream *substream)
239static int psc_dma_close(struct snd_pcm_substream *substream) 241static int psc_dma_close(struct snd_pcm_substream *substream)
240{ 242{
241 struct snd_soc_pcm_runtime *rtd = substream->private_data; 243 struct snd_soc_pcm_runtime *rtd = substream->private_data;
242 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 244 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
243 struct psc_dma_stream *s; 245 struct psc_dma_stream *s;
244 246
245 dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream); 247 dev_dbg(psc_dma->dev, "psc_dma_close(substream=%p)\n", substream);
@@ -264,7 +266,7 @@ static snd_pcm_uframes_t
264psc_dma_pointer(struct snd_pcm_substream *substream) 266psc_dma_pointer(struct snd_pcm_substream *substream)
265{ 267{
266 struct snd_soc_pcm_runtime *rtd = substream->private_data; 268 struct snd_soc_pcm_runtime *rtd = substream->private_data;
267 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 269 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
268 struct psc_dma_stream *s; 270 struct psc_dma_stream *s;
269 dma_addr_t count; 271 dma_addr_t count;
270 272
@@ -302,11 +304,11 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
302 struct snd_pcm *pcm) 304 struct snd_pcm *pcm)
303{ 305{
304 struct snd_soc_pcm_runtime *rtd = pcm->private_data; 306 struct snd_soc_pcm_runtime *rtd = pcm->private_data;
305 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 307 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
306 size_t size = psc_dma_hardware.buffer_bytes_max; 308 size_t size = psc_dma_hardware.buffer_bytes_max;
307 int rc = 0; 309 int rc = 0;
308 310
309 dev_dbg(rtd->socdev->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n", 311 dev_dbg(rtd->platform->dev, "psc_dma_new(card=%p, dai=%p, pcm=%p)\n",
310 card, dai, pcm); 312 card, dai, pcm);
311 313
312 if (!card->dev->dma_mask) 314 if (!card->dev->dma_mask)
@@ -328,8 +330,8 @@ static int psc_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
328 goto capture_alloc_err; 330 goto capture_alloc_err;
329 } 331 }
330 332
331 if (rtd->socdev->card->codec->ac97) 333 if (rtd->codec->ac97)
332 rtd->socdev->card->codec->ac97->private_data = psc_dma; 334 rtd->codec->ac97->private_data = psc_dma;
333 335
334 return 0; 336 return 0;
335 337
@@ -349,7 +351,7 @@ static void psc_dma_free(struct snd_pcm *pcm)
349 struct snd_pcm_substream *substream; 351 struct snd_pcm_substream *substream;
350 int stream; 352 int stream;
351 353
352 dev_dbg(rtd->socdev->dev, "psc_dma_free(pcm=%p)\n", pcm); 354 dev_dbg(rtd->platform->dev, "psc_dma_free(pcm=%p)\n", pcm);
353 355
354 for (stream = 0; stream < 2; stream++) { 356 for (stream = 0; stream < 2; stream++) {
355 substream = pcm->streams[stream].substream; 357 substream = pcm->streams[stream].substream;
@@ -361,15 +363,14 @@ static void psc_dma_free(struct snd_pcm *pcm)
361 } 363 }
362} 364}
363 365
364struct snd_soc_platform mpc5200_audio_dma_platform = { 366static struct snd_soc_platform_driver mpc5200_audio_dma_platform = {
365 .name = "mpc5200-psc-audio", 367 .ops = &psc_dma_ops,
366 .pcm_ops = &psc_dma_ops,
367 .pcm_new = &psc_dma_new, 368 .pcm_new = &psc_dma_new,
368 .pcm_free = &psc_dma_free, 369 .pcm_free = &psc_dma_free,
369}; 370};
370EXPORT_SYMBOL_GPL(mpc5200_audio_dma_platform);
371 371
372int mpc5200_audio_dma_create(struct platform_device *op) 372static int mpc5200_hpcd_probe(struct of_device *op,
373 const struct of_device_id *match)
373{ 374{
374 phys_addr_t fifo; 375 phys_addr_t fifo;
375 struct psc_dma *psc_dma; 376 struct psc_dma *psc_dma;
@@ -475,7 +476,7 @@ int mpc5200_audio_dma_create(struct platform_device *op)
475 dev_set_drvdata(&op->dev, psc_dma); 476 dev_set_drvdata(&op->dev, psc_dma);
476 477
477 /* Tell the ASoC OF helpers about it */ 478 /* Tell the ASoC OF helpers about it */
478 return snd_soc_register_platform(&mpc5200_audio_dma_platform); 479 return snd_soc_register_platform(&op->dev, &mpc5200_audio_dma_platform);
479out_irq: 480out_irq:
480 free_irq(psc_dma->irq, psc_dma); 481 free_irq(psc_dma->irq, psc_dma);
481 free_irq(psc_dma->capture.irq, &psc_dma->capture); 482 free_irq(psc_dma->capture.irq, &psc_dma->capture);
@@ -486,15 +487,14 @@ out_unmap:
486 iounmap(regs); 487 iounmap(regs);
487 return ret; 488 return ret;
488} 489}
489EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create);
490 490
491int mpc5200_audio_dma_destroy(struct platform_device *op) 491static int mpc5200_hpcd_remove(struct of_device *op)
492{ 492{
493 struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); 493 struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
494 494
495 dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n"); 495 dev_dbg(&op->dev, "mpc5200_audio_dma_destroy()\n");
496 496
497 snd_soc_unregister_platform(&mpc5200_audio_dma_platform); 497 snd_soc_unregister_platform(&op->dev);
498 498
499 bcom_gen_bd_rx_release(psc_dma->capture.bcom_task); 499 bcom_gen_bd_rx_release(psc_dma->capture.bcom_task);
500 bcom_gen_bd_tx_release(psc_dma->playback.bcom_task); 500 bcom_gen_bd_tx_release(psc_dma->playback.bcom_task);
@@ -510,7 +510,35 @@ int mpc5200_audio_dma_destroy(struct platform_device *op)
510 510
511 return 0; 511 return 0;
512} 512}
513EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); 513
514static struct of_device_id mpc5200_hpcd_match[] = {
515 {
516 .compatible = "fsl,mpc5200-pcm",
517 },
518 {}
519};
520MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match);
521
522static struct of_platform_driver mpc5200_hpcd_of_driver = {
523 .owner = THIS_MODULE,
524 .name = "mpc5200-pcm-audio",
525 .match_table = mpc5200_hpcd_match,
526 .probe = mpc5200_hpcd_probe,
527 .remove = mpc5200_hpcd_remove,
528};
529
530static int __init mpc5200_hpcd_init(void)
531{
532 return of_register_platform_driver(&mpc5200_hpcd_of_driver);
533}
534
535static void __exit mpc5200_hpcd_exit(void)
536{
537 of_unregister_platform_driver(&mpc5200_hpcd_of_driver);
538}
539
540module_init(mpc5200_hpcd_init);
541module_exit(mpc5200_hpcd_exit);
514 542
515MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); 543MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
516MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); 544MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
index ca99586f2ad9..a3c0cd5382fb 100644
--- a/sound/soc/fsl/mpc5200_dma.h
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -81,9 +81,4 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)
81 return &psc_dma->playback; 81 return &psc_dma->playback;
82} 82}
83 83
84int mpc5200_audio_dma_create(struct platform_device *op);
85int mpc5200_audio_dma_destroy(struct platform_device *op);
86
87extern struct snd_soc_platform mpc5200_audio_dma_platform;
88
89#endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ 84#endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index a9560235daee..40acc8e2b1ca 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -143,7 +143,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
143 struct snd_pcm_hw_params *params, 143 struct snd_pcm_hw_params *params,
144 struct snd_soc_dai *cpu_dai) 144 struct snd_soc_dai *cpu_dai)
145{ 145{
146 struct psc_dma *psc_dma = cpu_dai->private_data; 146 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
147 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); 147 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
148 148
149 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" 149 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
@@ -166,7 +166,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
166 struct snd_pcm_hw_params *params, 166 struct snd_pcm_hw_params *params,
167 struct snd_soc_dai *cpu_dai) 167 struct snd_soc_dai *cpu_dai)
168{ 168{
169 struct psc_dma *psc_dma = cpu_dai->private_data; 169 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
170 170
171 dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream); 171 dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream);
172 172
@@ -181,8 +181,7 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
181static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd, 181static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
182 struct snd_soc_dai *dai) 182 struct snd_soc_dai *dai)
183{ 183{
184 struct snd_soc_pcm_runtime *rtd = substream->private_data; 184 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(dai);
185 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
186 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma); 185 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
187 186
188 switch (cmd) { 187 switch (cmd) {
@@ -207,10 +206,9 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
207 return 0; 206 return 0;
208} 207}
209 208
210static int psc_ac97_probe(struct platform_device *pdev, 209static int psc_ac97_probe(struct snd_soc_dai *cpu_dai)
211 struct snd_soc_dai *cpu_dai)
212{ 210{
213 struct psc_dma *psc_dma = cpu_dai->private_data; 211 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
214 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 212 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
215 213
216 /* Go */ 214 /* Go */
@@ -237,9 +235,8 @@ static struct snd_soc_dai_ops psc_ac97_digital_ops = {
237 .hw_params = psc_ac97_hw_digital_params, 235 .hw_params = psc_ac97_hw_digital_params,
238}; 236};
239 237
240struct snd_soc_dai psc_ac97_dai[] = { 238static struct snd_soc_dai_driver psc_ac97_dai[] = {
241{ 239{
242 .name = "AC97",
243 .ac97_control = 1, 240 .ac97_control = 1,
244 .probe = psc_ac97_probe, 241 .probe = psc_ac97_probe,
245 .playback = { 242 .playback = {
@@ -257,7 +254,6 @@ struct snd_soc_dai psc_ac97_dai[] = {
257 .ops = &psc_ac97_analog_ops, 254 .ops = &psc_ac97_analog_ops,
258}, 255},
259{ 256{
260 .name = "SPDIF",
261 .ac97_control = 1, 257 .ac97_control = 1,
262 .playback = { 258 .playback = {
263 .channels_min = 1, 259 .channels_min = 1,
@@ -268,7 +264,6 @@ struct snd_soc_dai psc_ac97_dai[] = {
268 }, 264 },
269 .ops = &psc_ac97_digital_ops, 265 .ops = &psc_ac97_digital_ops,
270} }; 266} };
271EXPORT_SYMBOL_GPL(psc_ac97_dai);
272 267
273 268
274 269
@@ -280,18 +275,11 @@ EXPORT_SYMBOL_GPL(psc_ac97_dai);
280static int __devinit psc_ac97_of_probe(struct platform_device *op, 275static int __devinit psc_ac97_of_probe(struct platform_device *op,
281 const struct of_device_id *match) 276 const struct of_device_id *match)
282{ 277{
283 int rc, i; 278 int rc;
284 struct snd_ac97 ac97; 279 struct snd_ac97 ac97;
285 struct mpc52xx_psc __iomem *regs; 280 struct mpc52xx_psc __iomem *regs;
286 281
287 rc = mpc5200_audio_dma_create(op); 282 rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
288 if (rc != 0)
289 return rc;
290
291 for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
292 psc_ac97_dai[i].dev = &op->dev;
293
294 rc = snd_soc_register_dais(psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai));
295 if (rc != 0) { 283 if (rc != 0) {
296 dev_err(&op->dev, "Failed to register DAI\n"); 284 dev_err(&op->dev, "Failed to register DAI\n");
297 return rc; 285 return rc;
@@ -301,9 +289,6 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op,
301 regs = psc_dma->psc_regs; 289 regs = psc_dma->psc_regs;
302 ac97.private_data = psc_dma; 290 ac97.private_data = psc_dma;
303 291
304 for (i = 0; i < ARRAY_SIZE(psc_ac97_dai); i++)
305 psc_ac97_dai[i].private_data = psc_dma;
306
307 psc_dma->imr = 0; 292 psc_dma->imr = 0;
308 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); 293 out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr);
309 294
@@ -319,7 +304,8 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op,
319 304
320static int __devexit psc_ac97_of_remove(struct platform_device *op) 305static int __devexit psc_ac97_of_remove(struct platform_device *op)
321{ 306{
322 return mpc5200_audio_dma_destroy(op); 307 snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai));
308 return 0;
323} 309}
324 310
325/* Match table for of_platform binding */ 311/* Match table for of_platform binding */
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.h b/sound/soc/fsl/mpc5200_psc_ac97.h
index 4bc18c35c369..e881e784b270 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.h
+++ b/sound/soc/fsl/mpc5200_psc_ac97.h
@@ -7,8 +7,6 @@
7#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ 7#ifndef __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
8#define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__ 8#define __SOUND_SOC_FSL_MPC52xx_PSC_AC97_H__
9 9
10extern struct snd_soc_dai psc_ac97_dai[];
11
12#define MPC5200_AC97_NORMAL 0 10#define MPC5200_AC97_NORMAL 0
13#define MPC5200_AC97_SPDIF 1 11#define MPC5200_AC97_SPDIF 1
14 12
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 534f04cb15d7..74ffed41340f 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -40,7 +40,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
40 struct snd_soc_dai *dai) 40 struct snd_soc_dai *dai)
41{ 41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data; 42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 43 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(rtd->cpu_dai);
44 u32 mode; 44 u32 mode;
45 45
46 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" 46 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
@@ -88,7 +88,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
88static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, 88static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
89 int clk_id, unsigned int freq, int dir) 89 int clk_id, unsigned int freq, int dir)
90{ 90{
91 struct psc_dma *psc_dma = cpu_dai->private_data; 91 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
92 dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n", 92 dev_dbg(psc_dma->dev, "psc_i2s_set_sysclk(cpu_dai=%p, dir=%i)\n",
93 cpu_dai, dir); 93 cpu_dai, dir);
94 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL; 94 return (dir == SND_SOC_CLOCK_IN) ? 0 : -EINVAL;
@@ -107,7 +107,7 @@ static int psc_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
107 */ 107 */
108static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) 108static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
109{ 109{
110 struct psc_dma *psc_dma = cpu_dai->private_data; 110 struct psc_dma *psc_dma = snd_soc_dai_get_drvdata(cpu_dai);
111 dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n", 111 dev_dbg(psc_dma->dev, "psc_i2s_set_fmt(cpu_dai=%p, format=%i)\n",
112 cpu_dai, format); 112 cpu_dai, format);
113 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL; 113 return (format == SND_SOC_DAIFMT_I2S) ? 0 : -EINVAL;
@@ -129,8 +129,7 @@ static struct snd_soc_dai_ops psc_i2s_dai_ops = {
129 .set_fmt = psc_i2s_set_fmt, 129 .set_fmt = psc_i2s_set_fmt,
130}; 130};
131 131
132struct snd_soc_dai psc_i2s_dai[] = {{ 132static struct snd_soc_dai_driver psc_i2s_dai[] = {{
133 .name = "I2S",
134 .playback = { 133 .playback = {
135 .channels_min = 2, 134 .channels_min = 2,
136 .channels_max = 2, 135 .channels_max = 2,
@@ -145,7 +144,6 @@ struct snd_soc_dai psc_i2s_dai[] = {{
145 }, 144 },
146 .ops = &psc_i2s_dai_ops, 145 .ops = &psc_i2s_dai_ops,
147} }; 146} };
148EXPORT_SYMBOL_GPL(psc_i2s_dai);
149 147
150/* --------------------------------------------------------------------- 148/* ---------------------------------------------------------------------
151 * OF platform bus binding code: 149 * OF platform bus binding code:
@@ -159,11 +157,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op,
159 struct psc_dma *psc_dma; 157 struct psc_dma *psc_dma;
160 struct mpc52xx_psc __iomem *regs; 158 struct mpc52xx_psc __iomem *regs;
161 159
162 rc = mpc5200_audio_dma_create(op); 160 rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
163 if (rc != 0)
164 return rc;
165
166 rc = snd_soc_register_dais(psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai));
167 if (rc != 0) { 161 if (rc != 0) {
168 pr_err("Failed to register DAI\n"); 162 pr_err("Failed to register DAI\n");
169 return 0; 163 return 0;
@@ -207,7 +201,8 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op,
207 201
208static int __devexit psc_i2s_of_remove(struct platform_device *op) 202static int __devexit psc_i2s_of_remove(struct platform_device *op)
209{ 203{
210 return mpc5200_audio_dma_destroy(op); 204 snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai));
205 return 0;
211} 206}
212 207
213/* Match table for of_platform binding */ 208/* Match table for of_platform binding */
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 3b13b8d65262..0d7dcf1e4863 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -1,85 +1,97 @@
1/** 1/**
2 * Freescale MPC8610HPCD ALSA SoC Fabric driver 2 * Freescale MPC8610HPCD ALSA SoC Machine driver
3 * 3 *
4 * Author: Timur Tabi <timur@freescale.com> 4 * Author: Timur Tabi <timur@freescale.com>
5 * 5 *
6 * Copyright 2007-2008 Freescale Semiconductor, Inc. This file is licensed 6 * Copyright 2007-2010 Freescale Semiconductor, Inc.
7 * under the terms of the GNU General Public License version 2. This 7 *
8 * program is licensed "as is" without any warranty of any kind, whether 8 * This file is licensed under the terms of the GNU General Public License
9 * express or implied. 9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
10 */ 11 */
11 12
12#include <linux/slab.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/interrupt.h> 14#include <linux/interrupt.h>
15#include <linux/of_device.h> 15#include <linux/of_device.h>
16#include <linux/of_platform.h> 16#include <linux/slab.h>
17#include <sound/soc.h> 17#include <sound/soc.h>
18#include <asm/immap_86xx.h> 18#include <asm/fsl_guts.h>
19 19
20#include "../codecs/cs4270.h"
21#include "fsl_dma.h" 20#include "fsl_dma.h"
22#include "fsl_ssi.h" 21#include "fsl_ssi.h"
23 22
23/* There's only one global utilities register */
24static phys_addr_t guts_phys;
25
26#define DAI_NAME_SIZE 32
27
24/** 28/**
25 * mpc8610_hpcd_data: fabric-specific ASoC device data 29 * mpc8610_hpcd_data: machine-specific ASoC device data
26 * 30 *
27 * This structure contains data for a single sound platform device on an 31 * This structure contains data for a single sound platform device on an
28 * MPC8610 HPCD. Some of the data is taken from the device tree. 32 * MPC8610 HPCD. Some of the data is taken from the device tree.
29 */ 33 */
30struct mpc8610_hpcd_data { 34struct mpc8610_hpcd_data {
31 struct snd_soc_device sound_devdata; 35 struct snd_soc_dai_link dai[2];
32 struct snd_soc_dai_link dai; 36 struct snd_soc_card card;
33 struct snd_soc_card machine;
34 unsigned int dai_format; 37 unsigned int dai_format;
35 unsigned int codec_clk_direction; 38 unsigned int codec_clk_direction;
36 unsigned int cpu_clk_direction; 39 unsigned int cpu_clk_direction;
37 unsigned int clk_frequency; 40 unsigned int clk_frequency;
38 struct ccsr_guts __iomem *guts; 41 unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */
39 struct ccsr_ssi __iomem *ssi; 42 unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */
40 unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */
41 unsigned int ssi_irq;
42 unsigned int dma_id; /* 0 = DMA1, 1 = DMA2, etc */
43 unsigned int dma_irq[2];
44 struct ccsr_dma_channel __iomem *dma[2];
45 unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/ 43 unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
44 char codec_dai_name[DAI_NAME_SIZE];
45 char codec_name[DAI_NAME_SIZE];
46 char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
46}; 47};
47 48
48/** 49/**
49 * mpc8610_hpcd_machine_probe: initialize the board 50 * mpc8610_hpcd_machine_probe: initialize the board
50 * 51 *
51 * This function is called when platform_device_add() is called. It is used 52 * This function is used to initialize the board-specific hardware.
52 * to initialize the board-specific hardware.
53 * 53 *
54 * Here we program the DMACR and PMUXCR registers. 54 * Here we program the DMACR and PMUXCR registers.
55 */ 55 */
56static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device) 56static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
57{ 57{
58 struct snd_soc_card *card = platform_get_drvdata(sound_device);
58 struct mpc8610_hpcd_data *machine_data = 59 struct mpc8610_hpcd_data *machine_data =
59 sound_device->dev.platform_data; 60 container_of(card, struct mpc8610_hpcd_data, card);
61 struct ccsr_guts_86xx __iomem *guts;
60 62
61 /* Program the signal routing between the SSI and the DMA */ 63 guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
62 guts_set_dmacr(machine_data->guts, machine_data->dma_id, 64 if (!guts) {
63 machine_data->dma_channel_id[0], CCSR_GUTS_DMACR_DEV_SSI); 65 dev_err(card->dev, "could not map global utilities\n");
64 guts_set_dmacr(machine_data->guts, machine_data->dma_id, 66 return -ENOMEM;
65 machine_data->dma_channel_id[1], CCSR_GUTS_DMACR_DEV_SSI); 67 }
66 68
67 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, 69 /* Program the signal routing between the SSI and the DMA */
68 machine_data->dma_channel_id[0], 0); 70 guts_set_dmacr(guts, machine_data->dma_id[0],
69 guts_set_pmuxcr_dma(machine_data->guts, machine_data->dma_id, 71 machine_data->dma_channel_id[0],
70 machine_data->dma_channel_id[1], 0); 72 CCSR_GUTS_DMACR_DEV_SSI);
73 guts_set_dmacr(guts, machine_data->dma_id[1],
74 machine_data->dma_channel_id[1],
75 CCSR_GUTS_DMACR_DEV_SSI);
76
77 guts_set_pmuxcr_dma(guts, machine_data->dma_id[0],
78 machine_data->dma_channel_id[0], 0);
79 guts_set_pmuxcr_dma(guts, machine_data->dma_id[1],
80 machine_data->dma_channel_id[1], 0);
71 81
72 switch (machine_data->ssi_id) { 82 switch (machine_data->ssi_id) {
73 case 0: 83 case 0:
74 clrsetbits_be32(&machine_data->guts->pmuxcr, 84 clrsetbits_be32(&guts->pmuxcr,
75 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI); 85 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_SSI);
76 break; 86 break;
77 case 1: 87 case 1:
78 clrsetbits_be32(&machine_data->guts->pmuxcr, 88 clrsetbits_be32(&guts->pmuxcr,
79 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI); 89 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_SSI);
80 break; 90 break;
81 } 91 }
82 92
93 iounmap(guts);
94
83 return 0; 95 return 0;
84} 96}
85 97
@@ -93,38 +105,15 @@ static int mpc8610_hpcd_machine_probe(struct platform_device *sound_device)
93static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream) 105static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
94{ 106{
95 struct snd_soc_pcm_runtime *rtd = substream->private_data; 107 struct snd_soc_pcm_runtime *rtd = substream->private_data;
96 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
97 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
98 struct mpc8610_hpcd_data *machine_data = 108 struct mpc8610_hpcd_data *machine_data =
99 rtd->socdev->dev->platform_data; 109 container_of(rtd->card, struct mpc8610_hpcd_data, card);
110 struct device *dev = rtd->card->dev;
100 int ret = 0; 111 int ret = 0;
101 112
102 /* Tell the CPU driver what the serial protocol is. */
103 ret = snd_soc_dai_set_fmt(cpu_dai, machine_data->dai_format);
104 if (ret < 0) {
105 dev_err(substream->pcm->card->dev,
106 "could not set CPU driver audio format\n");
107 return ret;
108 }
109
110 /* Tell the codec driver what the serial protocol is. */ 113 /* Tell the codec driver what the serial protocol is. */
111 ret = snd_soc_dai_set_fmt(codec_dai, machine_data->dai_format); 114 ret = snd_soc_dai_set_fmt(rtd->codec_dai, machine_data->dai_format);
112 if (ret < 0) { 115 if (ret < 0) {
113 dev_err(substream->pcm->card->dev, 116 dev_err(dev, "could not set codec driver audio format\n");
114 "could not set codec driver audio format\n");
115 return ret;
116 }
117
118 /*
119 * Tell the CPU driver what the clock frequency is, and whether it's a
120 * slave or master.
121 */
122 ret = snd_soc_dai_set_sysclk(cpu_dai, 0,
123 machine_data->clk_frequency,
124 machine_data->cpu_clk_direction);
125 if (ret < 0) {
126 dev_err(substream->pcm->card->dev,
127 "could not set CPU driver clock parameters\n");
128 return ret; 117 return ret;
129 } 118 }
130 119
@@ -132,12 +121,11 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
132 * Tell the codec driver what the MCLK frequency is, and whether it's 121 * Tell the codec driver what the MCLK frequency is, and whether it's
133 * a slave or master. 122 * a slave or master.
134 */ 123 */
135 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 124 ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0,
136 machine_data->clk_frequency, 125 machine_data->clk_frequency,
137 machine_data->codec_clk_direction); 126 machine_data->codec_clk_direction);
138 if (ret < 0) { 127 if (ret < 0) {
139 dev_err(substream->pcm->card->dev, 128 dev_err(dev, "could not set codec driver clock params\n");
140 "could not set codec driver clock params\n");
141 return ret; 129 return ret;
142 } 130 }
143 131
@@ -150,116 +138,255 @@ static int mpc8610_hpcd_startup(struct snd_pcm_substream *substream)
150 * This function is called to remove the sound device for one SSI. We 138 * This function is called to remove the sound device for one SSI. We
151 * de-program the DMACR and PMUXCR register. 139 * de-program the DMACR and PMUXCR register.
152 */ 140 */
153int mpc8610_hpcd_machine_remove(struct platform_device *sound_device) 141static int mpc8610_hpcd_machine_remove(struct platform_device *sound_device)
154{ 142{
143 struct snd_soc_card *card = platform_get_drvdata(sound_device);
155 struct mpc8610_hpcd_data *machine_data = 144 struct mpc8610_hpcd_data *machine_data =
156 sound_device->dev.platform_data; 145 container_of(card, struct mpc8610_hpcd_data, card);
146 struct ccsr_guts_86xx __iomem *guts;
147
148 guts = ioremap(guts_phys, sizeof(struct ccsr_guts_86xx));
149 if (!guts) {
150 dev_err(card->dev, "could not map global utilities\n");
151 return -ENOMEM;
152 }
157 153
158 /* Restore the signal routing */ 154 /* Restore the signal routing */
159 155
160 guts_set_dmacr(machine_data->guts, machine_data->dma_id, 156 guts_set_dmacr(guts, machine_data->dma_id[0],
161 machine_data->dma_channel_id[0], 0); 157 machine_data->dma_channel_id[0], 0);
162 guts_set_dmacr(machine_data->guts, machine_data->dma_id, 158 guts_set_dmacr(guts, machine_data->dma_id[1],
163 machine_data->dma_channel_id[1], 0); 159 machine_data->dma_channel_id[1], 0);
164 160
165 switch (machine_data->ssi_id) { 161 switch (machine_data->ssi_id) {
166 case 0: 162 case 0:
167 clrsetbits_be32(&machine_data->guts->pmuxcr, 163 clrsetbits_be32(&guts->pmuxcr,
168 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA); 164 CCSR_GUTS_PMUXCR_SSI1_MASK, CCSR_GUTS_PMUXCR_SSI1_LA);
169 break; 165 break;
170 case 1: 166 case 1:
171 clrsetbits_be32(&machine_data->guts->pmuxcr, 167 clrsetbits_be32(&guts->pmuxcr,
172 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA); 168 CCSR_GUTS_PMUXCR_SSI2_MASK, CCSR_GUTS_PMUXCR_SSI2_LA);
173 break; 169 break;
174 } 170 }
175 171
172 iounmap(guts);
173
176 return 0; 174 return 0;
177} 175}
178 176
179/** 177/**
180 * mpc8610_hpcd_ops: ASoC fabric driver operations 178 * mpc8610_hpcd_ops: ASoC machine driver operations
181 */ 179 */
182static struct snd_soc_ops mpc8610_hpcd_ops = { 180static struct snd_soc_ops mpc8610_hpcd_ops = {
183 .startup = mpc8610_hpcd_startup, 181 .startup = mpc8610_hpcd_startup,
184}; 182};
185 183
186/** 184/**
187 * mpc8610_hpcd_probe: OF probe function for the fabric driver 185 * get_node_by_phandle_name - get a node by its phandle name
188 * 186 *
189 * This function gets called when an SSI node is found in the device tree. 187 * This function takes a node, the name of a property in that node, and a
188 * compatible string. Assuming the property is a phandle to another node,
189 * it returns that node, (optionally) if that node is compatible.
190 * 190 *
191 * Although this is a fabric driver, the SSI node is the "master" node with 191 * If the property is not a phandle, or the node it points to is not compatible
192 * respect to audio hardware connections. Therefore, we create a new ASoC 192 * with the specific string, then NULL is returned.
193 * device for each new SSI node that has a codec attached. 193 */
194static struct device_node *get_node_by_phandle_name(struct device_node *np,
195 const char *name,
196 const char *compatible)
197{
198 const phandle *ph;
199 int len;
200
201 ph = of_get_property(np, name, &len);
202 if (!ph || (len != sizeof(phandle)))
203 return NULL;
204
205 np = of_find_node_by_phandle(*ph);
206 if (!np)
207 return NULL;
208
209 if (compatible && !of_device_is_compatible(np, compatible)) {
210 of_node_put(np);
211 return NULL;
212 }
213
214 return np;
215}
216
217/**
218 * get_parent_cell_index -- return the cell-index of the parent of a node
219 *
220 * Return the value of the cell-index property of the parent of the given
221 * node. This is used for DMA channel nodes that need to know the DMA ID
222 * of the controller they are on.
223 */
224static int get_parent_cell_index(struct device_node *np)
225{
226 struct device_node *parent = of_get_parent(np);
227 const u32 *iprop;
228
229 if (!parent)
230 return -1;
231
232 iprop = of_get_property(parent, "cell-index", NULL);
233 of_node_put(parent);
234
235 if (!iprop)
236 return -1;
237
238 return *iprop;
239}
240
241/**
242 * codec_node_dev_name - determine the dev_name for a codec node
194 * 243 *
195 * FIXME: Currently, we only support one DMA controller, so if there are 244 * This function determines the dev_name for an I2C node. This is the name
196 * multiple SSI nodes with codecs, only the first will be supported. 245 * that would be returned by dev_name() if this device_node were part of a
246 * 'struct device' It's ugly and hackish, but it works.
197 * 247 *
198 * FIXME: Even if we did support multiple DMA controllers, we have no 248 * The dev_name for such devices include the bus number and I2C address. For
199 * mechanism for assigning DMA controllers and channels to the individual 249 * example, "cs4270-codec.0-004f".
200 * SSI devices. We also probably aren't compatible with the generic Elo DMA
201 * device driver.
202 */ 250 */
203static int mpc8610_hpcd_probe(struct platform_device *ofdev, 251static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
204 const struct of_device_id *match)
205{ 252{
206 struct device_node *np = ofdev->dev.of_node;
207 struct device_node *codec_np = NULL;
208 struct device_node *guts_np = NULL;
209 struct device_node *dma_np = NULL;
210 struct device_node *dma_channel_np = NULL;
211 const phandle *codec_ph;
212 const char *sprop;
213 const u32 *iprop; 253 const u32 *iprop;
254 int bus, addr;
255 char temp[DAI_NAME_SIZE];
256
257 of_modalias_node(np, temp, DAI_NAME_SIZE);
258
259 iprop = of_get_property(np, "reg", NULL);
260 if (!iprop)
261 return -EINVAL;
262
263 addr = *iprop;
264
265 bus = get_parent_cell_index(np);
266 if (bus < 0)
267 return bus;
268
269 snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
270
271 return 0;
272}
273
274static int get_dma_channel(struct device_node *ssi_np,
275 const char *compatible,
276 struct snd_soc_dai_link *dai,
277 unsigned int *dma_channel_id,
278 unsigned int *dma_id)
279{
214 struct resource res; 280 struct resource res;
281 struct device_node *dma_channel_np;
282 const u32 *iprop;
283 int ret;
284
285 dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
286 "fsl,ssi-dma-channel");
287 if (!dma_channel_np)
288 return -EINVAL;
289
290 /* Determine the dev_name for the device_node. This code mimics the
291 * behavior of of_device_make_bus_id(). We need this because ASoC uses
292 * the dev_name() of the device to match the platform (DMA) device with
293 * the CPU (SSI) device. It's all ugly and hackish, but it works (for
294 * now).
295 *
296 * dai->platform name should already point to an allocated buffer.
297 */
298 ret = of_address_to_resource(dma_channel_np, 0, &res);
299 if (ret)
300 return ret;
301 snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
302 (unsigned long long) res.start, dma_channel_np->name);
303
304 iprop = of_get_property(dma_channel_np, "cell-index", NULL);
305 if (!iprop) {
306 of_node_put(dma_channel_np);
307 return -EINVAL;
308 }
309
310 *dma_channel_id = *iprop;
311 *dma_id = get_parent_cell_index(dma_channel_np);
312 of_node_put(dma_channel_np);
313
314 return 0;
315}
316
317/**
318 * mpc8610_hpcd_probe: platform probe function for the machine driver
319 *
320 * Although this is a machine driver, the SSI node is the "master" node with
321 * respect to audio hardware connections. Therefore, we create a new ASoC
322 * device for each new SSI node that has a codec attached.
323 */
324static int mpc8610_hpcd_probe(struct platform_device *pdev)
325{
326 struct device *dev = pdev->dev.parent;
327 /* ssi_pdev is the platform device for the SSI node that probed us */
328 struct platform_device *ssi_pdev =
329 container_of(dev, struct platform_device, dev);
330 struct device_node *np = ssi_pdev->dev.of_node;
331 struct device_node *codec_np = NULL;
215 struct platform_device *sound_device = NULL; 332 struct platform_device *sound_device = NULL;
216 struct mpc8610_hpcd_data *machine_data; 333 struct mpc8610_hpcd_data *machine_data;
217 struct fsl_ssi_info ssi_info;
218 struct fsl_dma_info dma_info;
219 int ret = -ENODEV; 334 int ret = -ENODEV;
220 unsigned int playback_dma_channel; 335 const char *sprop;
221 unsigned int capture_dma_channel; 336 const u32 *iprop;
337
338 /* We are only interested in SSIs with a codec phandle in them,
339 * so let's make sure this SSI has one. The MPC8610 HPCD only
340 * knows about the CS4270 codec, so reject anything else.
341 */
342 codec_np = get_node_by_phandle_name(np, "codec-handle",
343 "cirrus,cs4270");
344 if (!codec_np) {
345 dev_err(dev, "invalid codec node\n");
346 return -EINVAL;
347 }
222 348
223 machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL); 349 machine_data = kzalloc(sizeof(struct mpc8610_hpcd_data), GFP_KERNEL);
224 if (!machine_data) 350 if (!machine_data)
225 return -ENOMEM; 351 return -ENOMEM;
226 352
227 memset(&ssi_info, 0, sizeof(ssi_info)); 353 machine_data->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
228 memset(&dma_info, 0, sizeof(dma_info)); 354 machine_data->dai[0].ops = &mpc8610_hpcd_ops;
229 355
230 ssi_info.dev = &ofdev->dev; 356 /* Determine the codec name, it will be used as the codec DAI name */
231 357 ret = codec_node_dev_name(codec_np, machine_data->codec_name,
232 /* 358 DAI_NAME_SIZE);
233 * We are only interested in SSIs with a codec phandle in them, so let's 359 if (ret) {
234 * make sure this SSI has one. 360 dev_err(&pdev->dev, "invalid codec node %s\n",
235 */ 361 codec_np->full_name);
236 codec_ph = of_get_property(np, "codec-handle", NULL); 362 ret = -EINVAL;
237 if (!codec_ph)
238 goto error; 363 goto error;
364 }
365 machine_data->dai[0].codec_name = machine_data->codec_name;
239 366
240 codec_np = of_find_node_by_phandle(*codec_ph); 367 /* The DAI name from the codec (snd_soc_dai_driver.name) */
241 if (!codec_np) 368 machine_data->dai[0].codec_dai_name = "cs4270-hifi";
242 goto error;
243 369
244 /* The MPC8610 HPCD only knows about the CS4270 codec, so reject 370 /* We register two DAIs per SSI, one for playback and the other for
245 anything else. */ 371 * capture. Currently, we only support codecs that have one DAI for
246 if (!of_device_is_compatible(codec_np, "cirrus,cs4270")) 372 * both playback and capture.
247 goto error; 373 */
374 memcpy(&machine_data->dai[1], &machine_data->dai[0],
375 sizeof(struct snd_soc_dai_link));
248 376
249 /* Get the device ID */ 377 /* Get the device ID */
250 iprop = of_get_property(np, "cell-index", NULL); 378 iprop = of_get_property(np, "cell-index", NULL);
251 if (!iprop) { 379 if (!iprop) {
252 dev_err(&ofdev->dev, "cell-index property not found\n"); 380 dev_err(&pdev->dev, "cell-index property not found\n");
253 ret = -EINVAL; 381 ret = -EINVAL;
254 goto error; 382 goto error;
255 } 383 }
256 machine_data->ssi_id = *iprop; 384 machine_data->ssi_id = *iprop;
257 ssi_info.id = *iprop;
258 385
259 /* Get the serial format and clock direction. */ 386 /* Get the serial format and clock direction. */
260 sprop = of_get_property(np, "fsl,mode", NULL); 387 sprop = of_get_property(np, "fsl,mode", NULL);
261 if (!sprop) { 388 if (!sprop) {
262 dev_err(&ofdev->dev, "fsl,mode property not found\n"); 389 dev_err(&pdev->dev, "fsl,mode property not found\n");
263 ret = -EINVAL; 390 ret = -EINVAL;
264 goto error; 391 goto error;
265 } 392 }
@@ -269,15 +396,14 @@ static int mpc8610_hpcd_probe(struct platform_device *ofdev,
269 machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT; 396 machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
270 machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN; 397 machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
271 398
272 /* 399 /* In i2s-slave mode, the codec has its own clock source, so we
273 * In i2s-slave mode, the codec has its own clock source, so we
274 * need to get the frequency from the device tree and pass it to 400 * need to get the frequency from the device tree and pass it to
275 * the codec driver. 401 * the codec driver.
276 */ 402 */
277 iprop = of_get_property(codec_np, "clock-frequency", NULL); 403 iprop = of_get_property(codec_np, "clock-frequency", NULL);
278 if (!iprop || !*iprop) { 404 if (!iprop || !*iprop) {
279 dev_err(&ofdev->dev, "codec bus-frequency property " 405 dev_err(&pdev->dev, "codec bus-frequency "
280 "is missing or invalid\n"); 406 "property is missing or invalid\n");
281 ret = -EINVAL; 407 ret = -EINVAL;
282 goto error; 408 goto error;
283 } 409 }
@@ -311,317 +437,153 @@ static int mpc8610_hpcd_probe(struct platform_device *ofdev,
311 machine_data->codec_clk_direction = SND_SOC_CLOCK_IN; 437 machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
312 machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT; 438 machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
313 } else { 439 } else {
314 dev_err(&ofdev->dev, 440 dev_err(&pdev->dev,
315 "unrecognized fsl,mode property \"%s\"\n", sprop); 441 "unrecognized fsl,mode property '%s'\n", sprop);
316 ret = -EINVAL; 442 ret = -EINVAL;
317 goto error; 443 goto error;
318 } 444 }
319 445
320 if (!machine_data->clk_frequency) { 446 if (!machine_data->clk_frequency) {
321 dev_err(&ofdev->dev, "unknown clock frequency\n"); 447 dev_err(&pdev->dev, "unknown clock frequency\n");
322 ret = -EINVAL; 448 ret = -EINVAL;
323 goto error; 449 goto error;
324 } 450 }
325 451
326 /* Read the SSI information from the device tree */ 452 /* Find the playback DMA channel to use. */
327 ret = of_address_to_resource(np, 0, &res); 453 machine_data->dai[0].platform_name = machine_data->platform_name[0];
454 ret = get_dma_channel(np, "fsl,playback-dma", &machine_data->dai[0],
455 &machine_data->dma_channel_id[0],
456 &machine_data->dma_id[0]);
328 if (ret) { 457 if (ret) {
329 dev_err(&ofdev->dev, "could not obtain SSI address\n"); 458 dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");
330 goto error;
331 }
332 if (!res.start) {
333 dev_err(&ofdev->dev, "invalid SSI address\n");
334 goto error;
335 }
336 ssi_info.ssi_phys = res.start;
337
338 machine_data->ssi = ioremap(ssi_info.ssi_phys, sizeof(struct ccsr_ssi));
339 if (!machine_data->ssi) {
340 dev_err(&ofdev->dev, "could not map SSI address %x\n",
341 ssi_info.ssi_phys);
342 ret = -EINVAL;
343 goto error;
344 }
345 ssi_info.ssi = machine_data->ssi;
346
347
348 /* Get the IRQ of the SSI */
349 machine_data->ssi_irq = irq_of_parse_and_map(np, 0);
350 if (!machine_data->ssi_irq) {
351 dev_err(&ofdev->dev, "could not get SSI IRQ\n");
352 ret = -EINVAL;
353 goto error;
354 }
355 ssi_info.irq = machine_data->ssi_irq;
356
357 /* Do we want to use asynchronous mode? */
358 ssi_info.asynchronous =
359 of_find_property(np, "fsl,ssi-asynchronous", NULL) ? 1 : 0;
360 if (ssi_info.asynchronous)
361 dev_info(&ofdev->dev, "using asynchronous mode\n");
362
363 /* Map the global utilities registers. */
364 guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
365 if (!guts_np) {
366 dev_err(&ofdev->dev, "could not obtain address of GUTS\n");
367 ret = -EINVAL;
368 goto error;
369 }
370 machine_data->guts = of_iomap(guts_np, 0);
371 of_node_put(guts_np);
372 if (!machine_data->guts) {
373 dev_err(&ofdev->dev, "could not map GUTS\n");
374 ret = -EINVAL;
375 goto error;
376 }
377
378 /* Find the DMA channels to use. Both SSIs need to use the same DMA
379 * controller, so let's use DMA#1.
380 */
381 for_each_compatible_node(dma_np, NULL, "fsl,mpc8610-dma") {
382 iprop = of_get_property(dma_np, "cell-index", NULL);
383 if (iprop && (*iprop == 0)) {
384 of_node_put(dma_np);
385 break;
386 }
387 }
388 if (!dma_np) {
389 dev_err(&ofdev->dev, "could not find DMA node\n");
390 ret = -EINVAL;
391 goto error;
392 }
393 machine_data->dma_id = *iprop;
394
395 /* SSI1 needs to use DMA Channels 0 and 1, and SSI2 needs to use DMA
396 * channels 2 and 3. This is just how the MPC8610 is wired
397 * internally.
398 */
399 playback_dma_channel = (machine_data->ssi_id == 0) ? 0 : 2;
400 capture_dma_channel = (machine_data->ssi_id == 0) ? 1 : 3;
401
402 /*
403 * Find the DMA channels to use.
404 */
405 while ((dma_channel_np = of_get_next_child(dma_np, dma_channel_np))) {
406 iprop = of_get_property(dma_channel_np, "cell-index", NULL);
407 if (iprop && (*iprop == playback_dma_channel)) {
408 /* dma_channel[0] and dma_irq[0] are for playback */
409 dma_info.dma_channel[0] = of_iomap(dma_channel_np, 0);
410 dma_info.dma_irq[0] =
411 irq_of_parse_and_map(dma_channel_np, 0);
412 machine_data->dma_channel_id[0] = *iprop;
413 continue;
414 }
415 if (iprop && (*iprop == capture_dma_channel)) {
416 /* dma_channel[1] and dma_irq[1] are for capture */
417 dma_info.dma_channel[1] = of_iomap(dma_channel_np, 0);
418 dma_info.dma_irq[1] =
419 irq_of_parse_and_map(dma_channel_np, 0);
420 machine_data->dma_channel_id[1] = *iprop;
421 continue;
422 }
423 }
424 if (!dma_info.dma_channel[0] || !dma_info.dma_channel[1] ||
425 !dma_info.dma_irq[0] || !dma_info.dma_irq[1]) {
426 dev_err(&ofdev->dev, "could not find DMA channels\n");
427 ret = -EINVAL;
428 goto error; 459 goto error;
429 } 460 }
430 461
431 dma_info.ssi_stx_phys = ssi_info.ssi_phys + 462 /* Find the capture DMA channel to use. */
432 offsetof(struct ccsr_ssi, stx0); 463 machine_data->dai[1].platform_name = machine_data->platform_name[1];
433 dma_info.ssi_srx_phys = ssi_info.ssi_phys + 464 ret = get_dma_channel(np, "fsl,capture-dma", &machine_data->dai[1],
434 offsetof(struct ccsr_ssi, srx0); 465 &machine_data->dma_channel_id[1],
435 466 &machine_data->dma_id[1]);
436 /* We have the DMA information, so tell the DMA driver what it is */ 467 if (ret) {
437 if (!fsl_dma_configure(&dma_info)) { 468 dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");
438 dev_err(&ofdev->dev, "could not instantiate DMA device\n");
439 ret = -EBUSY;
440 goto error; 469 goto error;
441 } 470 }
442 471
443 /* 472 /* Initialize our DAI data structure. */
444 * Initialize our DAI data structure. We should probably get this 473 machine_data->dai[0].stream_name = "playback";
445 * information from the device tree. 474 machine_data->dai[1].stream_name = "capture";
446 */ 475 machine_data->dai[0].name = machine_data->dai[0].stream_name;
447 machine_data->dai.name = "CS4270"; 476 machine_data->dai[1].name = machine_data->dai[1].stream_name;
448 machine_data->dai.stream_name = "CS4270";
449
450 machine_data->dai.cpu_dai = fsl_ssi_create_dai(&ssi_info);
451 machine_data->dai.codec_dai = &cs4270_dai; /* The codec_dai we want */
452 machine_data->dai.ops = &mpc8610_hpcd_ops;
453 477
454 machine_data->machine.probe = mpc8610_hpcd_machine_probe; 478 machine_data->card.probe = mpc8610_hpcd_machine_probe;
455 machine_data->machine.remove = mpc8610_hpcd_machine_remove; 479 machine_data->card.remove = mpc8610_hpcd_machine_remove;
456 machine_data->machine.name = "MPC8610 HPCD"; 480 machine_data->card.name = pdev->name; /* The platform driver name */
457 machine_data->machine.num_links = 1; 481 machine_data->card.num_links = 2;
458 machine_data->machine.dai_link = &machine_data->dai; 482 machine_data->card.dai_link = machine_data->dai;
459 483
460 /* Allocate a new audio platform device structure */ 484 /* Allocate a new audio platform device structure */
461 sound_device = platform_device_alloc("soc-audio", -1); 485 sound_device = platform_device_alloc("soc-audio", -1);
462 if (!sound_device) { 486 if (!sound_device) {
463 dev_err(&ofdev->dev, "platform device allocation failed\n"); 487 dev_err(&pdev->dev, "platform device alloc failed\n");
464 ret = -ENOMEM; 488 ret = -ENOMEM;
465 goto error; 489 goto error;
466 } 490 }
467 491
468 machine_data->sound_devdata.card = &machine_data->machine; 492 /* Associate the card data with the sound device */
469 machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270; 493 platform_set_drvdata(sound_device, &machine_data->card);
470 machine_data->machine.platform = &fsl_soc_platform;
471
472 sound_device->dev.platform_data = machine_data;
473
474 494
475 /* Set the platform device and ASoC device to point to each other */ 495 /* Register with ASoC */
476 platform_set_drvdata(sound_device, &machine_data->sound_devdata);
477
478 machine_data->sound_devdata.dev = &sound_device->dev;
479
480
481 /* Tell ASoC to probe us. This will call mpc8610_hpcd_machine.probe(),
482 if it exists. */
483 ret = platform_device_add(sound_device); 496 ret = platform_device_add(sound_device);
484
485 if (ret) { 497 if (ret) {
486 dev_err(&ofdev->dev, "platform device add failed\n"); 498 dev_err(&pdev->dev, "platform device add failed\n");
487 goto error; 499 goto error;
488 } 500 }
489 501
490 dev_set_drvdata(&ofdev->dev, sound_device); 502 of_node_put(codec_np);
491 503
492 return 0; 504 return 0;
493 505
494error: 506error:
495 of_node_put(codec_np); 507 of_node_put(codec_np);
496 of_node_put(guts_np);
497 of_node_put(dma_np);
498 of_node_put(dma_channel_np);
499 508
500 if (sound_device) 509 if (sound_device)
501 platform_device_unregister(sound_device); 510 platform_device_unregister(sound_device);
502 511
503 if (machine_data->dai.cpu_dai)
504 fsl_ssi_destroy_dai(machine_data->dai.cpu_dai);
505
506 if (ssi_info.ssi)
507 iounmap(ssi_info.ssi);
508
509 if (ssi_info.irq)
510 irq_dispose_mapping(ssi_info.irq);
511
512 if (dma_info.dma_channel[0])
513 iounmap(dma_info.dma_channel[0]);
514
515 if (dma_info.dma_channel[1])
516 iounmap(dma_info.dma_channel[1]);
517
518 if (dma_info.dma_irq[0])
519 irq_dispose_mapping(dma_info.dma_irq[0]);
520
521 if (dma_info.dma_irq[1])
522 irq_dispose_mapping(dma_info.dma_irq[1]);
523
524 if (machine_data->guts)
525 iounmap(machine_data->guts);
526
527 kfree(machine_data); 512 kfree(machine_data);
528 513
529 return ret; 514 return ret;
530} 515}
531 516
532/** 517/**
533 * mpc8610_hpcd_remove: remove the OF device 518 * mpc8610_hpcd_remove: remove the platform device
534 * 519 *
535 * This function is called when the OF device is removed. 520 * This function is called when the platform device is removed.
536 */ 521 */
537static int mpc8610_hpcd_remove(struct platform_device *ofdev) 522static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev)
538{ 523{
539 struct platform_device *sound_device = dev_get_drvdata(&ofdev->dev); 524 struct platform_device *sound_device = dev_get_drvdata(&pdev->dev);
525 struct snd_soc_card *card = platform_get_drvdata(sound_device);
540 struct mpc8610_hpcd_data *machine_data = 526 struct mpc8610_hpcd_data *machine_data =
541 sound_device->dev.platform_data; 527 container_of(card, struct mpc8610_hpcd_data, card);
542 528
543 platform_device_unregister(sound_device); 529 platform_device_unregister(sound_device);
544 530
545 if (machine_data->dai.cpu_dai)
546 fsl_ssi_destroy_dai(machine_data->dai.cpu_dai);
547
548 if (machine_data->ssi)
549 iounmap(machine_data->ssi);
550
551 if (machine_data->dma[0])
552 iounmap(machine_data->dma[0]);
553
554 if (machine_data->dma[1])
555 iounmap(machine_data->dma[1]);
556
557 if (machine_data->dma_irq[0])
558 irq_dispose_mapping(machine_data->dma_irq[0]);
559
560 if (machine_data->dma_irq[1])
561 irq_dispose_mapping(machine_data->dma_irq[1]);
562
563 if (machine_data->guts)
564 iounmap(machine_data->guts);
565
566 kfree(machine_data); 531 kfree(machine_data);
567 sound_device->dev.platform_data = NULL; 532 sound_device->dev.platform_data = NULL;
568 533
569 dev_set_drvdata(&ofdev->dev, NULL); 534 dev_set_drvdata(&pdev->dev, NULL);
570 535
571 return 0; 536 return 0;
572} 537}
573 538
574static struct of_device_id mpc8610_hpcd_match[] = { 539static struct platform_driver mpc8610_hpcd_driver = {
575 { 540 .probe = mpc8610_hpcd_probe,
576 .compatible = "fsl,mpc8610-ssi", 541 .remove = __devexit_p(mpc8610_hpcd_remove),
577 },
578 {}
579};
580MODULE_DEVICE_TABLE(of, mpc8610_hpcd_match);
581
582static struct of_platform_driver mpc8610_hpcd_of_driver = {
583 .driver = { 542 .driver = {
584 .name = "mpc8610_hpcd", 543 /* The name must match the 'model' property in the device tree,
544 * in lowercase letters.
545 */
546 .name = "snd-soc-mpc8610hpcd",
585 .owner = THIS_MODULE, 547 .owner = THIS_MODULE,
586 .of_match_table = mpc8610_hpcd_match,
587 }, 548 },
588 .probe = mpc8610_hpcd_probe,
589 .remove = mpc8610_hpcd_remove,
590}; 549};
591 550
592/** 551/**
593 * mpc8610_hpcd_init: fabric driver initialization. 552 * mpc8610_hpcd_init: machine driver initialization.
594 * 553 *
595 * This function is called when this module is loaded. 554 * This function is called when this module is loaded.
596 */ 555 */
597static int __init mpc8610_hpcd_init(void) 556static int __init mpc8610_hpcd_init(void)
598{ 557{
599 int ret; 558 struct device_node *guts_np;
600 559 struct resource res;
601 printk(KERN_INFO "Freescale MPC8610 HPCD ALSA SoC fabric driver\n");
602 560
603 ret = of_register_platform_driver(&mpc8610_hpcd_of_driver); 561 pr_info("Freescale MPC8610 HPCD ALSA SoC machine driver\n");
604 562
605 if (ret) 563 /* Get the physical address of the global utilities registers */
606 printk(KERN_ERR 564 guts_np = of_find_compatible_node(NULL, NULL, "fsl,mpc8610-guts");
607 "mpc8610-hpcd: failed to register platform driver\n"); 565 if (of_address_to_resource(guts_np, 0, &res)) {
566 pr_err("mpc8610-hpcd: missing/invalid global utilities node\n");
567 return -EINVAL;
568 }
569 guts_phys = res.start;
608 570
609 return ret; 571 return platform_driver_register(&mpc8610_hpcd_driver);
610} 572}
611 573
612/** 574/**
613 * mpc8610_hpcd_exit: fabric driver exit 575 * mpc8610_hpcd_exit: machine driver exit
614 * 576 *
615 * This function is called when this driver is unloaded. 577 * This function is called when this driver is unloaded.
616 */ 578 */
617static void __exit mpc8610_hpcd_exit(void) 579static void __exit mpc8610_hpcd_exit(void)
618{ 580{
619 of_unregister_platform_driver(&mpc8610_hpcd_of_driver); 581 platform_driver_unregister(&mpc8610_hpcd_driver);
620} 582}
621 583
622module_init(mpc8610_hpcd_init); 584module_init(mpc8610_hpcd_init);
623module_exit(mpc8610_hpcd_exit); 585module_exit(mpc8610_hpcd_exit);
624 586
625MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 587MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
626MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC fabric driver"); 588MODULE_DESCRIPTION("Freescale MPC8610 HPCD ALSA SoC machine driver");
627MODULE_LICENSE("GPL"); 589MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
new file mode 100644
index 000000000000..63b9eaa1ebc2
--- /dev/null
+++ b/sound/soc/fsl/p1022_ds.c
@@ -0,0 +1,591 @@
1/**
2 * Freescale P1022DS ALSA SoC Machine driver
3 *
4 * Author: Timur Tabi <timur@freescale.com>
5 *
6 * Copyright 2010 Freescale Semiconductor, Inc.
7 *
8 * This file is licensed under the terms of the GNU General Public License
9 * version 2. This program is licensed "as is" without any warranty of any
10 * kind, whether express or implied.
11 */
12
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/of_device.h>
16#include <linux/slab.h>
17#include <sound/soc.h>
18#include <asm/fsl_guts.h>
19
20#include "fsl_dma.h"
21#include "fsl_ssi.h"
22
23/* P1022-specific PMUXCR and DMUXCR bit definitions */
24
25#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK 0x0001c000
26#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI 0x00010000
27#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI 0x00018000
28
29#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK 0x00000c00
30#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI 0x00000000
31
32#define CCSR_GUTS_DMUXCR_PAD 1 /* DMA controller/channel set to pad */
33#define CCSR_GUTS_DMUXCR_SSI 2 /* DMA controller/channel set to SSI */
34
35/*
36 * Set the DMACR register in the GUTS
37 *
38 * The DMACR register determines the source of initiated transfers for each
39 * channel on each DMA controller. Rather than have a bunch of repetitive
40 * macros for the bit patterns, we just have a function that calculates
41 * them.
42 *
43 * guts: Pointer to GUTS structure
44 * co: The DMA controller (0 or 1)
45 * ch: The channel on the DMA controller (0, 1, 2, or 3)
46 * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
47 */
48static inline void guts_set_dmuxcr(struct ccsr_guts_85xx __iomem *guts,
49 unsigned int co, unsigned int ch, unsigned int device)
50{
51 unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
52
53 clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift);
54}
55
56/* There's only one global utilities register */
57static phys_addr_t guts_phys;
58
59#define DAI_NAME_SIZE 32
60
61/**
62 * machine_data: machine-specific ASoC device data
63 *
64 * This structure contains data for a single sound platform device on an
65 * P1022 DS. Some of the data is taken from the device tree.
66 */
67struct machine_data {
68 struct snd_soc_dai_link dai[2];
69 struct snd_soc_card card;
70 unsigned int dai_format;
71 unsigned int codec_clk_direction;
72 unsigned int cpu_clk_direction;
73 unsigned int clk_frequency;
74 unsigned int ssi_id; /* 0 = SSI1, 1 = SSI2, etc */
75 unsigned int dma_id[2]; /* 0 = DMA1, 1 = DMA2, etc */
76 unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
77 char codec_name[DAI_NAME_SIZE];
78 char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
79};
80
81/**
82 * p1022_ds_machine_probe: initialize the board
83 *
84 * This function is used to initialize the board-specific hardware.
85 *
86 * Here we program the DMACR and PMUXCR registers.
87 */
88static int p1022_ds_machine_probe(struct platform_device *sound_device)
89{
90 struct snd_soc_card *card = platform_get_drvdata(sound_device);
91 struct machine_data *mdata =
92 container_of(card, struct machine_data, card);
93 struct ccsr_guts_85xx __iomem *guts;
94
95 guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
96 if (!guts) {
97 dev_err(card->dev, "could not map global utilities\n");
98 return -ENOMEM;
99 }
100
101 /* Enable SSI Tx signal */
102 clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK,
103 CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI);
104
105 /* Enable SSI Rx signal */
106 clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK,
107 CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI);
108
109 /* Enable DMA Channel for SSI */
110 guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0],
111 CCSR_GUTS_DMUXCR_SSI);
112
113 guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1],
114 CCSR_GUTS_DMUXCR_SSI);
115
116 iounmap(guts);
117
118 return 0;
119}
120
121/**
122 * p1022_ds_startup: program the board with various hardware parameters
123 *
124 * This function takes board-specific information, like clock frequencies
125 * and serial data formats, and passes that information to the codec and
126 * transport drivers.
127 */
128static int p1022_ds_startup(struct snd_pcm_substream *substream)
129{
130 struct snd_soc_pcm_runtime *rtd = substream->private_data;
131 struct machine_data *mdata =
132 container_of(rtd->card, struct machine_data, card);
133 struct device *dev = rtd->card->dev;
134 int ret = 0;
135
136 /* Tell the codec driver what the serial protocol is. */
137 ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format);
138 if (ret < 0) {
139 dev_err(dev, "could not set codec driver audio format\n");
140 return ret;
141 }
142
143 /*
144 * Tell the codec driver what the MCLK frequency is, and whether it's
145 * a slave or master.
146 */
147 ret = snd_soc_dai_set_sysclk(rtd->codec_dai, 0, mdata->clk_frequency,
148 mdata->codec_clk_direction);
149 if (ret < 0) {
150 dev_err(dev, "could not set codec driver clock params\n");
151 return ret;
152 }
153
154 return 0;
155}
156
157/**
158 * p1022_ds_machine_remove: Remove the sound device
159 *
160 * This function is called to remove the sound device for one SSI. We
161 * de-program the DMACR and PMUXCR register.
162 */
163static int p1022_ds_machine_remove(struct platform_device *sound_device)
164{
165 struct snd_soc_card *card = platform_get_drvdata(sound_device);
166 struct machine_data *mdata =
167 container_of(card, struct machine_data, card);
168 struct ccsr_guts_85xx __iomem *guts;
169
170 guts = ioremap(guts_phys, sizeof(struct ccsr_guts_85xx));
171 if (!guts) {
172 dev_err(card->dev, "could not map global utilities\n");
173 return -ENOMEM;
174 }
175
176 /* Restore the signal routing */
177 clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK);
178 clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK);
179 guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0);
180 guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0);
181
182 iounmap(guts);
183
184 return 0;
185}
186
187/**
188 * p1022_ds_ops: ASoC machine driver operations
189 */
190static struct snd_soc_ops p1022_ds_ops = {
191 .startup = p1022_ds_startup,
192};
193
194/**
195 * get_node_by_phandle_name - get a node by its phandle name
196 *
197 * This function takes a node, the name of a property in that node, and a
198 * compatible string. Assuming the property is a phandle to another node,
199 * it returns that node, (optionally) if that node is compatible.
200 *
201 * If the property is not a phandle, or the node it points to is not compatible
202 * with the specific string, then NULL is returned.
203 */
204static struct device_node *get_node_by_phandle_name(struct device_node *np,
205 const char *name, const char *compatible)
206{
207 np = of_parse_phandle(np, name, 0);
208 if (!np)
209 return NULL;
210
211 if (!of_device_is_compatible(np, compatible)) {
212 of_node_put(np);
213 return NULL;
214 }
215
216 return np;
217}
218
219/**
220 * get_parent_cell_index -- return the cell-index of the parent of a node
221 *
222 * Return the value of the cell-index property of the parent of the given
223 * node. This is used for DMA channel nodes that need to know the DMA ID
224 * of the controller they are on.
225 */
226static int get_parent_cell_index(struct device_node *np)
227{
228 struct device_node *parent = of_get_parent(np);
229 const u32 *iprop;
230 int ret = -1;
231
232 if (!parent)
233 return -1;
234
235 iprop = of_get_property(parent, "cell-index", NULL);
236 if (iprop)
237 ret = *iprop;
238
239 of_node_put(parent);
240
241 return ret;
242}
243
244/**
245 * codec_node_dev_name - determine the dev_name for a codec node
246 *
247 * This function determines the dev_name for an I2C node. This is the name
248 * that would be returned by dev_name() if this device_node were part of a
249 * 'struct device' It's ugly and hackish, but it works.
250 *
251 * The dev_name for such devices include the bus number and I2C address. For
252 * example, "cs4270-codec.0-004f".
253 */
254static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
255{
256 const u32 *iprop;
257 int bus, addr;
258 char temp[DAI_NAME_SIZE];
259
260 of_modalias_node(np, temp, DAI_NAME_SIZE);
261
262 iprop = of_get_property(np, "reg", NULL);
263 if (!iprop)
264 return -EINVAL;
265
266 addr = *iprop;
267
268 bus = get_parent_cell_index(np);
269 if (bus < 0)
270 return bus;
271
272 snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
273
274 return 0;
275}
276
277static int get_dma_channel(struct device_node *ssi_np,
278 const char *compatible,
279 struct snd_soc_dai_link *dai,
280 unsigned int *dma_channel_id,
281 unsigned int *dma_id)
282{
283 struct resource res;
284 struct device_node *dma_channel_np;
285 const u32 *iprop;
286 int ret;
287
288 dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
289 "fsl,ssi-dma-channel");
290 if (!dma_channel_np)
291 return -EINVAL;
292
293 /* Determine the dev_name for the device_node. This code mimics the
294 * behavior of of_device_make_bus_id(). We need this because ASoC uses
295 * the dev_name() of the device to match the platform (DMA) device with
296 * the CPU (SSI) device. It's all ugly and hackish, but it works (for
297 * now).
298 *
299 * dai->platform name should already point to an allocated buffer.
300 */
301 ret = of_address_to_resource(dma_channel_np, 0, &res);
302 if (ret)
303 return ret;
304 snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%s",
305 (unsigned long long) res.start, dma_channel_np->name);
306
307 iprop = of_get_property(dma_channel_np, "cell-index", NULL);
308 if (!iprop) {
309 of_node_put(dma_channel_np);
310 return -EINVAL;
311 }
312
313 *dma_channel_id = *iprop;
314 *dma_id = get_parent_cell_index(dma_channel_np);
315 of_node_put(dma_channel_np);
316
317 return 0;
318}
319
320/**
321 * p1022_ds_probe: platform probe function for the machine driver
322 *
323 * Although this is a machine driver, the SSI node is the "master" node with
324 * respect to audio hardware connections. Therefore, we create a new ASoC
325 * device for each new SSI node that has a codec attached.
326 */
327static int p1022_ds_probe(struct platform_device *pdev)
328{
329 struct device *dev = pdev->dev.parent;
330 /* ssi_pdev is the platform device for the SSI node that probed us */
331 struct platform_device *ssi_pdev =
332 container_of(dev, struct platform_device, dev);
333 struct device_node *np = ssi_pdev->dev.of_node;
334 struct device_node *codec_np = NULL;
335 struct platform_device *sound_device = NULL;
336 struct machine_data *mdata;
337 int ret = -ENODEV;
338 const char *sprop;
339 const u32 *iprop;
340
341 /* Find the codec node for this SSI. */
342 codec_np = of_parse_phandle(np, "codec-handle", 0);
343 if (!codec_np) {
344 dev_err(dev, "could not find codec node\n");
345 return -EINVAL;
346 }
347
348 mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL);
349 if (!mdata) {
350 ret = -ENOMEM;
351 goto error_put;
352 }
353
354 mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
355 mdata->dai[0].ops = &p1022_ds_ops;
356
357 /* Determine the codec name, it will be used as the codec DAI name */
358 ret = codec_node_dev_name(codec_np, mdata->codec_name, DAI_NAME_SIZE);
359 if (ret) {
360 dev_err(&pdev->dev, "invalid codec node %s\n",
361 codec_np->full_name);
362 ret = -EINVAL;
363 goto error;
364 }
365 mdata->dai[0].codec_name = mdata->codec_name;
366
367 /* We register two DAIs per SSI, one for playback and the other for
368 * capture. We support codecs that have separate DAIs for both playback
369 * and capture.
370 */
371 memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link));
372
373 /* The DAI names from the codec (snd_soc_dai_driver.name) */
374 mdata->dai[0].codec_dai_name = "wm8776-hifi-playback";
375 mdata->dai[1].codec_dai_name = "wm8776-hifi-capture";
376
377 /* Get the device ID */
378 iprop = of_get_property(np, "cell-index", NULL);
379 if (!iprop) {
380 dev_err(&pdev->dev, "cell-index property not found\n");
381 ret = -EINVAL;
382 goto error;
383 }
384 mdata->ssi_id = *iprop;
385
386 /* Get the serial format and clock direction. */
387 sprop = of_get_property(np, "fsl,mode", NULL);
388 if (!sprop) {
389 dev_err(&pdev->dev, "fsl,mode property not found\n");
390 ret = -EINVAL;
391 goto error;
392 }
393
394 if (strcasecmp(sprop, "i2s-slave") == 0) {
395 mdata->dai_format = SND_SOC_DAIFMT_I2S;
396 mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
397 mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
398
399 /* In i2s-slave mode, the codec has its own clock source, so we
400 * need to get the frequency from the device tree and pass it to
401 * the codec driver.
402 */
403 iprop = of_get_property(codec_np, "clock-frequency", NULL);
404 if (!iprop || !*iprop) {
405 dev_err(&pdev->dev, "codec bus-frequency "
406 "property is missing or invalid\n");
407 ret = -EINVAL;
408 goto error;
409 }
410 mdata->clk_frequency = *iprop;
411 } else if (strcasecmp(sprop, "i2s-master") == 0) {
412 mdata->dai_format = SND_SOC_DAIFMT_I2S;
413 mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
414 mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
415 } else if (strcasecmp(sprop, "lj-slave") == 0) {
416 mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
417 mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
418 mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
419 } else if (strcasecmp(sprop, "lj-master") == 0) {
420 mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
421 mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
422 mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
423 } else if (strcasecmp(sprop, "rj-slave") == 0) {
424 mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
425 mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
426 mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
427 } else if (strcasecmp(sprop, "rj-master") == 0) {
428 mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
429 mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
430 mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
431 } else if (strcasecmp(sprop, "ac97-slave") == 0) {
432 mdata->dai_format = SND_SOC_DAIFMT_AC97;
433 mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
434 mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
435 } else if (strcasecmp(sprop, "ac97-master") == 0) {
436 mdata->dai_format = SND_SOC_DAIFMT_AC97;
437 mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
438 mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
439 } else {
440 dev_err(&pdev->dev,
441 "unrecognized fsl,mode property '%s'\n", sprop);
442 ret = -EINVAL;
443 goto error;
444 }
445
446 if (!mdata->clk_frequency) {
447 dev_err(&pdev->dev, "unknown clock frequency\n");
448 ret = -EINVAL;
449 goto error;
450 }
451
452 /* Find the playback DMA channel to use. */
453 mdata->dai[0].platform_name = mdata->platform_name[0];
454 ret = get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
455 &mdata->dma_channel_id[0],
456 &mdata->dma_id[0]);
457 if (ret) {
458 dev_err(&pdev->dev, "missing/invalid playback DMA phandle\n");
459 goto error;
460 }
461
462 /* Find the capture DMA channel to use. */
463 mdata->dai[1].platform_name = mdata->platform_name[1];
464 ret = get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
465 &mdata->dma_channel_id[1],
466 &mdata->dma_id[1]);
467 if (ret) {
468 dev_err(&pdev->dev, "missing/invalid capture DMA phandle\n");
469 goto error;
470 }
471
472 /* Initialize our DAI data structure. */
473 mdata->dai[0].stream_name = "playback";
474 mdata->dai[1].stream_name = "capture";
475 mdata->dai[0].name = mdata->dai[0].stream_name;
476 mdata->dai[1].name = mdata->dai[1].stream_name;
477
478 mdata->card.probe = p1022_ds_machine_probe;
479 mdata->card.remove = p1022_ds_machine_remove;
480 mdata->card.name = pdev->name; /* The platform driver name */
481 mdata->card.num_links = 2;
482 mdata->card.dai_link = mdata->dai;
483
484 /* Allocate a new audio platform device structure */
485 sound_device = platform_device_alloc("soc-audio", -1);
486 if (!sound_device) {
487 dev_err(&pdev->dev, "platform device alloc failed\n");
488 ret = -ENOMEM;
489 goto error;
490 }
491
492 /* Associate the card data with the sound device */
493 platform_set_drvdata(sound_device, &mdata->card);
494
495 /* Register with ASoC */
496 ret = platform_device_add(sound_device);
497 if (ret) {
498 dev_err(&pdev->dev, "platform device add failed\n");
499 goto error;
500 }
501
502 of_node_put(codec_np);
503
504 return 0;
505
506error:
507 if (sound_device)
508 platform_device_unregister(sound_device);
509
510 kfree(mdata);
511error_put:
512 of_node_put(codec_np);
513 return ret;
514}
515
516/**
517 * p1022_ds_remove: remove the platform device
518 *
519 * This function is called when the platform device is removed.
520 */
521static int __devexit p1022_ds_remove(struct platform_device *pdev)
522{
523 struct platform_device *sound_device = dev_get_drvdata(&pdev->dev);
524 struct snd_soc_card *card = platform_get_drvdata(sound_device);
525 struct machine_data *mdata =
526 container_of(card, struct machine_data, card);
527
528 platform_device_unregister(sound_device);
529
530 kfree(mdata);
531 sound_device->dev.platform_data = NULL;
532
533 dev_set_drvdata(&pdev->dev, NULL);
534
535 return 0;
536}
537
538static struct platform_driver p1022_ds_driver = {
539 .probe = p1022_ds_probe,
540 .remove = __devexit_p(p1022_ds_remove),
541 .driver = {
542 /* The name must match the 'model' property in the device tree,
543 * in lowercase letters, but only the part after that last
544 * comma. This is because some model properties have a "fsl,"
545 * prefix.
546 */
547 .name = "snd-soc-p1022",
548 .owner = THIS_MODULE,
549 },
550};
551
552/**
553 * p1022_ds_init: machine driver initialization.
554 *
555 * This function is called when this module is loaded.
556 */
557static int __init p1022_ds_init(void)
558{
559 struct device_node *guts_np;
560 struct resource res;
561
562 pr_info("Freescale P1022 DS ALSA SoC machine driver\n");
563
564 /* Get the physical address of the global utilities registers */
565 guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
566 if (of_address_to_resource(guts_np, 0, &res)) {
567 pr_err("p1022-ds: missing/invalid global utilities node\n");
568 return -EINVAL;
569 }
570 guts_phys = res.start;
571 of_node_put(guts_np);
572
573 return platform_driver_register(&p1022_ds_driver);
574}
575
576/**
577 * p1022_ds_exit: machine driver exit
578 *
579 * This function is called when this driver is unloaded.
580 */
581static void __exit p1022_ds_exit(void)
582{
583 platform_driver_unregister(&p1022_ds_driver);
584}
585
586module_init(p1022_ds_init);
587module_exit(p1022_ds_exit);
588
589MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
590MODULE_DESCRIPTION("Freescale P1022 DS ALSA SoC machine driver");
591MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
index 6644cba7cbf2..fe15bb26e484 100644
--- a/sound/soc/fsl/pcm030-audio-fabric.c
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -32,21 +32,24 @@
32 32
33#define DRV_NAME "pcm030-audio-fabric" 33#define DRV_NAME "pcm030-audio-fabric"
34 34
35static struct snd_soc_device device;
36static struct snd_soc_card card; 35static struct snd_soc_card card;
37 36
38static struct snd_soc_dai_link pcm030_fabric_dai[] = { 37static struct snd_soc_dai_link pcm030_fabric_dai[] = {
39{ 38{
40 .name = "AC97", 39 .name = "AC97",
41 .stream_name = "AC97 Analog", 40 .stream_name = "AC97 Analog",
42 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 41 .codec_dai_name = "wm9712-hifi",
43 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_NORMAL], 42 .cpu_dai_name = "mpc5200-psc-ac97.0",
43 .platform_name = "mpc5200-pcm-audio",
44 .codec_name = "wm9712-codec",
44}, 45},
45{ 46{
46 .name = "AC97", 47 .name = "AC97",
47 .stream_name = "AC97 IEC958", 48 .stream_name = "AC97 IEC958",
48 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 49 .codec_dai_name = "wm9712-aux",
49 .cpu_dai = &psc_ac97_dai[MPC5200_AC97_SPDIF], 50 .cpu_dai_name = "mpc5200-psc-ac97.1",
51 .platform_name = "mpc5200-pcm-audio",
52 ..codec_name = "wm9712-codec",
50}, 53},
51}; 54};
52 55
@@ -58,22 +61,18 @@ static __init int pcm030_fabric_init(void)
58 if (!of_machine_is_compatible("phytec,pcm030")) 61 if (!of_machine_is_compatible("phytec,pcm030"))
59 return -ENODEV; 62 return -ENODEV;
60 63
61 card.platform = &mpc5200_audio_dma_platform; 64
62 card.name = "pcm030"; 65 card.name = "pcm030";
63 card.dai_link = pcm030_fabric_dai; 66 card.dai_link = pcm030_fabric_dai;
64 card.num_links = ARRAY_SIZE(pcm030_fabric_dai); 67 card.num_links = ARRAY_SIZE(pcm030_fabric_dai);
65 68
66 device.card = &card;
67 device.codec_dev = &soc_codec_dev_wm9712;
68
69 pdev = platform_device_alloc("soc-audio", 1); 69 pdev = platform_device_alloc("soc-audio", 1);
70 if (!pdev) { 70 if (!pdev) {
71 pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); 71 pr_err("pcm030_fabric_init: platform_device_alloc() failed\n");
72 return -ENODEV; 72 return -ENODEV;
73 } 73 }
74 74
75 platform_set_drvdata(pdev, &device); 75 platform_set_drvdata(pdev, &card);
76 device.dev = &pdev->dev;
77 76
78 rc = platform_device_add(pdev); 77 rc = platform_device_add(pdev);
79 if (rc) { 78 if (rc) {
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
deleted file mode 100644
index 3bc13fd89096..000000000000
--- a/sound/soc/fsl/soc-of-simple.c
+++ /dev/null
@@ -1,172 +0,0 @@
1/*
2 * OF helpers for ALSA SoC Layer
3 *
4 * Copyright (C) 2008, Secret Lab Technologies Ltd.
5 */
6
7#include <linux/module.h>
8#include <linux/moduleparam.h>
9#include <linux/init.h>
10#include <linux/delay.h>
11#include <linux/pm.h>
12#include <linux/bitops.h>
13#include <linux/platform_device.h>
14#include <linux/of.h>
15#include <linux/slab.h>
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/soc.h>
20#include <sound/soc-of-simple.h>
21#include <sound/initval.h>
22
23MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
24MODULE_LICENSE("GPL");
25MODULE_DESCRIPTION("ALSA SoC OpenFirmware bindings");
26
27static DEFINE_MUTEX(of_snd_soc_mutex);
28static LIST_HEAD(of_snd_soc_device_list);
29static int of_snd_soc_next_index;
30
31struct of_snd_soc_device {
32 int id;
33 struct list_head list;
34 struct snd_soc_device device;
35 struct snd_soc_card card;
36 struct snd_soc_dai_link dai_link;
37 struct platform_device *pdev;
38 struct device_node *platform_node;
39 struct device_node *codec_node;
40};
41
42static struct snd_soc_ops of_snd_soc_ops = {
43};
44
45static struct of_snd_soc_device *
46of_snd_soc_get_device(struct device_node *codec_node)
47{
48 struct of_snd_soc_device *of_soc;
49
50 list_for_each_entry(of_soc, &of_snd_soc_device_list, list) {
51 if (of_soc->codec_node == codec_node)
52 return of_soc;
53 }
54
55 of_soc = kzalloc(sizeof(struct of_snd_soc_device), GFP_KERNEL);
56 if (!of_soc)
57 return NULL;
58
59 /* Initialize the structure and add it to the global list */
60 of_soc->codec_node = codec_node;
61 of_soc->id = of_snd_soc_next_index++;
62 of_soc->card.dai_link = &of_soc->dai_link;
63 of_soc->card.num_links = 1;
64 of_soc->device.card = &of_soc->card;
65 of_soc->dai_link.ops = &of_snd_soc_ops;
66 list_add(&of_soc->list, &of_snd_soc_device_list);
67
68 return of_soc;
69}
70
71static void of_snd_soc_register_device(struct of_snd_soc_device *of_soc)
72{
73 struct platform_device *pdev;
74 int rc;
75
76 /* Only register the device if both the codec and platform have
77 * been registered */
78 if ((!of_soc->device.codec_data) || (!of_soc->platform_node))
79 return;
80
81 pr_info("platform<-->codec match achieved; registering machine\n");
82
83 pdev = platform_device_alloc("soc-audio", of_soc->id);
84 if (!pdev) {
85 pr_err("of_soc: platform_device_alloc() failed\n");
86 return;
87 }
88
89 pdev->dev.platform_data = of_soc;
90 platform_set_drvdata(pdev, &of_soc->device);
91 of_soc->device.dev = &pdev->dev;
92
93 /* The ASoC device is complete; register it */
94 rc = platform_device_add(pdev);
95 if (rc) {
96 pr_err("of_soc: platform_device_add() failed\n");
97 return;
98 }
99
100}
101
102int of_snd_soc_register_codec(struct snd_soc_codec_device *codec_dev,
103 void *codec_data, struct snd_soc_dai *dai,
104 struct device_node *node)
105{
106 struct of_snd_soc_device *of_soc;
107 int rc = 0;
108
109 pr_info("registering ASoC codec driver: %s\n", node->full_name);
110
111 mutex_lock(&of_snd_soc_mutex);
112 of_soc = of_snd_soc_get_device(node);
113 if (!of_soc) {
114 rc = -ENOMEM;
115 goto out;
116 }
117
118 /* Store the codec data */
119 of_soc->device.codec_data = codec_data;
120 of_soc->device.codec_dev = codec_dev;
121 of_soc->dai_link.name = (char *)node->name;
122 of_soc->dai_link.stream_name = (char *)node->name;
123 of_soc->dai_link.codec_dai = dai;
124
125 /* Now try to register the SoC device */
126 of_snd_soc_register_device(of_soc);
127
128 out:
129 mutex_unlock(&of_snd_soc_mutex);
130 return rc;
131}
132EXPORT_SYMBOL_GPL(of_snd_soc_register_codec);
133
134int of_snd_soc_register_platform(struct snd_soc_platform *platform,
135 struct device_node *node,
136 struct snd_soc_dai *cpu_dai)
137{
138 struct of_snd_soc_device *of_soc;
139 struct device_node *codec_node;
140 const phandle *handle;
141 int len, rc = 0;
142
143 pr_info("registering ASoC platform driver: %s\n", node->full_name);
144
145 handle = of_get_property(node, "codec-handle", &len);
146 if (!handle || len < sizeof(handle))
147 return -ENODEV;
148 codec_node = of_find_node_by_phandle(*handle);
149 if (!codec_node)
150 return -ENODEV;
151 pr_info("looking for codec: %s\n", codec_node->full_name);
152
153 mutex_lock(&of_snd_soc_mutex);
154 of_soc = of_snd_soc_get_device(codec_node);
155 if (!of_soc) {
156 rc = -ENOMEM;
157 goto out;
158 }
159
160 of_soc->platform_node = node;
161 of_soc->dai_link.cpu_dai = cpu_dai;
162 of_soc->card.platform = platform;
163 of_soc->card.name = of_soc->dai_link.cpu_dai->name;
164
165 /* Now try to register the SoC device */
166 of_snd_soc_register_device(of_soc);
167
168 out:
169 mutex_unlock(&of_snd_soc_mutex);
170 return rc;
171}
172EXPORT_SYMBOL_GPL(of_snd_soc_register_platform);
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index 687c76fc0839..642270a635ea 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -8,12 +8,24 @@ menuconfig SND_IMX_SOC
8 Say Y or M if you want to add support for codecs attached to 8 Say Y or M if you want to add support for codecs attached to
9 the i.MX SSI interface. 9 the i.MX SSI interface.
10 10
11
11if SND_IMX_SOC 12if SND_IMX_SOC
12 13
14config SND_MXC_SOC_SSI
15 tristate
16
17config SND_MXC_SOC_FIQ
18 tristate
19
20config SND_MXC_SOC_MX2
21 tristate
22
13config SND_MXC_SOC_WM1133_EV1 23config SND_MXC_SOC_WM1133_EV1
14 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted" 24 tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
15 depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL 25 depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
16 select SND_SOC_WM8350 26 select SND_SOC_WM8350
27 select SND_MXC_SOC_SSI
28 select SND_MXC_SOC_FIQ
17 help 29 help
18 Enable support for audio on the i.MX31ADS with the WM1133-EV1 30 Enable support for audio on the i.MX31ADS with the WM1133-EV1
19 PMIC board with WM8835x fitted. 31 PMIC board with WM8835x fitted.
@@ -22,6 +34,8 @@ config SND_SOC_PHYCORE_AC97
22 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards" 34 tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
23 depends on MACH_PCM043 || MACH_PCA100 35 depends on MACH_PCM043 || MACH_PCA100
24 select SND_SOC_WM9712 36 select SND_SOC_WM9712
37 select SND_MXC_SOC_SSI
38 select SND_MXC_SOC_FIQ
25 help 39 help
26 Say Y if you want to add support for SoC audio on Phytec phyCORE 40 Say Y if you want to add support for SoC audio on Phytec phyCORE
27 and phyCARD boards in AC97 mode 41 and phyCARD boards in AC97 mode
@@ -32,6 +46,8 @@ config SND_SOC_EUKREA_TLV320
32 || MACH_EUKREA_MBIMXSD25_BASEBOARD \ 46 || MACH_EUKREA_MBIMXSD25_BASEBOARD \
33 || MACH_EUKREA_MBIMXSD35_BASEBOARD 47 || MACH_EUKREA_MBIMXSD35_BASEBOARD
34 select SND_SOC_TLV320AIC23 48 select SND_SOC_TLV320AIC23
49 select SND_MXC_SOC_SSI
50 select SND_MXC_SOC_FIQ
35 help 51 help
36 Enable I2S based access to the TLV320AIC23B codec attached 52 Enable I2S based access to the TLV320AIC23B codec attached
37 to the SSI interface 53 to the SSI interface
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index 7bc57baf2b0e..b67fc02a4ecc 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -1,11 +1,11 @@
1# i.MX Platform Support 1# i.MX Platform Support
2snd-soc-imx-objs := imx-ssi.o imx-pcm-fiq.o 2snd-soc-imx-objs := imx-ssi.o
3 3snd-soc-imx-fiq-objs := imx-pcm-fiq.o
4ifdef CONFIG_MACH_MX27 4snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o
5snd-soc-imx-objs += imx-pcm-dma-mx2.o
6endif
7 5
8obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o 6obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
7obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o
8obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o
9 9
10# i.MX Machine Support 10# i.MX Machine Support
11snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o 11snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c
index f15dfbdc47ee..b59675257ce5 100644
--- a/sound/soc/imx/eukrea-tlv320.c
+++ b/sound/soc/imx/eukrea-tlv320.c
@@ -79,22 +79,19 @@ static struct snd_soc_ops eukrea_tlv320_snd_ops = {
79static struct snd_soc_dai_link eukrea_tlv320_dai = { 79static struct snd_soc_dai_link eukrea_tlv320_dai = {
80 .name = "tlv320aic23", 80 .name = "tlv320aic23",
81 .stream_name = "TLV320AIC23", 81 .stream_name = "TLV320AIC23",
82 .codec_dai = &tlv320aic23_dai, 82 .codec_dai = "tlv320aic23-hifi",
83 .platform_name = "imx-pcm-audio.0",
84 .codec_name = "tlv320aic23-codec.0-001a",
85 .cpu_dai = "imx-ssi.0",
83 .ops = &eukrea_tlv320_snd_ops, 86 .ops = &eukrea_tlv320_snd_ops,
84}; 87};
85 88
86static struct snd_soc_card eukrea_tlv320 = { 89static struct snd_soc_card eukrea_tlv320 = {
87 .name = "cpuimx-audio", 90 .name = "cpuimx-audio",
88 .platform = &imx_soc_platform,
89 .dai_link = &eukrea_tlv320_dai, 91 .dai_link = &eukrea_tlv320_dai,
90 .num_links = 1, 92 .num_links = 1,
91}; 93};
92 94
93static struct snd_soc_device eukrea_tlv320_snd_devdata = {
94 .card = &eukrea_tlv320,
95 .codec_dev = &soc_codec_dev_tlv320aic23,
96};
97
98static struct platform_device *eukrea_tlv320_snd_device; 95static struct platform_device *eukrea_tlv320_snd_device;
99 96
100static int __init eukrea_tlv320_init(void) 97static int __init eukrea_tlv320_init(void)
@@ -110,10 +107,7 @@ static int __init eukrea_tlv320_init(void)
110 if (!eukrea_tlv320_snd_device) 107 if (!eukrea_tlv320_snd_device)
111 return -ENOMEM; 108 return -ENOMEM;
112 109
113 eukrea_tlv320_dai.cpu_dai = &imx_ssi_pcm_dai[0]; 110 platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320);
114
115 platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320_snd_devdata);
116 eukrea_tlv320_snd_devdata.dev = &eukrea_tlv320_snd_device->dev;
117 ret = platform_device_add(eukrea_tlv320_snd_device); 111 ret = platform_device_add(eukrea_tlv320_snd_device);
118 112
119 if (ret) { 113 if (ret) {
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 0a595da4811d..fd493ee1428e 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -103,7 +103,7 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream)
103 struct imx_pcm_runtime_data *iprtd = runtime->private_data; 103 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
104 int ret; 104 int ret;
105 105
106 dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 106 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
107 107
108 iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH); 108 iprtd->dma = imx_dma_request_by_prio(DRV_NAME, DMA_PRIO_HIGH);
109 if (iprtd->dma < 0) { 109 if (iprtd->dma < 0) {
@@ -213,7 +213,7 @@ static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
213 struct imx_pcm_runtime_data *iprtd = runtime->private_data; 213 struct imx_pcm_runtime_data *iprtd = runtime->private_data;
214 int err; 214 int err;
215 215
216 dma_params = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 216 dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
217 217
218 iprtd->substream = substream; 218 iprtd->substream = substream;
219 iprtd->buf = (unsigned int *)substream->dma_buffer.area; 219 iprtd->buf = (unsigned int *)substream->dma_buffer.area;
@@ -318,19 +318,42 @@ static struct snd_pcm_ops imx_pcm_ops = {
318 .mmap = snd_imx_pcm_mmap, 318 .mmap = snd_imx_pcm_mmap,
319}; 319};
320 320
321static struct snd_soc_platform imx_soc_platform_dma = { 321static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
322 .name = "imx-audio", 322 .ops = &imx_pcm_ops,
323 .pcm_ops = &imx_pcm_ops,
324 .pcm_new = imx_pcm_new, 323 .pcm_new = imx_pcm_new,
325 .pcm_free = imx_pcm_free, 324 .pcm_free = imx_pcm_free,
326}; 325};
327 326
328struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev, 327static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
329 struct imx_ssi *ssi)
330{ 328{
331 ssi->dma_params_tx.burstsize = DMA_TXFIFO_BURST; 329 return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
332 ssi->dma_params_rx.burstsize = DMA_RXFIFO_BURST; 330}
331
332static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
333{
334 snd_soc_unregister_platform(&pdev->dev);
335 return 0;
336}
337
338static struct platform_driver imx_pcm_driver = {
339 .driver = {
340 .name = "imx-pcm-audio",
341 .owner = THIS_MODULE,
342 },
333 343
334 return &imx_soc_platform_dma; 344 .probe = imx_soc_platform_probe,
345 .remove = __devexit_p(imx_soc_platform_remove),
346};
347
348static int __init snd_imx_pcm_init(void)
349{
350 return platform_driver_register(&imx_pcm_driver);
351}
352module_init(snd_imx_pcm_init);
353
354static void __exit snd_imx_pcm_exit(void)
355{
356 platform_driver_unregister(&imx_pcm_driver);
335} 357}
358module_exit(snd_imx_pcm_exit);
336 359
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index b2bf27282cd2..413b78da248f 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -236,6 +236,8 @@ static struct snd_pcm_ops imx_pcm_ops = {
236 .mmap = snd_imx_pcm_mmap, 236 .mmap = snd_imx_pcm_mmap,
237}; 237};
238 238
239static int ssi_irq = 0;
240
239static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai, 241static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
240 struct snd_pcm *pcm) 242 struct snd_pcm *pcm)
241{ 243{
@@ -245,7 +247,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
245 if (ret) 247 if (ret)
246 return ret; 248 return ret;
247 249
248 if (dai->playback.channels_min) { 250 if (dai->driver->playback.channels_min) {
249 struct snd_pcm_substream *substream = 251 struct snd_pcm_substream *substream =
250 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 252 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
251 struct snd_dma_buffer *buf = &substream->dma_buffer; 253 struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -253,7 +255,7 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
253 imx_ssi_fiq_tx_buffer = (unsigned long)buf->area; 255 imx_ssi_fiq_tx_buffer = (unsigned long)buf->area;
254 } 256 }
255 257
256 if (dai->capture.channels_min) { 258 if (dai->driver->capture.channels_min) {
257 struct snd_pcm_substream *substream = 259 struct snd_pcm_substream *substream =
258 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 260 pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
259 struct snd_dma_buffer *buf = &substream->dma_buffer; 261 struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -267,24 +269,32 @@ static int imx_pcm_fiq_new(struct snd_card *card, struct snd_soc_dai *dai,
267 return 0; 269 return 0;
268} 270}
269 271
270static struct snd_soc_platform imx_soc_platform_fiq = { 272static void imx_pcm_fiq_free(struct snd_pcm *pcm)
271 .pcm_ops = &imx_pcm_ops, 273{
274 mxc_set_irq_fiq(ssi_irq, 0);
275 release_fiq(&fh);
276 imx_pcm_free(pcm);
277}
278
279static struct snd_soc_platform_driver imx_soc_platform_fiq = {
280 .ops = &imx_pcm_ops,
272 .pcm_new = imx_pcm_fiq_new, 281 .pcm_new = imx_pcm_fiq_new,
273 .pcm_free = imx_pcm_free, 282 .pcm_free = imx_pcm_fiq_free,
274}; 283};
275 284
276struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, 285static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
277 struct imx_ssi *ssi)
278{ 286{
279 int ret = 0; 287 struct imx_ssi *ssi = platform_get_drvdata(pdev);
288 int ret;
280 289
281 ret = claim_fiq(&fh); 290 ret = claim_fiq(&fh);
282 if (ret) { 291 if (ret) {
283 dev_err(&pdev->dev, "failed to claim fiq: %d", ret); 292 dev_err(&pdev->dev, "failed to claim fiq: %d", ret);
284 return ERR_PTR(ret); 293 return ret;
285 } 294 }
286 295
287 mxc_set_irq_fiq(ssi->irq, 1); 296 mxc_set_irq_fiq(ssi->irq, 1);
297 ssi_irq = ssi->irq;
288 298
289 imx_pcm_fiq = ssi->irq; 299 imx_pcm_fiq = ssi->irq;
290 300
@@ -293,13 +303,43 @@ struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
293 ssi->dma_params_tx.burstsize = 4; 303 ssi->dma_params_tx.burstsize = 4;
294 ssi->dma_params_rx.burstsize = 6; 304 ssi->dma_params_rx.burstsize = 6;
295 305
296 return &imx_soc_platform_fiq; 306 ret = snd_soc_register_platform(&pdev->dev, &imx_soc_platform_fiq);
307 if (ret)
308 goto failed_register;
309
310 return 0;
311
312failed_register:
313 mxc_set_irq_fiq(ssi_irq, 0);
314 release_fiq(&fh);
315
316 return ret;
297} 317}
298 318
299void imx_ssi_fiq_exit(struct platform_device *pdev, 319static int __devexit imx_soc_platform_remove(struct platform_device *pdev)
300 struct imx_ssi *ssi)
301{ 320{
302 mxc_set_irq_fiq(ssi->irq, 0); 321 snd_soc_unregister_platform(&pdev->dev);
303 release_fiq(&fh); 322 return 0;
304} 323}
305 324
325static struct platform_driver imx_pcm_driver = {
326 .driver = {
327 .name = "imx-fiq-pcm-audio",
328 .owner = THIS_MODULE,
329 },
330
331 .probe = imx_soc_platform_probe,
332 .remove = __devexit_p(imx_soc_platform_remove),
333};
334
335static int __init snd_imx_pcm_init(void)
336{
337 return platform_driver_register(&imx_pcm_driver);
338}
339module_init(snd_imx_pcm_init);
340
341static void __exit snd_imx_pcm_exit(void)
342{
343 platform_driver_unregister(&imx_pcm_driver);
344}
345module_exit(snd_imx_pcm_exit);
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index c81da05a4f11..d4bd345b0a8d 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -61,7 +61,7 @@
61static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, 61static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
62 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) 62 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
63{ 63{
64 struct imx_ssi *ssi = cpu_dai->private_data; 64 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
65 u32 sccr; 65 u32 sccr;
66 66
67 sccr = readl(ssi->base + SSI_STCCR); 67 sccr = readl(ssi->base + SSI_STCCR);
@@ -86,7 +86,7 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
86 */ 86 */
87static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) 87static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
88{ 88{
89 struct imx_ssi *ssi = cpu_dai->private_data; 89 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
90 u32 strcr = 0, scr; 90 u32 strcr = 0, scr;
91 91
92 scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); 92 scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET);
@@ -164,7 +164,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
164static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 164static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
165 int clk_id, unsigned int freq, int dir) 165 int clk_id, unsigned int freq, int dir)
166{ 166{
167 struct imx_ssi *ssi = cpu_dai->private_data; 167 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
168 u32 scr; 168 u32 scr;
169 169
170 scr = readl(ssi->base + SSI_SCR); 170 scr = readl(ssi->base + SSI_SCR);
@@ -192,7 +192,7 @@ static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
192static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, 192static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
193 int div_id, int div) 193 int div_id, int div)
194{ 194{
195 struct imx_ssi *ssi = cpu_dai->private_data; 195 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
196 u32 stccr, srccr; 196 u32 stccr, srccr;
197 197
198 stccr = readl(ssi->base + SSI_STCCR); 198 stccr = readl(ssi->base + SSI_STCCR);
@@ -241,7 +241,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
241 struct snd_pcm_hw_params *params, 241 struct snd_pcm_hw_params *params,
242 struct snd_soc_dai *cpu_dai) 242 struct snd_soc_dai *cpu_dai)
243{ 243{
244 struct imx_ssi *ssi = cpu_dai->private_data; 244 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
245 struct imx_pcm_dma_params *dma_data; 245 struct imx_pcm_dma_params *dma_data;
246 u32 reg, sccr; 246 u32 reg, sccr;
247 247
@@ -282,9 +282,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
282static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, 282static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
283 struct snd_soc_dai *dai) 283 struct snd_soc_dai *dai)
284{ 284{
285 struct snd_soc_pcm_runtime *rtd = substream->private_data; 285 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai);
286 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
287 struct imx_ssi *ssi = cpu_dai->private_data;
288 unsigned int sier_bits, sier; 286 unsigned int sier_bits, sier;
289 unsigned int scr; 287 unsigned int scr;
290 288
@@ -353,22 +351,6 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
353 .trigger = imx_ssi_trigger, 351 .trigger = imx_ssi_trigger,
354}; 352};
355 353
356static struct snd_soc_dai imx_ssi_dai = {
357 .playback = {
358 .channels_min = 2,
359 .channels_max = 2,
360 .rates = SNDRV_PCM_RATE_8000_96000,
361 .formats = SNDRV_PCM_FMTBIT_S16_LE,
362 },
363 .capture = {
364 .channels_min = 2,
365 .channels_max = 2,
366 .rates = SNDRV_PCM_RATE_8000_96000,
367 .formats = SNDRV_PCM_FMTBIT_S16_LE,
368 },
369 .ops = &imx_ssi_pcm_dai_ops,
370};
371
372int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, 354int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
373 struct vm_area_struct *vma) 355 struct vm_area_struct *vma)
374{ 356{
@@ -384,6 +366,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
384 runtime->dma_bytes); 366 runtime->dma_bytes);
385 return ret; 367 return ret;
386} 368}
369EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
387 370
388static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 371static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
389{ 372{
@@ -415,14 +398,14 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
415 card->dev->dma_mask = &imx_pcm_dmamask; 398 card->dev->dma_mask = &imx_pcm_dmamask;
416 if (!card->dev->coherent_dma_mask) 399 if (!card->dev->coherent_dma_mask)
417 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 400 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
418 if (dai->playback.channels_min) { 401 if (dai->driver->playback.channels_min) {
419 ret = imx_pcm_preallocate_dma_buffer(pcm, 402 ret = imx_pcm_preallocate_dma_buffer(pcm,
420 SNDRV_PCM_STREAM_PLAYBACK); 403 SNDRV_PCM_STREAM_PLAYBACK);
421 if (ret) 404 if (ret)
422 goto out; 405 goto out;
423 } 406 }
424 407
425 if (dai->capture.channels_min) { 408 if (dai->driver->capture.channels_min) {
426 ret = imx_pcm_preallocate_dma_buffer(pcm, 409 ret = imx_pcm_preallocate_dma_buffer(pcm,
427 SNDRV_PCM_STREAM_CAPTURE); 410 SNDRV_PCM_STREAM_CAPTURE);
428 if (ret) 411 if (ret)
@@ -432,6 +415,7 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
432out: 415out:
433 return ret; 416 return ret;
434} 417}
418EXPORT_SYMBOL_GPL(imx_pcm_new);
435 419
436void imx_pcm_free(struct snd_pcm *pcm) 420void imx_pcm_free(struct snd_pcm *pcm)
437{ 421{
@@ -453,14 +437,40 @@ void imx_pcm_free(struct snd_pcm *pcm)
453 buf->area = NULL; 437 buf->area = NULL;
454 } 438 }
455} 439}
440EXPORT_SYMBOL_GPL(imx_pcm_free);
456 441
457struct snd_soc_platform imx_soc_platform = { 442static struct snd_soc_dai_driver imx_ssi_dai = {
458 .name = "imx-audio", 443 .playback = {
444 .channels_min = 2,
445 .channels_max = 2,
446 .rates = SNDRV_PCM_RATE_8000_96000,
447 .formats = SNDRV_PCM_FMTBIT_S16_LE,
448 },
449 .capture = {
450 .channels_min = 2,
451 .channels_max = 2,
452 .rates = SNDRV_PCM_RATE_8000_96000,
453 .formats = SNDRV_PCM_FMTBIT_S16_LE,
454 },
455 .ops = &imx_ssi_pcm_dai_ops,
459}; 456};
460EXPORT_SYMBOL_GPL(imx_soc_platform);
461 457
462static struct snd_soc_dai imx_ac97_dai = { 458static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
463 .name = "AC97", 459{
460 struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
461 uint32_t val;
462
463 snd_soc_dai_set_drvdata(dai, ssi);
464
465 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
466 SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
467 writel(val, ssi->base + SSI_SFCSR);
468
469 return 0;
470}
471
472static struct snd_soc_dai_driver imx_ac97_dai = {
473 .probe = imx_ssi_dai_probe,
464 .ac97_control = 1, 474 .ac97_control = 1,
465 .playback = { 475 .playback = {
466 .stream_name = "AC97 Playback", 476 .stream_name = "AC97 Playback",
@@ -580,25 +590,18 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
580}; 590};
581EXPORT_SYMBOL_GPL(soc_ac97_ops); 591EXPORT_SYMBOL_GPL(soc_ac97_ops);
582 592
583struct snd_soc_dai imx_ssi_pcm_dai[2];
584EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai);
585
586static int imx_ssi_probe(struct platform_device *pdev) 593static int imx_ssi_probe(struct platform_device *pdev)
587{ 594{
588 struct resource *res; 595 struct resource *res;
589 struct imx_ssi *ssi; 596 struct imx_ssi *ssi;
590 struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; 597 struct imx_ssi_platform_data *pdata = pdev->dev.platform_data;
591 struct snd_soc_platform *platform;
592 int ret = 0; 598 int ret = 0;
593 unsigned int val; 599 struct snd_soc_dai_driver *dai;
594 struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id];
595
596 if (dai->id >= ARRAY_SIZE(imx_ssi_pcm_dai))
597 return -EINVAL;
598 600
599 ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); 601 ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
600 if (!ssi) 602 if (!ssi)
601 return -ENOMEM; 603 return -ENOMEM;
604 dev_set_drvdata(&pdev->dev, ssi);
602 605
603 if (pdata) { 606 if (pdata) {
604 ssi->ac97_reset = pdata->ac97_reset; 607 ssi->ac97_reset = pdata->ac97_reset;
@@ -643,9 +646,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
643 } 646 }
644 ac97_ssi = ssi; 647 ac97_ssi = ssi;
645 setup_channel_to_ac97(ssi); 648 setup_channel_to_ac97(ssi);
646 memcpy(dai, &imx_ac97_dai, sizeof(imx_ac97_dai)); 649 dai = &imx_ac97_dai;
647 } else 650 } else
648 memcpy(dai, &imx_ssi_dai, sizeof(imx_ssi_dai)); 651 dai = &imx_ssi_dai;
649 652
650 writel(0x0, ssi->base + SSI_SIER); 653 writel(0x0, ssi->base + SSI_SIER);
651 654
@@ -660,37 +663,36 @@ static int imx_ssi_probe(struct platform_device *pdev)
660 if (res) 663 if (res)
661 ssi->dma_params_rx.dma = res->start; 664 ssi->dma_params_rx.dma = res->start;
662 665
663 dai->id = pdev->id;
664 dai->dev = &pdev->dev;
665 dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id);
666 dai->private_data = ssi;
667
668 if ((cpu_is_mx27() || cpu_is_mx21()) && 666 if ((cpu_is_mx27() || cpu_is_mx21()) &&
669 !(ssi->flags & IMX_SSI_USE_AC97) && 667 !(ssi->flags & IMX_SSI_USE_AC97) &&
670 (ssi->flags & IMX_SSI_DMA)) { 668 (ssi->flags & IMX_SSI_DMA)) {
671 ssi->flags |= IMX_SSI_DMA; 669 ssi->flags |= IMX_SSI_DMA;
672 platform = imx_ssi_dma_mx2_init(pdev, ssi); 670 }
673 } else
674 platform = imx_ssi_fiq_init(pdev, ssi);
675
676 imx_soc_platform.pcm_ops = platform->pcm_ops;
677 imx_soc_platform.pcm_new = platform->pcm_new;
678 imx_soc_platform.pcm_free = platform->pcm_free;
679 671
680 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | 672 platform_set_drvdata(pdev, ssi);
681 SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
682 writel(val, ssi->base + SSI_SFCSR);
683 673
684 ret = snd_soc_register_dai(dai); 674 ret = snd_soc_register_dai(&pdev->dev, dai);
685 if (ret) { 675 if (ret) {
686 dev_err(&pdev->dev, "register DAI failed\n"); 676 dev_err(&pdev->dev, "register DAI failed\n");
687 goto failed_register; 677 goto failed_register;
688 } 678 }
689 679
690 platform_set_drvdata(pdev, ssi); 680 ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id);
681 if (!ssi->soc_platform_pdev)
682 goto failed_pdev_alloc;
683 platform_set_drvdata(ssi->soc_platform_pdev, ssi);
684 ret = platform_device_add(ssi->soc_platform_pdev);
685 if (ret) {
686 dev_err(&pdev->dev, "failed to add platform device\n");
687 goto failed_pdev_add;
688 }
691 689
692 return 0; 690 return 0;
693 691
692failed_pdev_add:
693 platform_device_put(ssi->soc_platform_pdev);
694failed_pdev_alloc:
695 snd_soc_unregister_dai(&pdev->dev);
694failed_register: 696failed_register:
695failed_ac97: 697failed_ac97:
696 iounmap(ssi->base); 698 iounmap(ssi->base);
@@ -709,16 +711,15 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)
709{ 711{
710 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 712 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
711 struct imx_ssi *ssi = platform_get_drvdata(pdev); 713 struct imx_ssi *ssi = platform_get_drvdata(pdev);
712 struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id];
713 714
714 snd_soc_unregister_dai(dai); 715 platform_device_del(ssi->soc_platform_pdev);
716 platform_device_put(ssi->soc_platform_pdev);
717
718 snd_soc_unregister_dai(&pdev->dev);
715 719
716 if (ssi->flags & IMX_SSI_USE_AC97) 720 if (ssi->flags & IMX_SSI_USE_AC97)
717 ac97_ssi = NULL; 721 ac97_ssi = NULL;
718 722
719 if (!(ssi->flags & IMX_SSI_DMA))
720 imx_ssi_fiq_exit(pdev, ssi);
721
722 iounmap(ssi->base); 723 iounmap(ssi->base);
723 release_mem_region(res->start, resource_size(res)); 724 release_mem_region(res->start, resource_size(res));
724 clk_disable(ssi->clk); 725 clk_disable(ssi->clk);
@@ -733,34 +734,19 @@ static struct platform_driver imx_ssi_driver = {
733 .remove = __devexit_p(imx_ssi_remove), 734 .remove = __devexit_p(imx_ssi_remove),
734 735
735 .driver = { 736 .driver = {
736 .name = DRV_NAME, 737 .name = "imx-ssi",
737 .owner = THIS_MODULE, 738 .owner = THIS_MODULE,
738 }, 739 },
739}; 740};
740 741
741static int __init imx_ssi_init(void) 742static int __init imx_ssi_init(void)
742{ 743{
743 int ret; 744 return platform_driver_register(&imx_ssi_driver);
744
745 ret = snd_soc_register_platform(&imx_soc_platform);
746 if (ret) {
747 pr_err("failed to register soc platform: %d\n", ret);
748 return ret;
749 }
750
751 ret = platform_driver_register(&imx_ssi_driver);
752 if (ret) {
753 snd_soc_unregister_platform(&imx_soc_platform);
754 return ret;
755 }
756
757 return 0;
758} 745}
759 746
760static void __exit imx_ssi_exit(void) 747static void __exit imx_ssi_exit(void)
761{ 748{
762 platform_driver_unregister(&imx_ssi_driver); 749 platform_driver_unregister(&imx_ssi_driver);
763 snd_soc_unregister_platform(&imx_soc_platform);
764} 750}
765 751
766module_init(imx_ssi_init); 752module_init(imx_ssi_init);
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index 55f26ebcd8c2..53b780d9b2b0 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -183,9 +183,6 @@
183#define IMX_SSI_RX_DIV_PSR 4 183#define IMX_SSI_RX_DIV_PSR 4
184#define IMX_SSI_RX_DIV_PM 5 184#define IMX_SSI_RX_DIV_PM 5
185 185
186extern struct snd_soc_dai imx_ssi_pcm_dai[2];
187extern struct snd_soc_platform imx_soc_platform;
188
189#define DRV_NAME "imx-ssi" 186#define DRV_NAME "imx-ssi"
190 187
191struct imx_pcm_dma_params { 188struct imx_pcm_dma_params {
@@ -197,7 +194,7 @@ struct imx_pcm_dma_params {
197struct imx_ssi { 194struct imx_ssi {
198 struct platform_device *ac97_dev; 195 struct platform_device *ac97_dev;
199 196
200 struct snd_soc_device imx_ac97; 197 struct snd_soc_dai *imx_ac97;
201 struct clk *clk; 198 struct clk *clk;
202 void __iomem *base; 199 void __iomem *base;
203 int irq; 200 int irq;
@@ -213,6 +210,8 @@ struct imx_ssi {
213 struct imx_pcm_dma_params dma_params_tx; 210 struct imx_pcm_dma_params dma_params_tx;
214 211
215 int enabled; 212 int enabled;
213
214 struct platform_device *soc_platform_pdev;
216}; 215};
217 216
218struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev, 217struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c
index a8307d55c70e..6a65dd705519 100644
--- a/sound/soc/imx/phycore-ac97.c
+++ b/sound/soc/imx/phycore-ac97.c
@@ -32,23 +32,20 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = {
32 { 32 {
33 .name = "HiFi", 33 .name = "HiFi",
34 .stream_name = "HiFi", 34 .stream_name = "HiFi",
35 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 35 .codec_dai_name = "wm9712-hifi",
36 .codec_name = "wm9712-codec",
37 .cpu_dai_name = "imx-ssi.0",
38 .platform_name = "imx-fiq-pcm-audio.0",
36 .ops = &imx_phycore_hifi_ops, 39 .ops = &imx_phycore_hifi_ops,
37 }, 40 },
38}; 41};
39 42
40static struct snd_soc_card imx_phycore = { 43static struct snd_soc_card imx_phycore = {
41 .name = "PhyCORE-audio", 44 .name = "PhyCORE-audio",
42 .platform = &imx_soc_platform,
43 .dai_link = imx_phycore_dai_ac97, 45 .dai_link = imx_phycore_dai_ac97,
44 .num_links = ARRAY_SIZE(imx_phycore_dai_ac97), 46 .num_links = ARRAY_SIZE(imx_phycore_dai_ac97),
45}; 47};
46 48
47static struct snd_soc_device imx_phycore_snd_devdata = {
48 .card = &imx_phycore,
49 .codec_dev = &soc_codec_dev_wm9712,
50};
51
52static struct platform_device *imx_phycore_snd_device; 49static struct platform_device *imx_phycore_snd_device;
53 50
54static int __init imx_phycore_init(void) 51static int __init imx_phycore_init(void)
@@ -63,10 +60,12 @@ static int __init imx_phycore_init(void)
63 if (!imx_phycore_snd_device) 60 if (!imx_phycore_snd_device)
64 return -ENOMEM; 61 return -ENOMEM;
65 62
66 imx_phycore_dai_ac97[0].cpu_dai = &imx_ssi_pcm_dai[0]; 63 platform_set_drvdata(imx_phycore_snd_device, &imx_phycore);
64 ret = platform_device_add(imx_phycore_snd_device);
67 65
68 platform_set_drvdata(imx_phycore_snd_device, &imx_phycore_snd_devdata); 66 imx_phycore_snd_device = platform_device_alloc("wm9712-codec", -1);
69 imx_phycore_snd_devdata.dev = &imx_phycore_snd_device->dev; 67 if (!imx_phycore_snd_device)
68 return -ENOMEM;
70 ret = platform_device_add(imx_phycore_snd_device); 69 ret = platform_device_add(imx_phycore_snd_device);
71 70
72 if (ret) { 71 if (ret) {
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c
index a6e7d9497639..30fdb15065be 100644
--- a/sound/soc/imx/wm1133-ev1.c
+++ b/sound/soc/imx/wm1133-ev1.c
@@ -82,8 +82,8 @@ static int wm1133_ev1_hw_params(struct snd_pcm_substream *substream,
82 struct snd_pcm_hw_params *params) 82 struct snd_pcm_hw_params *params)
83{ 83{
84 struct snd_soc_pcm_runtime *rtd = substream->private_data; 84 struct snd_soc_pcm_runtime *rtd = substream->private_data;
85 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 85 struct snd_soc_dai *codec_dai = rtd->codec_dai;
86 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 86 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
87 int i, found = 0; 87 int i, found = 0;
88 snd_pcm_format_t format = params_format(params); 88 snd_pcm_format_t format = params_format(params);
89 unsigned int rate = params_rate(params); 89 unsigned int rate = params_rate(params);
@@ -210,9 +210,9 @@ static struct snd_soc_jack_pin mic_jack_pins[] = {
210 { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE }, 210 { .pin = "Mic2 Jack", .mask = SND_JACK_MICROPHONE },
211}; 211};
212 212
213static int wm1133_ev1_init(struct snd_soc_codec *codec) 213static int wm1133_ev1_init(struct snd_soc_pcm_runtime *rtd)
214{ 214{
215 struct snd_soc_card *card = codec->socdev->card; 215 struct snd_soc_codec *codec = rtd->codec;
216 216
217 snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets, 217 snd_soc_dapm_new_controls(codec, wm1133_ev1_widgets,
218 ARRAY_SIZE(wm1133_ev1_widgets)); 218 ARRAY_SIZE(wm1133_ev1_widgets));
@@ -221,13 +221,13 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec)
221 ARRAY_SIZE(wm1133_ev1_map)); 221 ARRAY_SIZE(wm1133_ev1_map));
222 222
223 /* Headphone jack detection */ 223 /* Headphone jack detection */
224 snd_soc_jack_new(card, "Headphone", SND_JACK_HEADPHONE, &hp_jack); 224 snd_soc_jack_new(codec, "Headphone", SND_JACK_HEADPHONE, &hp_jack);
225 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins), 225 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
226 hp_jack_pins); 226 hp_jack_pins);
227 wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE); 227 wm8350_hp_jack_detect(codec, WM8350_JDR, &hp_jack, SND_JACK_HEADPHONE);
228 228
229 /* Microphone jack detection */ 229 /* Microphone jack detection */
230 snd_soc_jack_new(card, "Microphone", 230 snd_soc_jack_new(codec, "Microphone",
231 SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack); 231 SND_JACK_MICROPHONE | SND_JACK_BTN_0, &mic_jack);
232 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins), 232 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
233 mic_jack_pins); 233 mic_jack_pins);
@@ -243,8 +243,10 @@ static int wm1133_ev1_init(struct snd_soc_codec *codec)
243static struct snd_soc_dai_link wm1133_ev1_dai = { 243static struct snd_soc_dai_link wm1133_ev1_dai = {
244 .name = "WM1133-EV1", 244 .name = "WM1133-EV1",
245 .stream_name = "Audio", 245 .stream_name = "Audio",
246 .cpu_dai = &imx_ssi_pcm_dai[0], 246 .cpu_dai_name = "imx-ssi.0",
247 .codec_dai = &wm8350_dai, 247 .codec_dai_name = "wm8350-hifi",
248 .platform_name = "imx-fiq-pcm-audio.0",
249 .codec_name = "wm8350-codec.0-0x1a",
248 .init = wm1133_ev1_init, 250 .init = wm1133_ev1_init,
249 .ops = &wm1133_ev1_ops, 251 .ops = &wm1133_ev1_ops,
250 .symmetric_rates = 1, 252 .symmetric_rates = 1,
@@ -252,16 +254,10 @@ static struct snd_soc_dai_link wm1133_ev1_dai = {
252 254
253static struct snd_soc_card wm1133_ev1 = { 255static struct snd_soc_card wm1133_ev1 = {
254 .name = "WM1133-EV1", 256 .name = "WM1133-EV1",
255 .platform = &imx_soc_platform,
256 .dai_link = &wm1133_ev1_dai, 257 .dai_link = &wm1133_ev1_dai,
257 .num_links = 1, 258 .num_links = 1,
258}; 259};
259 260
260static struct snd_soc_device wm1133_ev1_snd_devdata = {
261 .card = &wm1133_ev1,
262 .codec_dev = &soc_codec_dev_wm8350,
263};
264
265static struct platform_device *wm1133_ev1_snd_device; 261static struct platform_device *wm1133_ev1_snd_device;
266 262
267static int __init wm1133_ev1_audio_init(void) 263static int __init wm1133_ev1_audio_init(void)
@@ -286,8 +282,7 @@ static int __init wm1133_ev1_audio_init(void)
286 if (!wm1133_ev1_snd_device) 282 if (!wm1133_ev1_snd_device)
287 return -ENOMEM; 283 return -ENOMEM;
288 284
289 platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1_snd_devdata); 285 platform_set_drvdata(wm1133_ev1_snd_device, &wm1133_ev1);
290 wm1133_ev1_snd_devdata.dev = &wm1133_ev1_snd_device->dev;
291 ret = platform_device_add(wm1133_ev1_snd_device); 286 ret = platform_device_add(wm1133_ev1_snd_device);
292 287
293 if (ret) 288 if (ret)
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index eb518f0c5e01..f3cffd183401 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -106,15 +106,10 @@ static inline void jz4740_i2s_write(const struct jz4740_i2s *i2s,
106 writel(value, i2s->base + reg); 106 writel(value, i2s->base + reg);
107} 107}
108 108
109static inline struct jz4740_i2s *jz4740_dai_to_i2s(struct snd_soc_dai *dai)
110{
111 return dai->private_data;
112}
113
114static int jz4740_i2s_startup(struct snd_pcm_substream *substream, 109static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
115 struct snd_soc_dai *dai) 110 struct snd_soc_dai *dai)
116{ 111{
117 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 112 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
118 uint32_t conf, ctrl; 113 uint32_t conf, ctrl;
119 114
120 if (dai->active) 115 if (dai->active)
@@ -136,7 +131,7 @@ static int jz4740_i2s_startup(struct snd_pcm_substream *substream,
136static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, 131static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
137 struct snd_soc_dai *dai) 132 struct snd_soc_dai *dai)
138{ 133{
139 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 134 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
140 uint32_t conf; 135 uint32_t conf;
141 136
142 if (!dai->active) 137 if (!dai->active)
@@ -152,7 +147,7 @@ static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream,
152static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 147static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
153 struct snd_soc_dai *dai) 148 struct snd_soc_dai *dai)
154{ 149{
155 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 150 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
156 151
157 uint32_t ctrl; 152 uint32_t ctrl;
158 uint32_t mask; 153 uint32_t mask;
@@ -186,7 +181,7 @@ static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
186 181
187static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 182static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
188{ 183{
189 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 184 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
190 185
191 uint32_t format = 0; 186 uint32_t format = 0;
192 uint32_t conf; 187 uint32_t conf;
@@ -238,7 +233,7 @@ static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
238static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, 233static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
239 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 234 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
240{ 235{
241 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 236 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
242 enum jz4740_dma_width dma_width; 237 enum jz4740_dma_width dma_width;
243 struct jz4740_pcm_config *pcm_config; 238 struct jz4740_pcm_config *pcm_config;
244 unsigned int sample_size; 239 unsigned int sample_size;
@@ -288,7 +283,7 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream,
288static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, 283static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
289 unsigned int freq, int dir) 284 unsigned int freq, int dir)
290{ 285{
291 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 286 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
292 struct clk *parent; 287 struct clk *parent;
293 int ret = 0; 288 int ret = 0;
294 289
@@ -312,7 +307,7 @@ static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id,
312 307
313static int jz4740_i2s_suspend(struct snd_soc_dai *dai) 308static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
314{ 309{
315 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 310 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
316 uint32_t conf; 311 uint32_t conf;
317 312
318 if (dai->active) { 313 if (dai->active) {
@@ -330,7 +325,7 @@ static int jz4740_i2s_suspend(struct snd_soc_dai *dai)
330 325
331static int jz4740_i2s_resume(struct snd_soc_dai *dai) 326static int jz4740_i2s_resume(struct snd_soc_dai *dai)
332{ 327{
333 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 328 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
334 uint32_t conf; 329 uint32_t conf;
335 330
336 clk_enable(i2s->clk_aic); 331 clk_enable(i2s->clk_aic);
@@ -346,11 +341,38 @@ static int jz4740_i2s_resume(struct snd_soc_dai *dai)
346 return 0; 341 return 0;
347} 342}
348 343
349static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *dai) 344static void jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
350{ 345{
351 struct jz4740_i2s *i2s = jz4740_dai_to_i2s(dai); 346 struct jz4740_dma_config *dma_config;
347
348 /* Playback */
349 dma_config = &i2s->pcm_config_playback.dma_config;
350 dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
351 dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
352 dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
353 dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
354 dma_config->mode = JZ4740_DMA_MODE_SINGLE;
355 i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
356
357 /* Capture */
358 dma_config = &i2s->pcm_config_capture.dma_config;
359 dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
360 dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
361 dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
362 dma_config->flags = JZ4740_DMA_DST_AUTOINC;
363 dma_config->mode = JZ4740_DMA_MODE_SINGLE;
364 i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
365}
366
367static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai)
368{
369 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
352 uint32_t conf; 370 uint32_t conf;
353 371
372 clk_enable(i2s->clk_aic);
373
374 jz4740_i2c_init_pcm_config(i2s);
375
354 conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | 376 conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) |
355 (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | 377 (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) |
356 JZ_AIC_CONF_OVERFLOW_PLAY_LAST | 378 JZ_AIC_CONF_OVERFLOW_PLAY_LAST |
@@ -363,6 +385,14 @@ static int jz4740_i2s_probe(struct platform_device *pdev, struct snd_soc_dai *da
363 return 0; 385 return 0;
364} 386}
365 387
388static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai)
389{
390 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai);
391
392 clk_disable(i2s->clk_aic);
393 return 0;
394}
395
366static struct snd_soc_dai_ops jz4740_i2s_dai_ops = { 396static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
367 .startup = jz4740_i2s_startup, 397 .startup = jz4740_i2s_startup,
368 .shutdown = jz4740_i2s_shutdown, 398 .shutdown = jz4740_i2s_shutdown,
@@ -375,9 +405,9 @@ static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
375#define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ 405#define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
376 SNDRV_PCM_FMTBIT_S16_LE) 406 SNDRV_PCM_FMTBIT_S16_LE)
377 407
378struct snd_soc_dai jz4740_i2s_dai = { 408static struct snd_soc_dai_driver jz4740_i2s_dai = {
379 .name = "jz4740-i2s", 409 .probe = jz4740_i2s_dai_probe,
380 .probe = jz4740_i2s_probe, 410 .remove = jz4740_i2s_dai_remove,
381 .playback = { 411 .playback = {
382 .channels_min = 1, 412 .channels_min = 1,
383 .channels_max = 2, 413 .channels_max = 2,
@@ -395,30 +425,6 @@ struct snd_soc_dai jz4740_i2s_dai = {
395 .suspend = jz4740_i2s_suspend, 425 .suspend = jz4740_i2s_suspend,
396 .resume = jz4740_i2s_resume, 426 .resume = jz4740_i2s_resume,
397}; 427};
398EXPORT_SYMBOL_GPL(jz4740_i2s_dai);
399
400static void __devinit jz4740_i2c_init_pcm_config(struct jz4740_i2s *i2s)
401{
402 struct jz4740_dma_config *dma_config;
403
404 /* Playback */
405 dma_config = &i2s->pcm_config_playback.dma_config;
406 dma_config->src_width = JZ4740_DMA_WIDTH_32BIT,
407 dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
408 dma_config->request_type = JZ4740_DMA_TYPE_AIC_TRANSMIT;
409 dma_config->flags = JZ4740_DMA_SRC_AUTOINC;
410 dma_config->mode = JZ4740_DMA_MODE_SINGLE;
411 i2s->pcm_config_playback.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
412
413 /* Capture */
414 dma_config = &i2s->pcm_config_capture.dma_config;
415 dma_config->dst_width = JZ4740_DMA_WIDTH_32BIT,
416 dma_config->transfer_size = JZ4740_DMA_TRANSFER_SIZE_16BYTE;
417 dma_config->request_type = JZ4740_DMA_TYPE_AIC_RECEIVE;
418 dma_config->flags = JZ4740_DMA_DST_AUTOINC;
419 dma_config->mode = JZ4740_DMA_MODE_SINGLE;
420 i2s->pcm_config_capture.fifo_addr = i2s->phys_base + JZ_REG_AIC_FIFO;
421}
422 428
423static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev) 429static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
424{ 430{
@@ -463,24 +469,17 @@ static int __devinit jz4740_i2s_dev_probe(struct platform_device *pdev)
463 goto err_clk_put_aic; 469 goto err_clk_put_aic;
464 } 470 }
465 471
466 clk_enable(i2s->clk_aic); 472 platform_set_drvdata(pdev, i2s);
467 473 ret = snd_soc_register_dai(&pdev->dev, &jz4740_i2s_dai);
468 jz4740_i2c_init_pcm_config(i2s);
469
470 jz4740_i2s_dai.private_data = i2s;
471 ret = snd_soc_register_dai(&jz4740_i2s_dai);
472 474
473 if (ret) { 475 if (ret) {
474 dev_err(&pdev->dev, "Failed to register DAI\n"); 476 dev_err(&pdev->dev, "Failed to register DAI\n");
475 goto err_clk_put_i2s; 477 goto err_clk_put_i2s;
476 } 478 }
477 479
478 platform_set_drvdata(pdev, i2s);
479
480 return 0; 480 return 0;
481 481
482err_clk_put_i2s: 482err_clk_put_i2s:
483 clk_disable(i2s->clk_aic);
484 clk_put(i2s->clk_i2s); 483 clk_put(i2s->clk_i2s);
485err_clk_put_aic: 484err_clk_put_aic:
486 clk_put(i2s->clk_aic); 485 clk_put(i2s->clk_aic);
@@ -498,9 +497,8 @@ static int __devexit jz4740_i2s_dev_remove(struct platform_device *pdev)
498{ 497{
499 struct jz4740_i2s *i2s = platform_get_drvdata(pdev); 498 struct jz4740_i2s *i2s = platform_get_drvdata(pdev);
500 499
501 snd_soc_unregister_dai(&jz4740_i2s_dai); 500 snd_soc_unregister_dai(&pdev->dev);
502 501
503 clk_disable(i2s->clk_aic);
504 clk_put(i2s->clk_i2s); 502 clk_put(i2s->clk_i2s);
505 clk_put(i2s->clk_aic); 503 clk_put(i2s->clk_aic);
506 504
diff --git a/sound/soc/jz4740/jz4740-i2s.h b/sound/soc/jz4740/jz4740-i2s.h
index da22ed88a589..5e49339d8b93 100644
--- a/sound/soc/jz4740/jz4740-i2s.h
+++ b/sound/soc/jz4740/jz4740-i2s.h
@@ -13,6 +13,4 @@
13 13
14#define JZ4740_I2S_BIT_CLK 0 14#define JZ4740_I2S_BIT_CLK 0
15 15
16extern struct snd_soc_dai jz4740_i2s_dai;
17
18#endif 16#endif
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
index ee68d850c8dd..fb1483f7c966 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -109,7 +109,7 @@ static int jz4740_pcm_hw_params(struct snd_pcm_substream *substream,
109 struct snd_soc_pcm_runtime *rtd = substream->private_data; 109 struct snd_soc_pcm_runtime *rtd = substream->private_data;
110 struct jz4740_pcm_config *config; 110 struct jz4740_pcm_config *config;
111 111
112 config = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 112 config = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
113 113
114 if (!config) 114 if (!config)
115 return 0; 115 return 0;
@@ -310,14 +310,14 @@ int jz4740_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
310 if (!card->dev->coherent_dma_mask) 310 if (!card->dev->coherent_dma_mask)
311 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 311 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
312 312
313 if (dai->playback.channels_min) { 313 if (dai->driver->playback.channels_min) {
314 ret = jz4740_pcm_preallocate_dma_buffer(pcm, 314 ret = jz4740_pcm_preallocate_dma_buffer(pcm,
315 SNDRV_PCM_STREAM_PLAYBACK); 315 SNDRV_PCM_STREAM_PLAYBACK);
316 if (ret) 316 if (ret)
317 goto err; 317 goto err;
318 } 318 }
319 319
320 if (dai->capture.channels_min) { 320 if (dai->driver->capture.channels_min) {
321 ret = jz4740_pcm_preallocate_dma_buffer(pcm, 321 ret = jz4740_pcm_preallocate_dma_buffer(pcm,
322 SNDRV_PCM_STREAM_CAPTURE); 322 SNDRV_PCM_STREAM_CAPTURE);
323 if (ret) 323 if (ret)
@@ -328,22 +328,20 @@ err:
328 return ret; 328 return ret;
329} 329}
330 330
331struct snd_soc_platform jz4740_soc_platform = { 331static struct snd_soc_platform_driver jz4740_soc_platform = {
332 .name = "jz4740-pcm", 332 .ops = &jz4740_pcm_ops,
333 .pcm_ops = &jz4740_pcm_ops,
334 .pcm_new = jz4740_pcm_new, 333 .pcm_new = jz4740_pcm_new,
335 .pcm_free = jz4740_pcm_free, 334 .pcm_free = jz4740_pcm_free,
336}; 335};
337EXPORT_SYMBOL_GPL(jz4740_soc_platform);
338 336
339static int __devinit jz4740_pcm_probe(struct platform_device *pdev) 337static int __devinit jz4740_pcm_probe(struct platform_device *pdev)
340{ 338{
341 return snd_soc_register_platform(&jz4740_soc_platform); 339 return snd_soc_register_platform(&pdev->dev, &jz4740_soc_platform);
342} 340}
343 341
344static int __devexit jz4740_pcm_remove(struct platform_device *pdev) 342static int __devexit jz4740_pcm_remove(struct platform_device *pdev)
345{ 343{
346 snd_soc_unregister_platform(&jz4740_soc_platform); 344 snd_soc_unregister_platform(&pdev->dev);
347 return 0; 345 return 0;
348} 346}
349 347
@@ -351,7 +349,7 @@ static struct platform_driver jz4740_pcm_driver = {
351 .probe = jz4740_pcm_probe, 349 .probe = jz4740_pcm_probe,
352 .remove = __devexit_p(jz4740_pcm_remove), 350 .remove = __devexit_p(jz4740_pcm_remove),
353 .driver = { 351 .driver = {
354 .name = "jz4740-pcm", 352 .name = "jz4740-pcm-audio",
355 .owner = THIS_MODULE, 353 .owner = THIS_MODULE,
356 }, 354 },
357}; 355};
diff --git a/sound/soc/jz4740/jz4740-pcm.h b/sound/soc/jz4740/jz4740-pcm.h
index e3f221e2779c..1220cbb4382c 100644
--- a/sound/soc/jz4740/jz4740-pcm.h
+++ b/sound/soc/jz4740/jz4740-pcm.h
@@ -11,8 +11,6 @@
11#include <linux/dma-mapping.h> 11#include <linux/dma-mapping.h>
12#include <asm/mach-jz4740/dma.h> 12#include <asm/mach-jz4740/dma.h>
13 13
14/* platform data */
15extern struct snd_soc_platform jz4740_soc_platform;
16 14
17struct jz4740_pcm_config { 15struct jz4740_pcm_config {
18 struct jz4740_dma_config dma_config; 16 struct jz4740_dma_config dma_config;
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
index f15f4918f15f..ef1a99e6a3bd 100644
--- a/sound/soc/jz4740/qi_lb60.c
+++ b/sound/soc/jz4740/qi_lb60.c
@@ -22,11 +22,6 @@
22#include <sound/soc-dapm.h> 22#include <sound/soc-dapm.h>
23#include <linux/gpio.h> 23#include <linux/gpio.h>
24 24
25#include "../codecs/jz4740.h"
26#include "jz4740-pcm.h"
27#include "jz4740-i2s.h"
28
29
30#define QI_LB60_SND_GPIO JZ_GPIO_PORTB(29) 25#define QI_LB60_SND_GPIO JZ_GPIO_PORTB(29)
31#define QI_LB60_AMP_GPIO JZ_GPIO_PORTD(4) 26#define QI_LB60_AMP_GPIO JZ_GPIO_PORTD(4)
32 27
@@ -60,10 +55,11 @@ static const struct snd_soc_dapm_route qi_lb60_routes[] = {
60 SND_SOC_DAIFMT_NB_NF | \ 55 SND_SOC_DAIFMT_NB_NF | \
61 SND_SOC_DAIFMT_CBM_CFM) 56 SND_SOC_DAIFMT_CBM_CFM)
62 57
63static int qi_lb60_codec_init(struct snd_soc_codec *codec) 58static int qi_lb60_codec_init(struct snd_soc_pcm_runtime *rtd)
64{ 59{
60 struct snd_soc_codec *codec = rtd->codec;
61 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
65 int ret; 62 int ret;
66 struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;
67 63
68 snd_soc_dapm_nc_pin(codec, "LIN"); 64 snd_soc_dapm_nc_pin(codec, "LIN");
69 snd_soc_dapm_nc_pin(codec, "RIN"); 65 snd_soc_dapm_nc_pin(codec, "RIN");
@@ -84,8 +80,10 @@ static int qi_lb60_codec_init(struct snd_soc_codec *codec)
84static struct snd_soc_dai_link qi_lb60_dai = { 80static struct snd_soc_dai_link qi_lb60_dai = {
85 .name = "jz4740", 81 .name = "jz4740",
86 .stream_name = "jz4740", 82 .stream_name = "jz4740",
87 .cpu_dai = &jz4740_i2s_dai, 83 .cpu_dai_name = "jz4740-i2s",
88 .codec_dai = &jz4740_codec_dai, 84 .platform_name = "jz4740-pcm-audio",
85 .codec_dai_name = "jz4740-hifi",
86 .codec_name = "jz4740-codec",
89 .init = qi_lb60_codec_init, 87 .init = qi_lb60_codec_init,
90}; 88};
91 89
@@ -93,12 +91,6 @@ static struct snd_soc_card qi_lb60 = {
93 .name = "QI LB60", 91 .name = "QI LB60",
94 .dai_link = &qi_lb60_dai, 92 .dai_link = &qi_lb60_dai,
95 .num_links = 1, 93 .num_links = 1,
96 .platform = &jz4740_soc_platform,
97};
98
99static struct snd_soc_device qi_lb60_snd_devdata = {
100 .card = &qi_lb60,
101 .codec_dev = &soc_codec_dev_jz4740_codec,
102}; 94};
103 95
104static struct platform_device *qi_lb60_snd_device; 96static struct platform_device *qi_lb60_snd_device;
@@ -129,8 +121,7 @@ static int __init qi_lb60_init(void)
129 gpio_direction_output(QI_LB60_SND_GPIO, 0); 121 gpio_direction_output(QI_LB60_SND_GPIO, 0);
130 gpio_direction_output(QI_LB60_AMP_GPIO, 0); 122 gpio_direction_output(QI_LB60_AMP_GPIO, 0);
131 123
132 platform_set_drvdata(qi_lb60_snd_device, &qi_lb60_snd_devdata); 124 platform_set_drvdata(qi_lb60_snd_device, &qi_lb60);
133 qi_lb60_snd_devdata.dev = &qi_lb60_snd_device->dev;
134 125
135 ret = platform_device_add(qi_lb60_snd_device); 126 ret = platform_device_add(qi_lb60_snd_device);
136 if (ret) { 127 if (ret) {
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index a30205be3e2b..0fd6a630db01 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -2,6 +2,7 @@
2 * kirkwood-dma.c 2 * kirkwood-dma.c
3 * 3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com> 4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -18,7 +19,6 @@
18#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
19#include <linux/mbus.h> 20#include <linux/mbus.h>
20#include <sound/soc.h> 21#include <sound/soc.h>
21#include "kirkwood-dma.h"
22#include "kirkwood.h" 22#include "kirkwood.h"
23 23
24#define KIRKWOOD_RATES \ 24#define KIRKWOOD_RATES \
@@ -123,9 +123,10 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
123 int err; 123 int err;
124 struct snd_pcm_runtime *runtime = substream->runtime; 124 struct snd_pcm_runtime *runtime = substream->runtime;
125 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 125 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
126 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; 126 struct snd_soc_platform *platform = soc_runtime->platform;
127 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
127 struct kirkwood_dma_data *priv; 128 struct kirkwood_dma_data *priv;
128 struct kirkwood_dma_priv *prdata = cpu_dai->private_data; 129 struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
129 unsigned long addr; 130 unsigned long addr;
130 131
131 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 132 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
@@ -151,7 +152,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
151 if (err < 0) 152 if (err < 0)
152 return err; 153 return err;
153 154
154 if (soc_runtime->dai->cpu_dai->private_data == NULL) { 155 if (prdata == NULL) {
155 prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL); 156 prdata = kzalloc(sizeof(struct kirkwood_dma_priv), GFP_KERNEL);
156 if (prdata == NULL) 157 if (prdata == NULL)
157 return -ENOMEM; 158 return -ENOMEM;
@@ -165,7 +166,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
165 return -EBUSY; 166 return -EBUSY;
166 } 167 }
167 168
168 soc_runtime->dai->cpu_dai->private_data = prdata; 169 snd_soc_platform_set_drvdata(platform, prdata);
169 170
170 /* 171 /*
171 * Enable Error interrupts. We're only ack'ing them but 172 * Enable Error interrupts. We're only ack'ing them but
@@ -191,8 +192,9 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
191static int kirkwood_dma_close(struct snd_pcm_substream *substream) 192static int kirkwood_dma_close(struct snd_pcm_substream *substream)
192{ 193{
193 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 194 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
194 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; 195 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
195 struct kirkwood_dma_priv *prdata = cpu_dai->private_data; 196 struct snd_soc_platform *platform = soc_runtime->platform;
197 struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
196 struct kirkwood_dma_data *priv; 198 struct kirkwood_dma_data *priv;
197 199
198 priv = snd_soc_dai_get_dma_data(cpu_dai, substream); 200 priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
@@ -209,7 +211,7 @@ static int kirkwood_dma_close(struct snd_pcm_substream *substream)
209 writel(0, priv->io + KIRKWOOD_ERR_MASK); 211 writel(0, priv->io + KIRKWOOD_ERR_MASK);
210 free_irq(priv->irq, prdata); 212 free_irq(priv->irq, prdata);
211 kfree(prdata); 213 kfree(prdata);
212 soc_runtime->dai->cpu_dai->private_data = NULL; 214 snd_soc_platform_set_drvdata(platform, NULL);
213 } 215 }
214 216
215 return 0; 217 return 0;
@@ -236,7 +238,7 @@ static int kirkwood_dma_prepare(struct snd_pcm_substream *substream)
236{ 238{
237 struct snd_pcm_runtime *runtime = substream->runtime; 239 struct snd_pcm_runtime *runtime = substream->runtime;
238 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 240 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
239 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; 241 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
240 struct kirkwood_dma_data *priv; 242 struct kirkwood_dma_data *priv;
241 unsigned long size, count; 243 unsigned long size, count;
242 244
@@ -265,7 +267,7 @@ static snd_pcm_uframes_t kirkwood_dma_pointer(struct snd_pcm_substream
265 *substream) 267 *substream)
266{ 268{
267 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 269 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
268 struct snd_soc_dai *cpu_dai = soc_runtime->dai->cpu_dai; 270 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
269 struct kirkwood_dma_data *priv; 271 struct kirkwood_dma_data *priv;
270 snd_pcm_uframes_t count; 272 snd_pcm_uframes_t count;
271 273
@@ -320,14 +322,14 @@ static int kirkwood_dma_new(struct snd_card *card,
320 if (!card->dev->coherent_dma_mask) 322 if (!card->dev->coherent_dma_mask)
321 card->dev->coherent_dma_mask = 0xffffffff; 323 card->dev->coherent_dma_mask = 0xffffffff;
322 324
323 if (dai->playback.channels_min) { 325 if (dai->driver->playback.channels_min) {
324 ret = kirkwood_dma_preallocate_dma_buffer(pcm, 326 ret = kirkwood_dma_preallocate_dma_buffer(pcm,
325 SNDRV_PCM_STREAM_PLAYBACK); 327 SNDRV_PCM_STREAM_PLAYBACK);
326 if (ret) 328 if (ret)
327 return ret; 329 return ret;
328 } 330 }
329 331
330 if (dai->capture.channels_min) { 332 if (dai->driver->capture.channels_min) {
331 ret = kirkwood_dma_preallocate_dma_buffer(pcm, 333 ret = kirkwood_dma_preallocate_dma_buffer(pcm,
332 SNDRV_PCM_STREAM_CAPTURE); 334 SNDRV_PCM_STREAM_CAPTURE);
333 if (ret) 335 if (ret)
@@ -357,27 +359,46 @@ static void kirkwood_dma_free_dma_buffers(struct snd_pcm *pcm)
357 } 359 }
358} 360}
359 361
360struct snd_soc_platform kirkwood_soc_platform = { 362static struct snd_soc_platform_driver kirkwood_soc_platform = {
361 .name = "kirkwood-dma", 363 .ops = &kirkwood_dma_ops,
362 .pcm_ops = &kirkwood_dma_ops,
363 .pcm_new = kirkwood_dma_new, 364 .pcm_new = kirkwood_dma_new,
364 .pcm_free = kirkwood_dma_free_dma_buffers, 365 .pcm_free = kirkwood_dma_free_dma_buffers,
365}; 366};
366EXPORT_SYMBOL_GPL(kirkwood_soc_platform);
367 367
368static int __init kirkwood_soc_platform_init(void) 368static int __devinit kirkwood_soc_platform_probe(struct platform_device *pdev)
369{ 369{
370 return snd_soc_register_platform(&kirkwood_soc_platform); 370 return snd_soc_register_platform(&pdev->dev, &kirkwood_soc_platform);
371} 371}
372module_init(kirkwood_soc_platform_init);
373 372
374static void __exit kirkwood_soc_platform_exit(void) 373static int __devexit kirkwood_soc_platform_remove(struct platform_device *pdev)
375{ 374{
376 snd_soc_unregister_platform(&kirkwood_soc_platform); 375 snd_soc_unregister_platform(&pdev->dev);
376 return 0;
377} 377}
378module_exit(kirkwood_soc_platform_exit);
379 378
380MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>"); 379static struct platform_driver kirkwood_pcm_driver = {
380 .driver = {
381 .name = "kirkwood-pcm-audio",
382 .owner = THIS_MODULE,
383 },
384
385 .probe = kirkwood_soc_platform_probe,
386 .remove = __devexit_p(kirkwood_soc_platform_remove),
387};
388
389static int __init kirkwood_pcm_init(void)
390{
391 return platform_driver_register(&kirkwood_pcm_driver);
392}
393module_init(kirkwood_pcm_init);
394
395static void __exit kirkwood_pcm_exit(void)
396{
397 platform_driver_unregister(&kirkwood_pcm_driver);
398}
399module_exit(kirkwood_pcm_exit);
400
401MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
381MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module"); 402MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module");
382MODULE_LICENSE("GPL"); 403MODULE_LICENSE("GPL");
383 404MODULE_ALIAS("platform:kirkwood-pcm-audio");
diff --git a/sound/soc/kirkwood/kirkwood-dma.h b/sound/soc/kirkwood/kirkwood-dma.h
deleted file mode 100644
index ba4454cd34f1..000000000000
--- a/sound/soc/kirkwood/kirkwood-dma.h
+++ /dev/null
@@ -1,17 +0,0 @@
1/*
2 * kirkwood-dma.h
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#ifndef _KIRKWOOD_DMA_H
13#define _KIRKWOOD_DMA_H
14
15extern struct snd_soc_platform kirkwood_soc_platform;
16
17#endif
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 981ffc2a13c8..a33fc51f363b 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -2,6 +2,7 @@
2 * kirkwood-i2s.c 2 * kirkwood-i2s.c
3 * 3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com> 4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -20,7 +21,6 @@
20#include <sound/pcm_params.h> 21#include <sound/pcm_params.h>
21#include <sound/soc.h> 22#include <sound/soc.h>
22#include <plat/audio.h> 23#include <plat/audio.h>
23#include "kirkwood-i2s.h"
24#include "kirkwood.h" 24#include "kirkwood.h"
25 25
26#define DRV_NAME "kirkwood-i2s" 26#define DRV_NAME "kirkwood-i2s"
@@ -33,13 +33,10 @@
33 SNDRV_PCM_FMTBIT_S24_LE | \ 33 SNDRV_PCM_FMTBIT_S24_LE | \
34 SNDRV_PCM_FMTBIT_S32_LE) 34 SNDRV_PCM_FMTBIT_S32_LE)
35 35
36
37struct snd_soc_dai kirkwood_i2s_dai;
38static struct kirkwood_dma_data *priv;
39
40static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai, 36static int kirkwood_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
41 unsigned int fmt) 37 unsigned int fmt)
42{ 38{
39 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(cpu_dai);
43 unsigned long mask; 40 unsigned long mask;
44 unsigned long value; 41 unsigned long value;
45 42
@@ -101,10 +98,20 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
101 } while (value == 0); 98 } while (value == 0);
102} 99}
103 100
101static int kirkwood_i2s_startup(struct snd_pcm_substream *substream,
102 struct snd_soc_dai *dai)
103{
104 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
105
106 snd_soc_dai_set_dma_data(dai, substream, priv);
107 return 0;
108}
109
104static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream, 110static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
105 struct snd_pcm_hw_params *params, 111 struct snd_pcm_hw_params *params,
106 struct snd_soc_dai *dai) 112 struct snd_soc_dai *dai)
107{ 113{
114 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
108 unsigned int i2s_reg, reg; 115 unsigned int i2s_reg, reg;
109 unsigned long i2s_value, value; 116 unsigned long i2s_value, value;
110 117
@@ -171,6 +178,7 @@ static int kirkwood_i2s_hw_params(struct snd_pcm_substream *substream,
171static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream, 178static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
172 int cmd, struct snd_soc_dai *dai) 179 int cmd, struct snd_soc_dai *dai)
173{ 180{
181 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
174 unsigned long value; 182 unsigned long value;
175 183
176 /* 184 /*
@@ -244,6 +252,7 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
244static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream, 252static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
245 int cmd, struct snd_soc_dai *dai) 253 int cmd, struct snd_soc_dai *dai)
246{ 254{
255 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
247 unsigned long value; 256 unsigned long value;
248 257
249 value = readl(priv->io + KIRKWOOD_RECCTL); 258 value = readl(priv->io + KIRKWOOD_RECCTL);
@@ -323,9 +332,9 @@ static int kirkwood_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
323 return 0; 332 return 0;
324} 333}
325 334
326static int kirkwood_i2s_probe(struct platform_device *pdev, 335static int kirkwood_i2s_probe(struct snd_soc_dai *dai)
327 struct snd_soc_dai *dai)
328{ 336{
337 struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
329 unsigned long value; 338 unsigned long value;
330 unsigned int reg_data; 339 unsigned int reg_data;
331 340
@@ -359,21 +368,20 @@ static int kirkwood_i2s_probe(struct platform_device *pdev,
359 368
360} 369}
361 370
362static void kirkwood_i2s_remove(struct platform_device *pdev, 371static int kirkwood_i2s_remove(struct snd_soc_dai *dai)
363 struct snd_soc_dai *dai)
364{ 372{
373 return 0;
365} 374}
366 375
367static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = { 376static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
377 .startup = kirkwood_i2s_startup,
368 .trigger = kirkwood_i2s_trigger, 378 .trigger = kirkwood_i2s_trigger,
369 .hw_params = kirkwood_i2s_hw_params, 379 .hw_params = kirkwood_i2s_hw_params,
370 .set_fmt = kirkwood_i2s_set_fmt, 380 .set_fmt = kirkwood_i2s_set_fmt,
371}; 381};
372 382
373 383
374struct snd_soc_dai kirkwood_i2s_dai = { 384static struct snd_soc_dai_driver kirkwood_i2s_dai = {
375 .name = DRV_NAME,
376 .id = 0,
377 .probe = kirkwood_i2s_probe, 385 .probe = kirkwood_i2s_probe,
378 .remove = kirkwood_i2s_remove, 386 .remove = kirkwood_i2s_remove,
379 .playback = { 387 .playback = {
@@ -388,13 +396,13 @@ struct snd_soc_dai kirkwood_i2s_dai = {
388 .formats = KIRKWOOD_I2S_FORMATS,}, 396 .formats = KIRKWOOD_I2S_FORMATS,},
389 .ops = &kirkwood_i2s_dai_ops, 397 .ops = &kirkwood_i2s_dai_ops,
390}; 398};
391EXPORT_SYMBOL_GPL(kirkwood_i2s_dai);
392 399
393static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev) 400static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
394{ 401{
395 struct resource *mem; 402 struct resource *mem;
396 struct kirkwood_asoc_platform_data *data = 403 struct kirkwood_asoc_platform_data *data =
397 pdev->dev.platform_data; 404 pdev->dev.platform_data;
405 struct kirkwood_dma_data *priv;
398 int err; 406 int err;
399 407
400 priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL); 408 priv = kzalloc(sizeof(struct kirkwood_dma_data), GFP_KERNEL);
@@ -403,6 +411,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
403 err = -ENOMEM; 411 err = -ENOMEM;
404 goto error; 412 goto error;
405 } 413 }
414 dev_set_drvdata(&pdev->dev, priv);
406 415
407 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 416 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
408 if (!mem) { 417 if (!mem) {
@@ -441,10 +450,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
441 priv->dram = data->dram; 450 priv->dram = data->dram;
442 priv->burst = data->burst; 451 priv->burst = data->burst;
443 452
444 kirkwood_i2s_dai.capture.dma_data = priv; 453 return snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai);
445 kirkwood_i2s_dai.playback.dma_data = priv;
446
447 return snd_soc_register_dai(&kirkwood_i2s_dai);
448 454
449err_ioremap: 455err_ioremap:
450 iounmap(priv->io); 456 iounmap(priv->io);
@@ -458,12 +464,13 @@ error:
458 464
459static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev) 465static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
460{ 466{
461 if (priv) { 467 struct kirkwood_dma_data *priv = dev_get_drvdata(&pdev->dev);
462 iounmap(priv->io); 468
463 release_mem_region(priv->mem->start, SZ_16K); 469 snd_soc_unregister_dai(&pdev->dev);
464 kfree(priv); 470 iounmap(priv->io);
465 } 471 release_mem_region(priv->mem->start, SZ_16K);
466 snd_soc_unregister_dai(&kirkwood_i2s_dai); 472 kfree(priv);
473
467 return 0; 474 return 0;
468} 475}
469 476
@@ -489,7 +496,7 @@ static void __exit kirkwood_i2s_exit(void)
489module_exit(kirkwood_i2s_exit); 496module_exit(kirkwood_i2s_exit);
490 497
491/* Module information */ 498/* Module information */
492MODULE_AUTHOR("Arnaud Patard, <apatard@mandriva.com>"); 499MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
493MODULE_DESCRIPTION("Kirkwood I2S SoC Interface"); 500MODULE_DESCRIPTION("Kirkwood I2S SoC Interface");
494MODULE_LICENSE("GPL"); 501MODULE_LICENSE("GPL");
495MODULE_ALIAS("platform:kirkwood-i2s"); 502MODULE_ALIAS("platform:kirkwood-i2s");
diff --git a/sound/soc/kirkwood/kirkwood-i2s.h b/sound/soc/kirkwood/kirkwood-i2s.h
deleted file mode 100644
index c5595c616d7a..000000000000
--- a/sound/soc/kirkwood/kirkwood-i2s.h
+++ /dev/null
@@ -1,17 +0,0 @@
1/*
2 * kirkwood-i2s.h
3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#ifndef _KIRKWOOD_I2S_H
13#define _KIRKWOOD_I2S_H
14
15extern struct snd_soc_dai kirkwood_i2s_dai;
16
17#endif
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index 0353d06bc41a..9d7c81e921f1 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -2,6 +2,7 @@
2 * kirkwood-openrd.c 2 * kirkwood-openrd.c
3 * 3 *
4 * (c) 2010 Arnaud Patard <apatard@mandriva.com> 4 * (c) 2010 Arnaud Patard <apatard@mandriva.com>
5 * (c) 2010 Arnaud Patard <arnaud.patard@rtp-net.org>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the 8 * under the terms of the GNU General Public License as published by the
@@ -18,16 +19,14 @@
18#include <mach/kirkwood.h> 19#include <mach/kirkwood.h>
19#include <plat/audio.h> 20#include <plat/audio.h>
20#include <asm/mach-types.h> 21#include <asm/mach-types.h>
21#include "kirkwood-i2s.h"
22#include "kirkwood-dma.h"
23#include "../codecs/cs42l51.h" 22#include "../codecs/cs42l51.h"
24 23
25static int openrd_client_hw_params(struct snd_pcm_substream *substream, 24static int openrd_client_hw_params(struct snd_pcm_substream *substream,
26 struct snd_pcm_hw_params *params) 25 struct snd_pcm_hw_params *params)
27{ 26{
28 struct snd_soc_pcm_runtime *rtd = substream->private_data; 27 struct snd_soc_pcm_runtime *rtd = substream->private_data;
29 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 28 struct snd_soc_dai *codec_dai = rtd->codec_dai;
30 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 29 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
31 int ret; 30 int ret;
32 unsigned int freq, fmt; 31 unsigned int freq, fmt;
33 32
@@ -66,8 +65,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
66{ 65{
67 .name = "CS42L51", 66 .name = "CS42L51",
68 .stream_name = "CS42L51 HiFi", 67 .stream_name = "CS42L51 HiFi",
69 .cpu_dai = &kirkwood_i2s_dai, 68 .cpu_dai_name = "kirkwood-i2s",
70 .codec_dai = &cs42l51_dai, 69 .platform_name = "kirkwood-pcm-audio",
70 .codec_dai_name = "cs42l51-hifi",
71 .codec_name = "cs42l51-codec.0-004a",
71 .ops = &openrd_client_ops, 72 .ops = &openrd_client_ops,
72}, 73},
73}; 74};
@@ -75,16 +76,10 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
75 76
76static struct snd_soc_card openrd_client = { 77static struct snd_soc_card openrd_client = {
77 .name = "OpenRD Client", 78 .name = "OpenRD Client",
78 .platform = &kirkwood_soc_platform,
79 .dai_link = openrd_client_dai, 79 .dai_link = openrd_client_dai,
80 .num_links = ARRAY_SIZE(openrd_client_dai), 80 .num_links = ARRAY_SIZE(openrd_client_dai),
81}; 81};
82 82
83static struct snd_soc_device openrd_client_snd_devdata = {
84 .card = &openrd_client,
85 .codec_dev = &soc_codec_device_cs42l51,
86};
87
88static struct platform_device *openrd_client_snd_device; 83static struct platform_device *openrd_client_snd_device;
89 84
90static int __init openrd_client_init(void) 85static int __init openrd_client_init(void)
@@ -99,8 +94,7 @@ static int __init openrd_client_init(void)
99 return -ENOMEM; 94 return -ENOMEM;
100 95
101 platform_set_drvdata(openrd_client_snd_device, 96 platform_set_drvdata(openrd_client_snd_device,
102 &openrd_client_snd_devdata); 97 &openrd_client);
103 openrd_client_snd_devdata.dev = &openrd_client_snd_device->dev;
104 98
105 ret = platform_device_add(openrd_client_snd_device); 99 ret = platform_device_add(openrd_client_snd_device);
106 if (ret) { 100 if (ret) {
@@ -120,7 +114,7 @@ module_init(openrd_client_init);
120module_exit(openrd_client_exit); 114module_exit(openrd_client_exit);
121 115
122/* Module information */ 116/* Module information */
123MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>"); 117MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
124MODULE_DESCRIPTION("ALSA SoC OpenRD Client"); 118MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
125MODULE_LICENSE("GPL"); 119MODULE_LICENSE("GPL");
126MODULE_ALIAS("platform:soc-audio"); 120MODULE_ALIAS("platform:soc-audio");
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index caa7c901bc2e..293dc748797c 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -20,7 +20,6 @@
20#include <sound/pcm.h> 20#include <sound/pcm.h>
21#include <sound/initval.h> 21#include <sound/initval.h>
22#include <sound/soc.h> 22#include <sound/soc.h>
23#include <linux/device.h>
24#include <linux/clk.h> 23#include <linux/clk.h>
25 24
26#include <mach/mfp.h> 25#include <mach/mfp.h>
@@ -297,8 +296,7 @@ static struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
297 .trigger = nuc900_ac97_trigger, 296 .trigger = nuc900_ac97_trigger,
298}; 297};
299 298
300struct snd_soc_dai nuc900_ac97_dai = { 299static struct snd_soc_dai_driver nuc900_ac97_dai = {
301 .name = "nuc900-ac97",
302 .probe = nuc900_ac97_probe, 300 .probe = nuc900_ac97_probe,
303 .remove = nuc900_ac97_remove, 301 .remove = nuc900_ac97_remove,
304 .ac97_control = 1, 302 .ac97_control = 1,
@@ -316,7 +314,6 @@ struct snd_soc_dai nuc900_ac97_dai = {
316 }, 314 },
317 .ops = &nuc900_ac97_dai_ops, 315 .ops = &nuc900_ac97_dai_ops,
318} 316}
319EXPORT_SYMBOL_GPL(nuc900_ac97_dai);
320 317
321static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev) 318static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
322{ 319{
@@ -365,9 +362,7 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
365 362
366 nuc900_ac97_data = nuc900_audio; 363 nuc900_ac97_data = nuc900_audio;
367 364
368 nuc900_audio->dev = nuc900_ac97_dai.dev = &pdev->dev; 365 ret = snd_soc_register_dai(&pdev->dev, &nuc900_ac97_dai);
369
370 ret = snd_soc_register_dai(&nuc900_ac97_dai);
371 if (ret) 366 if (ret)
372 goto out3; 367 goto out3;
373 368
@@ -390,7 +385,7 @@ out0:
390static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev) 385static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
391{ 386{
392 387
393 snd_soc_unregister_dai(&nuc900_ac97_dai); 388 snd_soc_unregister_dai(&pdev->dev);
394 389
395 clk_put(nuc900_ac97_data->clk); 390 clk_put(nuc900_ac97_data->clk);
396 iounmap(nuc900_ac97_data->mmio); 391 iounmap(nuc900_ac97_data->mmio);
@@ -404,7 +399,7 @@ static int __devexit nuc900_ac97_drvremove(struct platform_device *pdev)
404 399
405static struct platform_driver nuc900_ac97_driver = { 400static struct platform_driver nuc900_ac97_driver = {
406 .driver = { 401 .driver = {
407 .name = "nuc900-audio", 402 .name = "nuc900-ac97",
408 .owner = THIS_MODULE, 403 .owner = THIS_MODULE,
409 }, 404 },
410 .probe = nuc900_ac97_drvprobe, 405 .probe = nuc900_ac97_drvprobe,
diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c
index 72e6f518f7b2..161f5b667d7b 100644
--- a/sound/soc/nuc900/nuc900-audio.c
+++ b/sound/soc/nuc900/nuc900-audio.c
@@ -20,26 +20,21 @@
20#include <sound/soc.h> 20#include <sound/soc.h>
21#include <sound/soc-dapm.h> 21#include <sound/soc-dapm.h>
22 22
23#include "../codecs/ac97.h"
24#include "nuc900-audio.h" 23#include "nuc900-audio.h"
25 24
26static struct snd_soc_dai_link nuc900evb_ac97_dai = { 25static struct snd_soc_dai_link nuc900evb_ac97_dai = {
27 .name = "AC97", 26 .name = "AC97",
28 .stream_name = "AC97 HiFi", 27 .stream_name = "AC97 HiFi",
29 .cpu_dai = &nuc900_ac97_dai, 28 .cpu_dai_name = "nuc900-ac97",
30 .codec_dai = &ac97_dai, 29 .codec_dai_name = "ac97-hifi",
30 .codec_name = "ac97-codec",
31 .platform_name = "nuc900-pcm-audio",
31}; 32};
32 33
33static struct snd_soc_card nuc900evb_audio_machine = { 34static struct snd_soc_card nuc900evb_audio_machine = {
34 .name = "NUC900EVB_AC97", 35 .name = "NUC900EVB_AC97",
35 .dai_link = &nuc900evb_ac97_dai, 36 .dai_link = &nuc900evb_ac97_dai,
36 .num_links = 1, 37 .num_links = 1,
37 .platform = &nuc900_soc_platform,
38};
39
40static struct snd_soc_device nuc900evb_ac97_devdata = {
41 .card = &nuc900evb_audio_machine,
42 .codec_dev = &soc_codec_dev_ac97,
43}; 38};
44 39
45static struct platform_device *nuc900evb_asoc_dev; 40static struct platform_device *nuc900evb_asoc_dev;
@@ -54,9 +49,8 @@ static int __init nuc900evb_audio_init(void)
54 goto out; 49 goto out;
55 50
56 /* nuc900 board audio device */ 51 /* nuc900 board audio device */
57 platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_ac97_devdata); 52 platform_set_drvdata(nuc900evb_asoc_dev, &nuc900evb_audio_machine);
58 53
59 nuc900evb_ac97_devdata.dev = &nuc900evb_asoc_dev->dev;
60 ret = platform_device_add(nuc900evb_asoc_dev); 54 ret = platform_device_add(nuc900evb_asoc_dev);
61 55
62 if (ret) { 56 if (ret) {
diff --git a/sound/soc/nuc900/nuc900-audio.h b/sound/soc/nuc900/nuc900-audio.h
index 3038f519729f..aeed8ead2b2b 100644
--- a/sound/soc/nuc900/nuc900-audio.h
+++ b/sound/soc/nuc900/nuc900-audio.h
@@ -110,8 +110,4 @@ struct nuc900_audio {
110 110
111}; 111};
112 112
113extern struct nuc900_audio *nuc900_ac97_data;
114extern struct snd_soc_dai nuc900_ac97_dai;
115extern struct snd_soc_platform nuc900_soc_platform;
116
117#endif /*end _NUC900_AUDIO_H */ 113#endif /*end _NUC900_AUDIO_H */
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
index e81e803b3a63..195d1ac94771 100644
--- a/sound/soc/nuc900/nuc900-pcm.c
+++ b/sound/soc/nuc900/nuc900-pcm.c
@@ -328,26 +328,44 @@ static int nuc900_dma_new(struct snd_card *card,
328 return 0; 328 return 0;
329} 329}
330 330
331struct snd_soc_platform nuc900_soc_platform = { 331static struct snd_soc_platform_driver nuc900_soc_platform = {
332 .name = "nuc900-dma", 332 .ops = &nuc900_dma_ops,
333 .pcm_ops = &nuc900_dma_ops,
334 .pcm_new = nuc900_dma_new, 333 .pcm_new = nuc900_dma_new,
335 .pcm_free = nuc900_dma_free_dma_buffers, 334 .pcm_free = nuc900_dma_free_dma_buffers,
336} 335}
337EXPORT_SYMBOL_GPL(nuc900_soc_platform);
338 336
339static int __init nuc900_soc_platform_init(void) 337static int __devinit nuc900_soc_platform_probe(struct platform_device *pdev)
340{ 338{
341 return snd_soc_register_platform(&nuc900_soc_platform); 339 return snd_soc_register_platform(&pdev->dev, &nuc900_soc_platform);
342} 340}
343 341
344static void __exit nuc900_soc_platform_exit(void) 342static int __devexit nuc900_soc_platform_remove(struct platform_device *pdev)
345{ 343{
346 snd_soc_unregister_platform(&nuc900_soc_platform); 344 snd_soc_unregister_platform(&pdev->dev);
345 return 0;
347} 346}
348 347
349module_init(nuc900_soc_platform_init); 348static struct platform_driver nuc900_pcm_driver = {
350module_exit(nuc900_soc_platform_exit); 349 .driver = {
350 .name = "nuc900-pcm-audio",
351 .owner = THIS_MODULE,
352 },
353
354 .probe = nuc900_soc_platform_probe,
355 .remove = __devexit_p(nuc900_soc_platform_remove),
356};
357
358static int __init nuc900_pcm_init(void)
359{
360 return platform_driver_register(&nuc900_pcm_driver);
361}
362module_init(nuc900_pcm_init);
363
364static void __exit nuc900_pcm_exit(void)
365{
366 platform_driver_unregister(&nuc900_pcm_driver);
367}
368module_exit(nuc900_pcm_exit);
351 369
352MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>"); 370MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>");
353MODULE_DESCRIPTION("nuc900 Audio DMA module"); 371MODULE_DESCRIPTION("nuc900 Audio DMA module");
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index 135901b2ea11..979dd508305f 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -40,8 +40,8 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,
40 struct snd_pcm_hw_params *params) 40 struct snd_pcm_hw_params *params)
41{ 41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data; 42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 43 struct snd_soc_dai *codec_dai = rtd->codec_dai;
44 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 44 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
45 int ret; 45 int ret;
46 46
47 /* Set codec DAI configuration */ 47 /* Set codec DAI configuration */
@@ -111,8 +111,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
111 {"MICIN", NULL, "Mic In"}, 111 {"MICIN", NULL, "Mic In"},
112}; 112};
113 113
114static int am3517evm_aic23_init(struct snd_soc_codec *codec) 114static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd)
115{ 115{
116 struct snd_soc_codec *codec = rtd->codec;
117
116 /* Add am3517-evm specific widgets */ 118 /* Add am3517-evm specific widgets */
117 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, 119 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
118 ARRAY_SIZE(tlv320aic23_dapm_widgets)); 120 ARRAY_SIZE(tlv320aic23_dapm_widgets));
@@ -134,8 +136,10 @@ static int am3517evm_aic23_init(struct snd_soc_codec *codec)
134static struct snd_soc_dai_link am3517evm_dai = { 136static struct snd_soc_dai_link am3517evm_dai = {
135 .name = "TLV320AIC23", 137 .name = "TLV320AIC23",
136 .stream_name = "AIC23", 138 .stream_name = "AIC23",
137 .cpu_dai = &omap_mcbsp_dai[0], 139 .cpu_dai_name ="omap-mcbsp-dai.0",
138 .codec_dai = &tlv320aic23_dai, 140 .codec_dai_name = "tlv320aic23-hifi",
141 .platform_name = "omap-pcm-audio",
142 .codec_name = "tlv320aic23-codec",
139 .init = am3517evm_aic23_init, 143 .init = am3517evm_aic23_init,
140 .ops = &am3517evm_ops, 144 .ops = &am3517evm_ops,
141}; 145};
@@ -143,27 +147,18 @@ static struct snd_soc_dai_link am3517evm_dai = {
143/* Audio machine driver */ 147/* Audio machine driver */
144static struct snd_soc_card snd_soc_am3517evm = { 148static struct snd_soc_card snd_soc_am3517evm = {
145 .name = "am3517evm", 149 .name = "am3517evm",
146 .platform = &omap_soc_platform,
147 .dai_link = &am3517evm_dai, 150 .dai_link = &am3517evm_dai,
148 .num_links = 1, 151 .num_links = 1,
149}; 152};
150 153
151/* Audio subsystem */
152static struct snd_soc_device am3517evm_snd_devdata = {
153 .card = &snd_soc_am3517evm,
154 .codec_dev = &soc_codec_dev_tlv320aic23,
155};
156
157static struct platform_device *am3517evm_snd_device; 154static struct platform_device *am3517evm_snd_device;
158 155
159static int __init am3517evm_soc_init(void) 156static int __init am3517evm_soc_init(void)
160{ 157{
161 int ret; 158 int ret;
162 159
163 if (!machine_is_omap3517evm()) { 160 if (!machine_is_omap3517evm())
164 pr_err("Not OMAP3517 / AM3517 EVM!\n");
165 return -ENODEV; 161 return -ENODEV;
166 }
167 pr_info("OMAP3517 / AM3517 EVM SoC init\n"); 162 pr_info("OMAP3517 / AM3517 EVM SoC init\n");
168 163
169 am3517evm_snd_device = platform_device_alloc("soc-audio", -1); 164 am3517evm_snd_device = platform_device_alloc("soc-audio", -1);
@@ -172,9 +167,7 @@ static int __init am3517evm_soc_init(void)
172 return -ENOMEM; 167 return -ENOMEM;
173 } 168 }
174 169
175 platform_set_drvdata(am3517evm_snd_device, &am3517evm_snd_devdata); 170 platform_set_drvdata(am3517evm_snd_device, &snd_soc_am3517evm);
176 am3517evm_snd_devdata.dev = &am3517evm_snd_device->dev;
177 *(unsigned int *)am3517evm_dai.cpu_dai->private_data = 0; /* McBSP1 */
178 171
179 ret = platform_device_add(am3517evm_snd_device); 172 ret = platform_device_add(am3517evm_snd_device);
180 if (ret) 173 if (ret)
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index b0f618e44840..438146addbb8 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -99,7 +99,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
99 int pin, changed = 0; 99 int pin, changed = 0;
100 100
101 /* Refuse any mode changes if we are not able to control the codec. */ 101 /* Refuse any mode changes if we are not able to control the codec. */
102 if (!codec->control_data) 102 if (!codec->hw_write)
103 return -EUNATCH; 103 return -EUNATCH;
104 104
105 if (ucontrol->value.enumerated.item[0] >= control->max) 105 if (ucontrol->value.enumerated.item[0] >= control->max)
@@ -268,10 +268,32 @@ static void cx81801_timeout(unsigned long data)
268 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); 268 ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
269} 269}
270 270
271/*
272 * Used for passing a codec structure pointer
273 * from the board initialization code to the tty line discipline.
274 */
275static struct snd_soc_codec *cx20442_codec;
276
271/* Line discipline .open() */ 277/* Line discipline .open() */
272static int cx81801_open(struct tty_struct *tty) 278static int cx81801_open(struct tty_struct *tty)
273{ 279{
274 return v253_ops.open(tty); 280 int ret;
281
282 if (!cx20442_codec)
283 return -ENODEV;
284
285 /*
286 * Pass the codec structure pointer for use by other ldisc callbacks,
287 * both the card and the codec specific parts.
288 */
289 tty->disc_data = cx20442_codec;
290
291 ret = v253_ops.open(tty);
292
293 if (ret < 0)
294 tty->disc_data = NULL;
295
296 return ret;
275} 297}
276 298
277/* Line discipline .close() */ 299/* Line discipline .close() */
@@ -281,11 +303,14 @@ static void cx81801_close(struct tty_struct *tty)
281 303
282 del_timer_sync(&cx81801_timer); 304 del_timer_sync(&cx81801_timer);
283 305
284 v253_ops.close(tty);
285
286 /* Prevent the hook switch from further changing the DAPM pins */ 306 /* Prevent the hook switch from further changing the DAPM pins */
287 INIT_LIST_HEAD(&ams_delta_hook_switch.pins); 307 INIT_LIST_HEAD(&ams_delta_hook_switch.pins);
288 308
309 if (!codec)
310 return;
311
312 v253_ops.close(tty);
313
289 /* Revert back to default audio input/output constellation */ 314 /* Revert back to default audio input/output constellation */
290 snd_soc_dapm_disable_pin(codec, "Mouthpiece"); 315 snd_soc_dapm_disable_pin(codec, "Mouthpiece");
291 snd_soc_dapm_enable_pin(codec, "Earpiece"); 316 snd_soc_dapm_enable_pin(codec, "Earpiece");
@@ -310,7 +335,10 @@ static void cx81801_receive(struct tty_struct *tty,
310 const unsigned char *c; 335 const unsigned char *c;
311 int apply, ret; 336 int apply, ret;
312 337
313 if (!codec->control_data) { 338 if (!codec)
339 return;
340
341 if (!codec->hw_write) {
314 /* First modem response, complete setup procedure */ 342 /* First modem response, complete setup procedure */
315 343
316 /* Initialize timer used for config pulse generation */ 344 /* Initialize timer used for config pulse generation */
@@ -323,7 +351,7 @@ static void cx81801_receive(struct tty_struct *tty,
323 ARRAY_SIZE(ams_delta_hook_switch_pins), 351 ARRAY_SIZE(ams_delta_hook_switch_pins),
324 ams_delta_hook_switch_pins); 352 ams_delta_hook_switch_pins);
325 if (ret) 353 if (ret)
326 dev_warn(codec->socdev->card->dev, 354 dev_warn(codec->dev,
327 "Failed to link hook switch to DAPM pins, " 355 "Failed to link hook switch to DAPM pins, "
328 "will continue with hook switch unlinked.\n"); 356 "will continue with hook switch unlinked.\n");
329 357
@@ -383,7 +411,7 @@ static int ams_delta_hw_params(struct snd_pcm_substream *substream,
383 struct snd_soc_pcm_runtime *rtd = substream->private_data; 411 struct snd_soc_pcm_runtime *rtd = substream->private_data;
384 412
385 /* Set cpu DAI configuration */ 413 /* Set cpu DAI configuration */
386 return snd_soc_dai_set_fmt(rtd->dai->cpu_dai, 414 return snd_soc_dai_set_fmt(rtd->cpu_dai,
387 SND_SOC_DAIFMT_DSP_A | 415 SND_SOC_DAIFMT_DSP_A |
388 SND_SOC_DAIFMT_NB_NF | 416 SND_SOC_DAIFMT_NB_NF |
389 SND_SOC_DAIFMT_CBM_CFM); 417 SND_SOC_DAIFMT_CBM_CFM);
@@ -398,7 +426,7 @@ static struct snd_soc_ops ams_delta_ops = {
398static int ams_delta_set_bias_level(struct snd_soc_card *card, 426static int ams_delta_set_bias_level(struct snd_soc_card *card,
399 enum snd_soc_bias_level level) 427 enum snd_soc_bias_level level)
400{ 428{
401 struct snd_soc_codec *codec = card->codec; 429 struct snd_soc_codec *codec = card->rtd->codec;
402 430
403 switch (level) { 431 switch (level) {
404 case SND_SOC_BIAS_ON: 432 case SND_SOC_BIAS_ON:
@@ -461,18 +489,22 @@ static void ams_delta_shutdown(struct snd_pcm_substream *substream)
461 * Card initialization 489 * Card initialization
462 */ 490 */
463 491
464static int ams_delta_cx20442_init(struct snd_soc_codec *codec) 492static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
465{ 493{
466 struct snd_soc_dai *codec_dai = codec->dai; 494 struct snd_soc_codec *codec = rtd->codec;
467 struct snd_soc_card *card = codec->socdev->card; 495 struct snd_soc_dai *codec_dai = rtd->codec_dai;
496 struct snd_soc_card *card = rtd->card;
468 int ret; 497 int ret;
469 /* Codec is ready, now add/activate board specific controls */ 498 /* Codec is ready, now add/activate board specific controls */
470 499
500 /* Store a pointer to the codec structure for tty ldisc use */
501 cx20442_codec = codec;
502
471 /* Set up digital mute if not provided by the codec */ 503 /* Set up digital mute if not provided by the codec */
472 if (!codec_dai->ops) { 504 if (!codec_dai->driver->ops) {
473 codec_dai->ops = &ams_delta_dai_ops; 505 codec_dai->driver->ops = &ams_delta_dai_ops;
474 } else if (!codec_dai->ops->digital_mute) { 506 } else if (!codec_dai->driver->ops->digital_mute) {
475 codec_dai->ops->digital_mute = ams_delta_digital_mute; 507 codec_dai->driver->ops->digital_mute = ams_delta_digital_mute;
476 } else { 508 } else {
477 ams_delta_ops.startup = ams_delta_startup; 509 ams_delta_ops.startup = ams_delta_startup;
478 ams_delta_ops.shutdown = ams_delta_shutdown; 510 ams_delta_ops.shutdown = ams_delta_shutdown;
@@ -483,7 +515,7 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec)
483 515
484 /* Add hook switch - can be used to control the codec from userspace 516 /* Add hook switch - can be used to control the codec from userspace
485 * even if line discipline fails */ 517 * even if line discipline fails */
486 ret = snd_soc_jack_new(card, "hook_switch", 518 ret = snd_soc_jack_new(rtd->codec, "hook_switch",
487 SND_JACK_HEADSET, &ams_delta_hook_switch); 519 SND_JACK_HEADSET, &ams_delta_hook_switch);
488 if (ret) 520 if (ret)
489 dev_warn(card->dev, 521 dev_warn(card->dev,
@@ -551,27 +583,22 @@ static int ams_delta_cx20442_init(struct snd_soc_codec *codec)
551static struct snd_soc_dai_link ams_delta_dai_link = { 583static struct snd_soc_dai_link ams_delta_dai_link = {
552 .name = "CX20442", 584 .name = "CX20442",
553 .stream_name = "CX20442", 585 .stream_name = "CX20442",
554 .cpu_dai = &omap_mcbsp_dai[0], 586 .cpu_dai_name ="omap-mcbsp-dai.0",
555 .codec_dai = &cx20442_dai, 587 .codec_dai_name = "cx20442-voice",
556 .init = ams_delta_cx20442_init, 588 .init = ams_delta_cx20442_init,
589 .platform_name = "omap-pcm-audio",
590 .codec_name = "cx20442-codec",
557 .ops = &ams_delta_ops, 591 .ops = &ams_delta_ops,
558}; 592};
559 593
560/* Audio card driver */ 594/* Audio card driver */
561static struct snd_soc_card ams_delta_audio_card = { 595static struct snd_soc_card ams_delta_audio_card = {
562 .name = "AMS_DELTA", 596 .name = "AMS_DELTA",
563 .platform = &omap_soc_platform,
564 .dai_link = &ams_delta_dai_link, 597 .dai_link = &ams_delta_dai_link,
565 .num_links = 1, 598 .num_links = 1,
566 .set_bias_level = ams_delta_set_bias_level, 599 .set_bias_level = ams_delta_set_bias_level,
567}; 600};
568 601
569/* Audio subsystem */
570static struct snd_soc_device ams_delta_snd_soc_device = {
571 .card = &ams_delta_audio_card,
572 .codec_dev = &cx20442_codec_dev,
573};
574
575/* Module init/exit */ 602/* Module init/exit */
576static struct platform_device *ams_delta_audio_platform_device; 603static struct platform_device *ams_delta_audio_platform_device;
577static struct platform_device *cx20442_platform_device; 604static struct platform_device *cx20442_platform_device;
@@ -589,9 +616,7 @@ static int __init ams_delta_module_init(void)
589 return -ENOMEM; 616 return -ENOMEM;
590 617
591 platform_set_drvdata(ams_delta_audio_platform_device, 618 platform_set_drvdata(ams_delta_audio_platform_device,
592 &ams_delta_snd_soc_device); 619 &ams_delta_audio_card);
593 ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev;
594 *(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1;
595 620
596 ret = platform_device_add(ams_delta_audio_platform_device); 621 ret = platform_device_add(ams_delta_audio_platform_device);
597 if (ret) 622 if (ret)
@@ -601,8 +626,8 @@ static int __init ams_delta_module_init(void)
601 * Codec platform device could be registered from elsewhere (board?), 626 * Codec platform device could be registered from elsewhere (board?),
602 * but I do it here as it makes sense only if used with the card. 627 * but I do it here as it makes sense only if used with the card.
603 */ 628 */
604 cx20442_platform_device = platform_device_register_simple("cx20442", 629 cx20442_platform_device =
605 -1, NULL, 0); 630 platform_device_register_simple("cx20442-codec", -1, NULL, 0);
606 return 0; 631 return 0;
607err: 632err:
608 platform_device_put(ams_delta_audio_platform_device); 633 platform_device_put(ams_delta_audio_platform_device);
@@ -612,19 +637,6 @@ module_init(ams_delta_module_init);
612 637
613static void __exit ams_delta_module_exit(void) 638static void __exit ams_delta_module_exit(void)
614{ 639{
615 struct snd_soc_codec *codec;
616 struct tty_struct *tty;
617
618 if (ams_delta_audio_card.codec) {
619 codec = ams_delta_audio_card.codec;
620
621 if (codec->control_data) {
622 tty = codec->control_data;
623
624 tty_hangup(tty);
625 }
626 }
627
628 if (tty_unregister_ldisc(N_V253) != 0) 640 if (tty_unregister_ldisc(N_V253) != 0)
629 dev_warn(&ams_delta_audio_platform_device->dev, 641 dev_warn(&ams_delta_audio_platform_device->dev,
630 "failed to unregister V253 line discipline\n"); 642 "failed to unregister V253 line discipline\n");
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
index 3583c429f9be..fd3a40f309c8 100644
--- a/sound/soc/omap/igep0020.c
+++ b/sound/soc/omap/igep0020.c
@@ -33,14 +33,13 @@
33 33
34#include "omap-mcbsp.h" 34#include "omap-mcbsp.h"
35#include "omap-pcm.h" 35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37 36
38static int igep2_hw_params(struct snd_pcm_substream *substream, 37static int igep2_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params) 38 struct snd_pcm_hw_params *params)
40{ 39{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data; 40 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 41 struct snd_soc_dai *codec_dai = rtd->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
44 int ret; 43 int ret;
45 44
46 /* Set codec DAI configuration */ 45 /* Set codec DAI configuration */
@@ -82,35 +81,28 @@ static struct snd_soc_ops igep2_ops = {
82static struct snd_soc_dai_link igep2_dai = { 81static struct snd_soc_dai_link igep2_dai = {
83 .name = "TWL4030", 82 .name = "TWL4030",
84 .stream_name = "TWL4030", 83 .stream_name = "TWL4030",
85 .cpu_dai = &omap_mcbsp_dai[0], 84 .cpu_dai_name = "omap-mcbsp-dai.1",
86 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 85 .codec_dai_name = "twl4030-hifi",
86 .platform_name = "omap-pcm-audio",
87 .codec_name = "twl4030-codec",
87 .ops = &igep2_ops, 88 .ops = &igep2_ops,
88}; 89};
89 90
90/* Audio machine driver */ 91/* Audio machine driver */
91static struct snd_soc_card snd_soc_card_igep2 = { 92static struct snd_soc_card snd_soc_card_igep2 = {
92 .name = "igep2", 93 .name = "igep2",
93 .platform = &omap_soc_platform,
94 .dai_link = &igep2_dai, 94 .dai_link = &igep2_dai,
95 .num_links = 1, 95 .num_links = 1,
96}; 96};
97 97
98/* Audio subsystem */
99static struct snd_soc_device igep2_snd_devdata = {
100 .card = &snd_soc_card_igep2,
101 .codec_dev = &soc_codec_dev_twl4030,
102};
103
104static struct platform_device *igep2_snd_device; 98static struct platform_device *igep2_snd_device;
105 99
106static int __init igep2_soc_init(void) 100static int __init igep2_soc_init(void)
107{ 101{
108 int ret; 102 int ret;
109 103
110 if (!machine_is_igep0020()) { 104 if (!machine_is_igep0020())
111 pr_debug("Not IGEP v2!\n");
112 return -ENODEV; 105 return -ENODEV;
113 }
114 printk(KERN_INFO "IGEP v2 SoC init\n"); 106 printk(KERN_INFO "IGEP v2 SoC init\n");
115 107
116 igep2_snd_device = platform_device_alloc("soc-audio", -1); 108 igep2_snd_device = platform_device_alloc("soc-audio", -1);
@@ -119,9 +111,7 @@ static int __init igep2_soc_init(void)
119 return -ENOMEM; 111 return -ENOMEM;
120 } 112 }
121 113
122 platform_set_drvdata(igep2_snd_device, &igep2_snd_devdata); 114 platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2);
123 igep2_snd_devdata.dev = &igep2_snd_device->dev;
124 *(unsigned int *)igep2_dai.cpu_dai->private_data = 1; /* McBSP2 */
125 115
126 ret = platform_device_add(igep2_snd_device); 116 ret = platform_device_add(igep2_snd_device);
127 if (ret) 117 if (ret)
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
index 90b8bf71c893..928f03707451 100644
--- a/sound/soc/omap/mcpdm.c
+++ b/sound/soc/omap/mcpdm.c
@@ -402,7 +402,7 @@ int omap_mcpdm_set_offset(int offset1, int offset2)
402 return 0; 402 return 0;
403} 403}
404 404
405static int __devinit omap_mcpdm_probe(struct platform_device *pdev) 405int __devinit omap_mcpdm_probe(struct platform_device *pdev)
406{ 406{
407 struct resource *res; 407 struct resource *res;
408 int ret = 0; 408 int ret = 0;
@@ -449,7 +449,7 @@ exit:
449 return ret; 449 return ret;
450} 450}
451 451
452static int __devexit omap_mcpdm_remove(struct platform_device *pdev) 452int __devexit omap_mcpdm_remove(struct platform_device *pdev)
453{ 453{
454 struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev); 454 struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
455 455
@@ -468,18 +468,3 @@ static int __devexit omap_mcpdm_remove(struct platform_device *pdev)
468 return 0; 468 return 0;
469} 469}
470 470
471static struct platform_driver omap_mcpdm_driver = {
472 .probe = omap_mcpdm_probe,
473 .remove = __devexit_p(omap_mcpdm_remove),
474 .driver = {
475 .name = "omap-mcpdm",
476 },
477};
478
479static struct platform_device *omap_mcpdm_device;
480
481static int __init omap_mcpdm_init(void)
482{
483 return platform_driver_register(&omap_mcpdm_driver);
484}
485arch_initcall(omap_mcpdm_init);
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h
index 7bb326ef0886..df3e16fb51f3 100644
--- a/sound/soc/omap/mcpdm.h
+++ b/sound/soc/omap/mcpdm.h
@@ -149,3 +149,5 @@ extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);
149extern int omap_mcpdm_request(void); 149extern int omap_mcpdm_request(void);
150extern void omap_mcpdm_free(void); 150extern void omap_mcpdm_free(void);
151extern int omap_mcpdm_set_offset(int offset1, int offset2); 151extern int omap_mcpdm_set_offset(int offset1, int offset2);
152int __devinit omap_mcpdm_probe(struct platform_device *pdev);
153int __devexit omap_mcpdm_remove(struct platform_device *pdev);
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 08e09d72790f..a3b6d897ad84 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -97,7 +97,7 @@ static int n810_startup(struct snd_pcm_substream *substream)
97{ 97{
98 struct snd_pcm_runtime *runtime = substream->runtime; 98 struct snd_pcm_runtime *runtime = substream->runtime;
99 struct snd_soc_pcm_runtime *rtd = substream->private_data; 99 struct snd_soc_pcm_runtime *rtd = substream->private_data;
100 struct snd_soc_codec *codec = rtd->socdev->card->codec; 100 struct snd_soc_codec *codec = rtd->codec;
101 101
102 snd_pcm_hw_constraint_minmax(runtime, 102 snd_pcm_hw_constraint_minmax(runtime,
103 SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); 103 SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
@@ -115,8 +115,8 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
115 struct snd_pcm_hw_params *params) 115 struct snd_pcm_hw_params *params)
116{ 116{
117 struct snd_soc_pcm_runtime *rtd = substream->private_data; 117 struct snd_soc_pcm_runtime *rtd = substream->private_data;
118 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 118 struct snd_soc_dai *codec_dai = rtd->codec_dai;
119 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 119 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
120 int err; 120 int err;
121 121
122 /* Set codec DAI configuration */ 122 /* Set codec DAI configuration */
@@ -271,8 +271,9 @@ static const struct snd_kcontrol_new aic33_n810_controls[] = {
271 n810_get_input, n810_set_input), 271 n810_get_input, n810_set_input),
272}; 272};
273 273
274static int n810_aic33_init(struct snd_soc_codec *codec) 274static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
275{ 275{
276 struct snd_soc_codec *codec = rtd->codec;
276 int err; 277 int err;
277 278
278 /* Not connected */ 279 /* Not connected */
@@ -307,8 +308,10 @@ static int n810_aic33_init(struct snd_soc_codec *codec)
307static struct snd_soc_dai_link n810_dai = { 308static struct snd_soc_dai_link n810_dai = {
308 .name = "TLV320AIC33", 309 .name = "TLV320AIC33",
309 .stream_name = "AIC33", 310 .stream_name = "AIC33",
310 .cpu_dai = &omap_mcbsp_dai[0], 311 .cpu_dai_name = "omap-mcbsp-dai.1",
311 .codec_dai = &aic3x_dai, 312 .platform_name = "omap-pcm-audio",
313 .codec_name = "tlv320aic3x-codec.2-0018",
314 .codec_dai_name = "tlv320aic3x-hifi",
312 .init = n810_aic33_init, 315 .init = n810_aic33_init,
313 .ops = &n810_ops, 316 .ops = &n810_ops,
314}; 317};
@@ -316,33 +319,12 @@ static struct snd_soc_dai_link n810_dai = {
316/* Audio machine driver */ 319/* Audio machine driver */
317static struct snd_soc_card snd_soc_n810 = { 320static struct snd_soc_card snd_soc_n810 = {
318 .name = "N810", 321 .name = "N810",
319 .platform = &omap_soc_platform,
320 .dai_link = &n810_dai, 322 .dai_link = &n810_dai,
321 .num_links = 1, 323 .num_links = 1,
322}; 324};
323 325
324/* Audio private data */
325static struct aic3x_setup_data n810_aic33_setup = {
326 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
327 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
328};
329
330/* Audio subsystem */
331static struct snd_soc_device n810_snd_devdata = {
332 .card = &snd_soc_n810,
333 .codec_dev = &soc_codec_dev_aic3x,
334 .codec_data = &n810_aic33_setup,
335};
336
337static struct platform_device *n810_snd_device; 326static struct platform_device *n810_snd_device;
338 327
339/* temporary i2c device creation until this can be moved into the machine
340 * support file.
341*/
342static struct i2c_board_info i2c_device[] = {
343 { I2C_BOARD_INFO("tlv320aic3x", 0x1b), }
344};
345
346static int __init n810_soc_init(void) 328static int __init n810_soc_init(void)
347{ 329{
348 int err; 330 int err;
@@ -351,15 +333,11 @@ static int __init n810_soc_init(void)
351 if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) 333 if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax()))
352 return -ENODEV; 334 return -ENODEV;
353 335
354 i2c_register_board_info(1, i2c_device, ARRAY_SIZE(i2c_device));
355
356 n810_snd_device = platform_device_alloc("soc-audio", -1); 336 n810_snd_device = platform_device_alloc("soc-audio", -1);
357 if (!n810_snd_device) 337 if (!n810_snd_device)
358 return -ENOMEM; 338 return -ENOMEM;
359 339
360 platform_set_drvdata(n810_snd_device, &n810_snd_devdata); 340 platform_set_drvdata(n810_snd_device, &snd_soc_n810);
361 n810_snd_devdata.dev = &n810_snd_device->dev;
362 *(unsigned int *)n810_dai.cpu_dai->private_data = 1; /* McBSP2 */
363 err = platform_device_add(n810_snd_device); 341 err = platform_device_add(n810_snd_device);
364 if (err) 342 if (err)
365 goto err1; 343 goto err1;
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 86f213905e2c..99696187b55a 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -62,8 +62,6 @@ struct omap_mcbsp_data {
62 int wlen; 62 int wlen;
63}; 63};
64 64
65#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
66
67static struct omap_mcbsp_data mcbsp_data[NUM_LINKS]; 65static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
68 66
69/* 67/*
@@ -153,13 +151,13 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {};
153static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) 151static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
154{ 152{
155 struct snd_soc_pcm_runtime *rtd = substream->private_data; 153 struct snd_soc_pcm_runtime *rtd = substream->private_data;
156 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 154 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
157 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 155 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
158 struct omap_pcm_dma_data *dma_data; 156 struct omap_pcm_dma_data *dma_data;
159 int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); 157 int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
160 int words; 158 int words;
161 159
162 dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 160 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
163 161
164 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ 162 /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
165 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) 163 if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
@@ -203,11 +201,9 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
203} 201}
204 202
205static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, 203static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
206 struct snd_soc_dai *dai) 204 struct snd_soc_dai *cpu_dai)
207{ 205{
208 struct snd_soc_pcm_runtime *rtd = substream->private_data; 206 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
209 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
210 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
211 int bus_id = mcbsp_data->bus_id; 207 int bus_id = mcbsp_data->bus_id;
212 int err = 0; 208 int err = 0;
213 209
@@ -249,11 +245,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
249} 245}
250 246
251static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, 247static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
252 struct snd_soc_dai *dai) 248 struct snd_soc_dai *cpu_dai)
253{ 249{
254 struct snd_soc_pcm_runtime *rtd = substream->private_data; 250 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
255 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
256 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
257 251
258 if (!cpu_dai->active) { 252 if (!cpu_dai->active) {
259 omap_mcbsp_free(mcbsp_data->bus_id); 253 omap_mcbsp_free(mcbsp_data->bus_id);
@@ -262,11 +256,9 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
262} 256}
263 257
264static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, 258static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
265 struct snd_soc_dai *dai) 259 struct snd_soc_dai *cpu_dai)
266{ 260{
267 struct snd_soc_pcm_runtime *rtd = substream->private_data; 261 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
268 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
269 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
270 int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 262 int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
271 263
272 switch (cmd) { 264 switch (cmd) {
@@ -295,8 +287,8 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
295 struct snd_soc_dai *dai) 287 struct snd_soc_dai *dai)
296{ 288{
297 struct snd_soc_pcm_runtime *rtd = substream->private_data; 289 struct snd_soc_pcm_runtime *rtd = substream->private_data;
298 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 290 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
299 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 291 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
300 u16 fifo_use; 292 u16 fifo_use;
301 snd_pcm_sframes_t delay; 293 snd_pcm_sframes_t delay;
302 294
@@ -317,11 +309,9 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
317 309
318static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, 310static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
319 struct snd_pcm_hw_params *params, 311 struct snd_pcm_hw_params *params,
320 struct snd_soc_dai *dai) 312 struct snd_soc_dai *cpu_dai)
321{ 313{
322 struct snd_soc_pcm_runtime *rtd = substream->private_data; 314 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
323 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
324 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
325 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 315 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
326 struct omap_pcm_dma_data *dma_data; 316 struct omap_pcm_dma_data *dma_data;
327 int dma, bus_id = mcbsp_data->bus_id; 317 int dma, bus_id = mcbsp_data->bus_id;
@@ -496,7 +486,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
496static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, 486static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
497 unsigned int fmt) 487 unsigned int fmt)
498{ 488{
499 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 489 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
500 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 490 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
501 unsigned int temp_fmt = fmt; 491 unsigned int temp_fmt = fmt;
502 492
@@ -596,7 +586,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
596static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, 586static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
597 int div_id, int div) 587 int div_id, int div)
598{ 588{
599 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 589 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
600 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 590 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
601 591
602 if (div_id != OMAP_MCBSP_CLKGDV) 592 if (div_id != OMAP_MCBSP_CLKGDV)
@@ -699,7 +689,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
699 int clk_id, unsigned int freq, 689 int clk_id, unsigned int freq,
700 int dir) 690 int dir)
701{ 691{
702 struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); 692 struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
703 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 693 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
704 int err = 0; 694 int err = 0;
705 695
@@ -733,7 +723,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
733 return err; 723 return err;
734} 724}
735 725
736static struct snd_soc_dai_ops omap_mcbsp_dai_ops = { 726static struct snd_soc_dai_ops mcbsp_dai_ops = {
737 .startup = omap_mcbsp_dai_startup, 727 .startup = omap_mcbsp_dai_startup,
738 .shutdown = omap_mcbsp_dai_shutdown, 728 .shutdown = omap_mcbsp_dai_shutdown,
739 .trigger = omap_mcbsp_dai_trigger, 729 .trigger = omap_mcbsp_dai_trigger,
@@ -744,43 +734,32 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
744 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, 734 .set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
745}; 735};
746 736
747#define OMAP_MCBSP_DAI_BUILDER(link_id) \ 737static int mcbsp_dai_probe(struct snd_soc_dai *dai)
748{ \ 738{
749 .name = "omap-mcbsp-dai-"#link_id, \ 739 mcbsp_data[dai->id].bus_id = dai->id;
750 .id = (link_id), \ 740 snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id);
751 .playback = { \ 741 return 0;
752 .channels_min = 1, \
753 .channels_max = 16, \
754 .rates = OMAP_MCBSP_RATES, \
755 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
756 SNDRV_PCM_FMTBIT_S32_LE, \
757 }, \
758 .capture = { \
759 .channels_min = 1, \
760 .channels_max = 16, \
761 .rates = OMAP_MCBSP_RATES, \
762 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
763 SNDRV_PCM_FMTBIT_S32_LE, \
764 }, \
765 .ops = &omap_mcbsp_dai_ops, \
766 .private_data = &mcbsp_data[(link_id)].bus_id, \
767} 742}
768 743
769struct snd_soc_dai omap_mcbsp_dai[] = { 744static struct snd_soc_dai_driver omap_mcbsp_dai =
770 OMAP_MCBSP_DAI_BUILDER(0), 745{
771 OMAP_MCBSP_DAI_BUILDER(1), 746 .probe = mcbsp_dai_probe,
772#if NUM_LINKS >= 3 747 .playback = {
773 OMAP_MCBSP_DAI_BUILDER(2), 748 .channels_min = 1,
774#endif 749 .channels_max = 16,
775#if NUM_LINKS == 5 750 .rates = OMAP_MCBSP_RATES,
776 OMAP_MCBSP_DAI_BUILDER(3), 751 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
777 OMAP_MCBSP_DAI_BUILDER(4), 752 },
778#endif 753 .capture = {
754 .channels_min = 1,
755 .channels_max = 16,
756 .rates = OMAP_MCBSP_RATES,
757 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
758 },
759 .ops = &mcbsp_dai_ops,
779}; 760};
780 761
781EXPORT_SYMBOL_GPL(omap_mcbsp_dai); 762static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
782
783int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
784 struct snd_ctl_elem_info *uinfo) 763 struct snd_ctl_elem_info *uinfo)
785{ 764{
786 struct soc_mixer_control *mc = 765 struct soc_mixer_control *mc =
@@ -910,16 +889,36 @@ int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
910} 889}
911EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); 890EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
912 891
892static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
893{
894 return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
895}
896
897static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
898{
899 snd_soc_unregister_dai(&pdev->dev);
900 return 0;
901}
902
903static struct platform_driver asoc_mcbsp_driver = {
904 .driver = {
905 .name = "omap-mcbsp-dai",
906 .owner = THIS_MODULE,
907 },
908
909 .probe = asoc_mcbsp_probe,
910 .remove = __devexit_p(asoc_mcbsp_remove),
911};
912
913static int __init snd_omap_mcbsp_init(void) 913static int __init snd_omap_mcbsp_init(void)
914{ 914{
915 return snd_soc_register_dais(omap_mcbsp_dai, 915 return platform_driver_register(&asoc_mcbsp_driver);
916 ARRAY_SIZE(omap_mcbsp_dai));
917} 916}
918module_init(snd_omap_mcbsp_init); 917module_init(snd_omap_mcbsp_init);
919 918
920static void __exit snd_omap_mcbsp_exit(void) 919static void __exit snd_omap_mcbsp_exit(void)
921{ 920{
922 snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai)); 921 platform_driver_unregister(&asoc_mcbsp_driver);
923} 922}
924module_exit(snd_omap_mcbsp_exit); 923module_exit(snd_omap_mcbsp_exit);
925 924
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index 6c363e5f4387..ffdcc5abb7b9 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -55,8 +55,6 @@ enum omap_mcbsp_div {
55#define NUM_LINKS 5 55#define NUM_LINKS 5
56#endif 56#endif
57 57
58extern struct snd_soc_dai omap_mcbsp_dai[NUM_LINKS];
59
60int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id); 58int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
61 59
62#endif 60#endif
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index b7f4f7e015f3..f161c2f5ed36 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -36,7 +36,6 @@
36#include <plat/dma.h> 36#include <plat/dma.h>
37#include <plat/mcbsp.h> 37#include <plat/mcbsp.h>
38#include "mcpdm.h" 38#include "mcpdm.h"
39#include "omap-mcpdm.h"
40#include "omap-pcm.h" 39#include "omap-pcm.h"
41 40
42struct omap_mcpdm_data { 41struct omap_mcpdm_data {
@@ -89,11 +88,9 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
89static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, 88static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
90 struct snd_soc_dai *dai) 89 struct snd_soc_dai *dai)
91{ 90{
92 struct snd_soc_pcm_runtime *rtd = substream->private_data;
93 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
94 int err = 0; 91 int err = 0;
95 92
96 if (!cpu_dai->active) 93 if (!dai->active)
97 err = omap_mcpdm_request(); 94 err = omap_mcpdm_request();
98 95
99 return err; 96 return err;
@@ -102,19 +99,14 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
102static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, 99static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
103 struct snd_soc_dai *dai) 100 struct snd_soc_dai *dai)
104{ 101{
105 struct snd_soc_pcm_runtime *rtd = substream->private_data; 102 if (!dai->active)
106 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
107
108 if (!cpu_dai->active)
109 omap_mcpdm_free(); 103 omap_mcpdm_free();
110} 104}
111 105
112static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd, 106static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
113 struct snd_soc_dai *dai) 107 struct snd_soc_dai *dai)
114{ 108{
115 struct snd_soc_pcm_runtime *rtd = substream->private_data; 109 struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
116 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
117 struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
118 int stream = substream->stream; 110 int stream = substream->stream;
119 int err = 0; 111 int err = 0;
120 112
@@ -143,14 +135,12 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
143 struct snd_pcm_hw_params *params, 135 struct snd_pcm_hw_params *params,
144 struct snd_soc_dai *dai) 136 struct snd_soc_dai *dai)
145{ 137{
146 struct snd_soc_pcm_runtime *rtd = substream->private_data; 138 struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
147 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
148 struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
149 struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; 139 struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
150 int stream = substream->stream; 140 int stream = substream->stream;
151 int channels, err, link_mask = 0; 141 int channels, err, link_mask = 0;
152 142
153 snd_soc_dai_set_dma_data(cpu_dai, substream, 143 snd_soc_dai_set_dma_data(dai, substream,
154 &omap_mcpdm_dai_dma_params[stream]); 144 &omap_mcpdm_dai_dma_params[stream]);
155 145
156 channels = params_channels(params); 146 channels = params_channels(params);
@@ -189,9 +179,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
189static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream, 179static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream,
190 struct snd_soc_dai *dai) 180 struct snd_soc_dai *dai)
191{ 181{
192 struct snd_soc_pcm_runtime *rtd = substream->private_data; 182 struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
193 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
194 struct omap_mcpdm_data *mcpdm_priv = cpu_dai->private_data;
195 struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links; 183 struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
196 int stream = substream->stream; 184 int stream = substream->stream;
197 int err; 185 int err;
@@ -215,9 +203,14 @@ static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
215#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 203#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
216#define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) 204#define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
217 205
218struct snd_soc_dai omap_mcpdm_dai = { 206static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai)
219 .name = "omap-mcpdm", 207{
220 .id = -1, 208 snd_soc_dai_set_drvdata(dai, &mcpdm_data);
209 return 0;
210}
211
212static struct snd_soc_dai_driver omap_mcpdm_dai = {
213 .probe = omap_mcpdm_dai_probe,
221 .playback = { 214 .playback = {
222 .channels_min = 1, 215 .channels_min = 1,
223 .channels_max = 4, 216 .channels_max = 4,
@@ -231,19 +224,47 @@ struct snd_soc_dai omap_mcpdm_dai = {
231 .formats = OMAP_MCPDM_FORMATS, 224 .formats = OMAP_MCPDM_FORMATS,
232 }, 225 },
233 .ops = &omap_mcpdm_dai_ops, 226 .ops = &omap_mcpdm_dai_ops,
234 .private_data = &mcpdm_data,
235}; 227};
236EXPORT_SYMBOL_GPL(omap_mcpdm_dai); 228
229static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
230{
231 int ret;
232
233 ret = omap_mcpdm_probe(pdev);
234 if (ret < 0)
235 return ret;
236 ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
237 if (ret < 0)
238 omap_mcpdm_remove(pdev);
239 return ret;
240}
241
242static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
243{
244 snd_soc_unregister_dai(&pdev->dev);
245 omap_mcpdm_remove(pdev);
246 return 0;
247}
248
249static struct platform_driver asoc_mcpdm_driver = {
250 .driver = {
251 .name = "omap-mcpdm-dai",
252 .owner = THIS_MODULE,
253 },
254
255 .probe = asoc_mcpdm_probe,
256 .remove = __devexit_p(asoc_mcpdm_remove),
257};
237 258
238static int __init snd_omap_mcpdm_init(void) 259static int __init snd_omap_mcpdm_init(void)
239{ 260{
240 return snd_soc_register_dai(&omap_mcpdm_dai); 261 return platform_driver_register(&asoc_mcpdm_driver);
241} 262}
242module_init(snd_omap_mcpdm_init); 263module_init(snd_omap_mcpdm_init);
243 264
244static void __exit snd_omap_mcpdm_exit(void) 265static void __exit snd_omap_mcpdm_exit(void)
245{ 266{
246 snd_soc_unregister_dai(&omap_mcpdm_dai); 267 platform_driver_unregister(&asoc_mcpdm_driver);
247} 268}
248module_exit(snd_omap_mcpdm_exit); 269module_exit(snd_omap_mcpdm_exit);
249 270
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h
deleted file mode 100644
index 73b80d559345..000000000000
--- a/sound/soc/omap/omap-mcpdm.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * omap-mcpdm.h
3 *
4 * Copyright (C) 2009 Texas Instruments
5 *
6 * Contact: Misael Lopez Cruz <x0052729@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __OMAP_MCPDM_H__
25#define __OMAP_MCPDM_H__
26
27extern struct snd_soc_dai omap_mcpdm_dai;
28
29#endif /* End of __OMAP_MCPDM_H__ */
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 1e521904ea64..8caeb8d305c3 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -101,9 +101,10 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
101 struct snd_soc_pcm_runtime *rtd = substream->private_data; 101 struct snd_soc_pcm_runtime *rtd = substream->private_data;
102 struct omap_runtime_data *prtd = runtime->private_data; 102 struct omap_runtime_data *prtd = runtime->private_data;
103 struct omap_pcm_dma_data *dma_data; 103 struct omap_pcm_dma_data *dma_data;
104
104 int err = 0; 105 int err = 0;
105 106
106 dma_data = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 107 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
107 108
108 /* return if this is a bufferless transfer e.g. 109 /* return if this is a bufferless transfer e.g.
109 * codec <--> BT codec or GSM modem -- lg FIXME */ 110 * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -374,14 +375,14 @@ static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
374 if (!card->dev->coherent_dma_mask) 375 if (!card->dev->coherent_dma_mask)
375 card->dev->coherent_dma_mask = DMA_BIT_MASK(64); 376 card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
376 377
377 if (dai->playback.channels_min) { 378 if (dai->driver->playback.channels_min) {
378 ret = omap_pcm_preallocate_dma_buffer(pcm, 379 ret = omap_pcm_preallocate_dma_buffer(pcm,
379 SNDRV_PCM_STREAM_PLAYBACK); 380 SNDRV_PCM_STREAM_PLAYBACK);
380 if (ret) 381 if (ret)
381 goto out; 382 goto out;
382 } 383 }
383 384
384 if (dai->capture.channels_min) { 385 if (dai->driver->capture.channels_min) {
385 ret = omap_pcm_preallocate_dma_buffer(pcm, 386 ret = omap_pcm_preallocate_dma_buffer(pcm,
386 SNDRV_PCM_STREAM_CAPTURE); 387 SNDRV_PCM_STREAM_CAPTURE);
387 if (ret) 388 if (ret)
@@ -392,25 +393,45 @@ out:
392 return ret; 393 return ret;
393} 394}
394 395
395struct snd_soc_platform omap_soc_platform = { 396static struct snd_soc_platform_driver omap_soc_platform = {
396 .name = "omap-pcm-audio", 397 .ops = &omap_pcm_ops,
397 .pcm_ops = &omap_pcm_ops,
398 .pcm_new = omap_pcm_new, 398 .pcm_new = omap_pcm_new,
399 .pcm_free = omap_pcm_free_dma_buffers, 399 .pcm_free = omap_pcm_free_dma_buffers,
400}; 400};
401EXPORT_SYMBOL_GPL(omap_soc_platform);
402 401
403static int __init omap_soc_platform_init(void) 402static __devinit int omap_pcm_probe(struct platform_device *pdev)
403{
404 return snd_soc_register_platform(&pdev->dev,
405 &omap_soc_platform);
406}
407
408static int __devexit omap_pcm_remove(struct platform_device *pdev)
409{
410 snd_soc_unregister_platform(&pdev->dev);
411 return 0;
412}
413
414static struct platform_driver omap_pcm_driver = {
415 .driver = {
416 .name = "omap-pcm-audio",
417 .owner = THIS_MODULE,
418 },
419
420 .probe = omap_pcm_probe,
421 .remove = __devexit_p(omap_pcm_remove),
422};
423
424static int __init snd_omap_pcm_init(void)
404{ 425{
405 return snd_soc_register_platform(&omap_soc_platform); 426 return platform_driver_register(&omap_pcm_driver);
406} 427}
407module_init(omap_soc_platform_init); 428module_init(snd_omap_pcm_init);
408 429
409static void __exit omap_soc_platform_exit(void) 430static void __exit snd_omap_pcm_exit(void)
410{ 431{
411 snd_soc_unregister_platform(&omap_soc_platform); 432 platform_driver_unregister(&omap_pcm_driver);
412} 433}
413module_exit(omap_soc_platform_exit); 434module_exit(snd_omap_pcm_exit);
414 435
415MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>"); 436MODULE_AUTHOR("Jarkko Nikula <jhnikula@gmail.com>");
416MODULE_DESCRIPTION("OMAP PCM DMA module"); 437MODULE_DESCRIPTION("OMAP PCM DMA module");
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index b19975d26907..fea0515331fb 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -35,6 +35,4 @@ struct omap_pcm_dma_data {
35 int packet_size; /* packet size only in PACKET mode */ 35 int packet_size; /* packet size only in PACKET mode */
36}; 36};
37 37
38extern struct snd_soc_platform omap_soc_platform;
39
40#endif 38#endif
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c
index c7adea38274c..cf3fc8a675b5 100644
--- a/sound/soc/omap/omap2evm.c
+++ b/sound/soc/omap/omap2evm.c
@@ -35,15 +35,13 @@
35 35
36#include "omap-mcbsp.h" 36#include "omap-mcbsp.h"
37#include "omap-pcm.h" 37#include "omap-pcm.h"
38#include "../codecs/twl4030.h"
39 38
40static int omap2evm_hw_params(struct snd_pcm_substream *substream, 39static int omap2evm_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params, 40 struct snd_pcm_hw_params *params)
42 struct snd_soc_dai *dai)
43{ 41{
44 struct snd_soc_pcm_runtime *rtd = substream->private_data; 42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
45 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 43 struct snd_soc_dai *codec_dai = rtd->codec_dai;
46 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 44 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
47 int ret; 45 int ret;
48 46
49 /* Set codec DAI configuration */ 47 /* Set codec DAI configuration */
@@ -85,35 +83,28 @@ static struct snd_soc_ops omap2evm_ops = {
85static struct snd_soc_dai_link omap2evm_dai = { 83static struct snd_soc_dai_link omap2evm_dai = {
86 .name = "TWL4030", 84 .name = "TWL4030",
87 .stream_name = "TWL4030", 85 .stream_name = "TWL4030",
88 .cpu_dai = &omap_mcbsp_dai[0], 86 .cpu_dai_name = "omap-mcbsp-dai.1",
89 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 87 .codec_dai_name = "twl4030-hifi",
88 .platform_name = "omap-pcm-audio",
89 .codec_name = "twl4030-codec",
90 .ops = &omap2evm_ops, 90 .ops = &omap2evm_ops,
91}; 91};
92 92
93/* Audio machine driver */ 93/* Audio machine driver */
94static struct snd_soc_card snd_soc_omap2evm = { 94static struct snd_soc_card snd_soc_omap2evm = {
95 .name = "omap2evm", 95 .name = "omap2evm",
96 .platform = &omap_soc_platform,
97 .dai_link = &omap2evm_dai, 96 .dai_link = &omap2evm_dai,
98 .num_links = 1, 97 .num_links = 1,
99}; 98};
100 99
101/* Audio subsystem */
102static struct snd_soc_device omap2evm_snd_devdata = {
103 .card = &snd_soc_omap2evm,
104 .codec_dev = &soc_codec_dev_twl4030,
105};
106
107static struct platform_device *omap2evm_snd_device; 100static struct platform_device *omap2evm_snd_device;
108 101
109static int __init omap2evm_soc_init(void) 102static int __init omap2evm_soc_init(void)
110{ 103{
111 int ret; 104 int ret;
112 105
113 if (!machine_is_omap2evm()) { 106 if (!machine_is_omap2evm())
114 pr_debug("Not omap2evm!\n");
115 return -ENODEV; 107 return -ENODEV;
116 }
117 printk(KERN_INFO "omap2evm SoC init\n"); 108 printk(KERN_INFO "omap2evm SoC init\n");
118 109
119 omap2evm_snd_device = platform_device_alloc("soc-audio", -1); 110 omap2evm_snd_device = platform_device_alloc("soc-audio", -1);
@@ -122,9 +113,7 @@ static int __init omap2evm_soc_init(void)
122 return -ENOMEM; 113 return -ENOMEM;
123 } 114 }
124 115
125 platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata); 116 platform_set_drvdata(omap2evm_snd_device, &snd_soc_omap2evm);
126 omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev;
127 *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */
128 117
129 ret = platform_device_add(omap2evm_snd_device); 118 ret = platform_device_add(omap2evm_snd_device);
130 if (ret) 119 if (ret)
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
index 240e0975dd6a..e56832b0c444 100644
--- a/sound/soc/omap/omap3beagle.c
+++ b/sound/soc/omap/omap3beagle.c
@@ -33,14 +33,13 @@
33 33
34#include "omap-mcbsp.h" 34#include "omap-mcbsp.h"
35#include "omap-pcm.h" 35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37 36
38static int omap3beagle_hw_params(struct snd_pcm_substream *substream, 37static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params) 38 struct snd_pcm_hw_params *params)
40{ 39{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data; 40 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 41 struct snd_soc_dai *codec_dai = rtd->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
44 unsigned int fmt; 43 unsigned int fmt;
45 int ret; 44 int ret;
46 45
@@ -92,35 +91,29 @@ static struct snd_soc_ops omap3beagle_ops = {
92static struct snd_soc_dai_link omap3beagle_dai = { 91static struct snd_soc_dai_link omap3beagle_dai = {
93 .name = "TWL4030", 92 .name = "TWL4030",
94 .stream_name = "TWL4030", 93 .stream_name = "TWL4030",
95 .cpu_dai = &omap_mcbsp_dai[0], 94 .cpu_dai_name = "omap-mcbsp-dai.1",
96 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 95 .platform_name = "omap-pcm-audio",
96 .codec_dai_name = "twl4030-hifi",
97 .codec_name = "twl4030-codec",
97 .ops = &omap3beagle_ops, 98 .ops = &omap3beagle_ops,
98}; 99};
99 100
100/* Audio machine driver */ 101/* Audio machine driver */
101static struct snd_soc_card snd_soc_omap3beagle = { 102static struct snd_soc_card snd_soc_omap3beagle = {
102 .name = "omap3beagle", 103 .name = "omap3beagle",
103 .platform = &omap_soc_platform, 104 .owner = THIS_MODULE,
104 .dai_link = &omap3beagle_dai, 105 .dai_link = &omap3beagle_dai,
105 .num_links = 1, 106 .num_links = 1,
106}; 107};
107 108
108/* Audio subsystem */
109static struct snd_soc_device omap3beagle_snd_devdata = {
110 .card = &snd_soc_omap3beagle,
111 .codec_dev = &soc_codec_dev_twl4030,
112};
113
114static struct platform_device *omap3beagle_snd_device; 109static struct platform_device *omap3beagle_snd_device;
115 110
116static int __init omap3beagle_soc_init(void) 111static int __init omap3beagle_soc_init(void)
117{ 112{
118 int ret; 113 int ret;
119 114
120 if (!(machine_is_omap3_beagle() || machine_is_devkit8000())) { 115 if (!(machine_is_omap3_beagle() || machine_is_devkit8000()))
121 pr_debug("Not OMAP3 Beagle or Devkit8000!\n");
122 return -ENODEV; 116 return -ENODEV;
123 }
124 pr_info("OMAP3 Beagle/Devkit8000 SoC init\n"); 117 pr_info("OMAP3 Beagle/Devkit8000 SoC init\n");
125 118
126 omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); 119 omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
@@ -129,9 +122,7 @@ static int __init omap3beagle_soc_init(void)
129 return -ENOMEM; 122 return -ENOMEM;
130 } 123 }
131 124
132 platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata); 125 platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle);
133 omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
134 *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
135 126
136 ret = platform_device_add(omap3beagle_snd_device); 127 ret = platform_device_add(omap3beagle_snd_device);
137 if (ret) 128 if (ret)
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
index dfcb344092e4..810f1e36da21 100644
--- a/sound/soc/omap/omap3evm.c
+++ b/sound/soc/omap/omap3evm.c
@@ -31,14 +31,13 @@
31 31
32#include "omap-mcbsp.h" 32#include "omap-mcbsp.h"
33#include "omap-pcm.h" 33#include "omap-pcm.h"
34#include "../codecs/twl4030.h"
35 34
36static int omap3evm_hw_params(struct snd_pcm_substream *substream, 35static int omap3evm_hw_params(struct snd_pcm_substream *substream,
37 struct snd_pcm_hw_params *params) 36 struct snd_pcm_hw_params *params)
38{ 37{
39 struct snd_soc_pcm_runtime *rtd = substream->private_data; 38 struct snd_soc_pcm_runtime *rtd = substream->private_data;
40 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 39 struct snd_soc_dai *codec_dai = rtd->codec_dai;
41 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 40 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
42 int ret; 41 int ret;
43 42
44 /* Set codec DAI configuration */ 43 /* Set codec DAI configuration */
@@ -80,42 +79,28 @@ static struct snd_soc_ops omap3evm_ops = {
80static struct snd_soc_dai_link omap3evm_dai = { 79static struct snd_soc_dai_link omap3evm_dai = {
81 .name = "TWL4030", 80 .name = "TWL4030",
82 .stream_name = "TWL4030", 81 .stream_name = "TWL4030",
83 .cpu_dai = &omap_mcbsp_dai[0], 82 .cpu_dai_name = "omap-mcbsp-dai.1",
84 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 83 .codec_dai_name = "twl4030-hifi",
84 .platform_name = "omap-pcm-audio",
85 .codec_name = "twl4030-codec",
85 .ops = &omap3evm_ops, 86 .ops = &omap3evm_ops,
86}; 87};
87 88
88/* Audio machine driver */ 89/* Audio machine driver */
89static struct snd_soc_card snd_soc_omap3evm = { 90static struct snd_soc_card snd_soc_omap3evm = {
90 .name = "omap3evm", 91 .name = "omap3evm",
91 .platform = &omap_soc_platform,
92 .dai_link = &omap3evm_dai, 92 .dai_link = &omap3evm_dai,
93 .num_links = 1, 93 .num_links = 1,
94}; 94};
95 95
96/* twl4030 setup */
97static struct twl4030_setup_data twl4030_setup = {
98 .ramp_delay_value = 4,
99 .sysclk = 26000,
100};
101
102/* Audio subsystem */
103static struct snd_soc_device omap3evm_snd_devdata = {
104 .card = &snd_soc_omap3evm,
105 .codec_dev = &soc_codec_dev_twl4030,
106 .codec_data = &twl4030_setup,
107};
108
109static struct platform_device *omap3evm_snd_device; 96static struct platform_device *omap3evm_snd_device;
110 97
111static int __init omap3evm_soc_init(void) 98static int __init omap3evm_soc_init(void)
112{ 99{
113 int ret; 100 int ret;
114 101
115 if (!machine_is_omap3evm()) { 102 if (!machine_is_omap3evm())
116 pr_err("Not OMAP3 EVM!\n");
117 return -ENODEV; 103 return -ENODEV;
118 }
119 pr_info("OMAP3 EVM SoC init\n"); 104 pr_info("OMAP3 EVM SoC init\n");
120 105
121 omap3evm_snd_device = platform_device_alloc("soc-audio", -1); 106 omap3evm_snd_device = platform_device_alloc("soc-audio", -1);
@@ -124,10 +109,7 @@ static int __init omap3evm_soc_init(void)
124 return -ENOMEM; 109 return -ENOMEM;
125 } 110 }
126 111
127 platform_set_drvdata(omap3evm_snd_device, &omap3evm_snd_devdata); 112 platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm);
128 omap3evm_snd_devdata.dev = &omap3evm_snd_device->dev;
129 *(unsigned int *)omap3evm_dai.cpu_dai->private_data = 1;
130
131 ret = platform_device_add(omap3evm_snd_device); 113 ret = platform_device_add(omap3evm_snd_device);
132 if (ret) 114 if (ret)
133 goto err1; 115 goto err1;
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 9eecac135bbb..dbd9d96b5f92 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -31,10 +31,10 @@
31#include <sound/soc-dapm.h> 31#include <sound/soc-dapm.h>
32 32
33#include <asm/mach-types.h> 33#include <asm/mach-types.h>
34#include <plat/mcbsp.h>
34 35
35#include "omap-mcbsp.h" 36#include "omap-mcbsp.h"
36#include "omap-pcm.h" 37#include "omap-pcm.h"
37#include "../codecs/twl4030.h"
38 38
39#define OMAP3_PANDORA_DAC_POWER_GPIO 118 39#define OMAP3_PANDORA_DAC_POWER_GPIO 118
40#define OMAP3_PANDORA_AMP_POWER_GPIO 14 40#define OMAP3_PANDORA_AMP_POWER_GPIO 14
@@ -47,8 +47,8 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
47 struct snd_pcm_hw_params *params) 47 struct snd_pcm_hw_params *params)
48{ 48{
49 struct snd_soc_pcm_runtime *rtd = substream->private_data; 49 struct snd_soc_pcm_runtime *rtd = substream->private_data;
50 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 50 struct snd_soc_dai *codec_dai = rtd->codec_dai;
51 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 51 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
52 int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 52 int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
53 SND_SOC_DAIFMT_CBS_CFS; 53 SND_SOC_DAIFMT_CBS_CFS;
54 int ret; 54 int ret;
@@ -167,8 +167,9 @@ static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
167 {"Mic Bias 2", NULL, "Mic (external)"}, 167 {"Mic Bias 2", NULL, "Mic (external)"},
168}; 168};
169 169
170static int omap3pandora_out_init(struct snd_soc_codec *codec) 170static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
171{ 171{
172 struct snd_soc_codec *codec = rtd->codec;
172 int ret; 173 int ret;
173 174
174 /* All TWL4030 output pins are floating */ 175 /* All TWL4030 output pins are floating */
@@ -194,8 +195,9 @@ static int omap3pandora_out_init(struct snd_soc_codec *codec)
194 return snd_soc_dapm_sync(codec); 195 return snd_soc_dapm_sync(codec);
195} 196}
196 197
197static int omap3pandora_in_init(struct snd_soc_codec *codec) 198static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
198{ 199{
200 struct snd_soc_codec *codec = rtd->codec;
199 int ret; 201 int ret;
200 202
201 /* Not comnnected */ 203 /* Not comnnected */
@@ -224,15 +226,19 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
224 { 226 {
225 .name = "PCM1773", 227 .name = "PCM1773",
226 .stream_name = "HiFi Out", 228 .stream_name = "HiFi Out",
227 .cpu_dai = &omap_mcbsp_dai[0], 229 .cpu_dai_name = "omap-mcbsp-dai.1",
228 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 230 .codec_dai_name = "twl4030-hifi",
231 .platform_name = "omap-pcm-audio",
232 .codec_name = "twl4030-codec",
229 .ops = &omap3pandora_ops, 233 .ops = &omap3pandora_ops,
230 .init = omap3pandora_out_init, 234 .init = omap3pandora_out_init,
231 }, { 235 }, {
232 .name = "TWL4030", 236 .name = "TWL4030",
233 .stream_name = "Line/Mic In", 237 .stream_name = "Line/Mic In",
234 .cpu_dai = &omap_mcbsp_dai[1], 238 .cpu_dai_name = "omap-mcbsp-dai.3",
235 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 239 .codec_dai_name = "twl4030-hifi",
240 .platform_name = "omap-pcm-audio",
241 .codec_name = "twl4030-codec",
236 .ops = &omap3pandora_ops, 242 .ops = &omap3pandora_ops,
237 .init = omap3pandora_in_init, 243 .init = omap3pandora_in_init,
238 } 244 }
@@ -241,17 +247,10 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
241/* SoC card */ 247/* SoC card */
242static struct snd_soc_card snd_soc_card_omap3pandora = { 248static struct snd_soc_card snd_soc_card_omap3pandora = {
243 .name = "omap3pandora", 249 .name = "omap3pandora",
244 .platform = &omap_soc_platform,
245 .dai_link = omap3pandora_dai, 250 .dai_link = omap3pandora_dai,
246 .num_links = ARRAY_SIZE(omap3pandora_dai), 251 .num_links = ARRAY_SIZE(omap3pandora_dai),
247}; 252};
248 253
249/* Audio subsystem */
250static struct snd_soc_device omap3pandora_snd_data = {
251 .card = &snd_soc_card_omap3pandora,
252 .codec_dev = &soc_codec_dev_twl4030,
253};
254
255static struct platform_device *omap3pandora_snd_device; 254static struct platform_device *omap3pandora_snd_device;
256 255
257static int __init omap3pandora_soc_init(void) 256static int __init omap3pandora_soc_init(void)
@@ -294,10 +293,7 @@ static int __init omap3pandora_soc_init(void)
294 goto fail1; 293 goto fail1;
295 } 294 }
296 295
297 platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data); 296 platform_set_drvdata(omap3pandora_snd_device, &snd_soc_card_omap3pandora);
298 omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev;
299 *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */
300 *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */
301 297
302 ret = platform_device_add(omap3pandora_snd_device); 298 ret = platform_device_add(omap3pandora_snd_device);
303 if (ret) { 299 if (ret) {
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index 498ca2e03519..f0e662556428 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -55,8 +55,8 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
55 struct snd_pcm_hw_params *params) 55 struct snd_pcm_hw_params *params)
56{ 56{
57 struct snd_soc_pcm_runtime *rtd = substream->private_data; 57 struct snd_soc_pcm_runtime *rtd = substream->private_data;
58 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 58 struct snd_soc_dai *codec_dai = rtd->codec_dai;
59 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 59 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
60 int err; 60 int err;
61 61
62 /* Set codec DAI configuration */ 62 /* Set codec DAI configuration */
@@ -113,8 +113,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
113 {"MICIN", NULL, "Mic Jack"}, 113 {"MICIN", NULL, "Mic Jack"},
114}; 114};
115 115
116static int osk_tlv320aic23_init(struct snd_soc_codec *codec) 116static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
117{ 117{
118 struct snd_soc_codec *codec = rtd->codec;
118 119
119 /* Add osk5912 specific widgets */ 120 /* Add osk5912 specific widgets */
120 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, 121 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
@@ -136,8 +137,10 @@ static int osk_tlv320aic23_init(struct snd_soc_codec *codec)
136static struct snd_soc_dai_link osk_dai = { 137static struct snd_soc_dai_link osk_dai = {
137 .name = "TLV320AIC23", 138 .name = "TLV320AIC23",
138 .stream_name = "AIC23", 139 .stream_name = "AIC23",
139 .cpu_dai = &omap_mcbsp_dai[0], 140 .cpu_dai_name = "omap-mcbsp-dai.0",
140 .codec_dai = &tlv320aic23_dai, 141 .codec_dai_name = "tlv320aic23-hifi",
142 .platform_name = "omap-pcm-audio",
143 .codec_name = "tlv320aic23-codec",
141 .init = osk_tlv320aic23_init, 144 .init = osk_tlv320aic23_init,
142 .ops = &osk_ops, 145 .ops = &osk_ops,
143}; 146};
@@ -145,17 +148,10 @@ static struct snd_soc_dai_link osk_dai = {
145/* Audio machine driver */ 148/* Audio machine driver */
146static struct snd_soc_card snd_soc_card_osk = { 149static struct snd_soc_card snd_soc_card_osk = {
147 .name = "OSK5912", 150 .name = "OSK5912",
148 .platform = &omap_soc_platform,
149 .dai_link = &osk_dai, 151 .dai_link = &osk_dai,
150 .num_links = 1, 152 .num_links = 1,
151}; 153};
152 154
153/* Audio subsystem */
154static struct snd_soc_device osk_snd_devdata = {
155 .card = &snd_soc_card_osk,
156 .codec_dev = &soc_codec_dev_tlv320aic23,
157};
158
159static struct platform_device *osk_snd_device; 155static struct platform_device *osk_snd_device;
160 156
161static int __init osk_soc_init(void) 157static int __init osk_soc_init(void)
@@ -171,9 +167,7 @@ static int __init osk_soc_init(void)
171 if (!osk_snd_device) 167 if (!osk_snd_device)
172 return -ENOMEM; 168 return -ENOMEM;
173 169
174 platform_set_drvdata(osk_snd_device, &osk_snd_devdata); 170 platform_set_drvdata(osk_snd_device, &snd_soc_card_osk);
175 osk_snd_devdata.dev = &osk_snd_device->dev;
176 *(unsigned int *)osk_dai.cpu_dai->private_data = 0; /* McBSP1 */
177 err = platform_device_add(osk_snd_device); 171 err = platform_device_add(osk_snd_device);
178 if (err) 172 if (err)
179 goto err1; 173 goto err1;
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index c25f5276ad6f..e95a607937de 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -33,14 +33,13 @@
33 33
34#include "omap-mcbsp.h" 34#include "omap-mcbsp.h"
35#include "omap-pcm.h" 35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37 36
38static int overo_hw_params(struct snd_pcm_substream *substream, 37static int overo_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params) 38 struct snd_pcm_hw_params *params)
40{ 39{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data; 40 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 41 struct snd_soc_dai *codec_dai = rtd->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
44 int ret; 43 int ret;
45 44
46 /* Set codec DAI configuration */ 45 /* Set codec DAI configuration */
@@ -82,25 +81,20 @@ static struct snd_soc_ops overo_ops = {
82static struct snd_soc_dai_link overo_dai = { 81static struct snd_soc_dai_link overo_dai = {
83 .name = "TWL4030", 82 .name = "TWL4030",
84 .stream_name = "TWL4030", 83 .stream_name = "TWL4030",
85 .cpu_dai = &omap_mcbsp_dai[0], 84 .cpu_dai_name = "omap-mcbsp-dai.1",
86 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 85 .codec_dai_name = "twl4030-hifi",
86 .platform_name = "omap-pcm-audio",
87 .codec_name = "twl4030-codec",
87 .ops = &overo_ops, 88 .ops = &overo_ops,
88}; 89};
89 90
90/* Audio machine driver */ 91/* Audio machine driver */
91static struct snd_soc_card snd_soc_card_overo = { 92static struct snd_soc_card snd_soc_card_overo = {
92 .name = "overo", 93 .name = "overo",
93 .platform = &omap_soc_platform,
94 .dai_link = &overo_dai, 94 .dai_link = &overo_dai,
95 .num_links = 1, 95 .num_links = 1,
96}; 96};
97 97
98/* Audio subsystem */
99static struct snd_soc_device overo_snd_devdata = {
100 .card = &snd_soc_card_overo,
101 .codec_dev = &soc_codec_dev_twl4030,
102};
103
104static struct platform_device *overo_snd_device; 98static struct platform_device *overo_snd_device;
105 99
106static int __init overo_soc_init(void) 100static int __init overo_soc_init(void)
@@ -119,9 +113,7 @@ static int __init overo_soc_init(void)
119 return -ENOMEM; 113 return -ENOMEM;
120 } 114 }
121 115
122 platform_set_drvdata(overo_snd_device, &overo_snd_devdata); 116 platform_set_drvdata(overo_snd_device, &snd_soc_card_overo);
123 overo_snd_devdata.dev = &overo_snd_device->dev;
124 *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */
125 117
126 ret = platform_device_add(overo_snd_device); 118 ret = platform_device_add(overo_snd_device);
127 if (ret) 119 if (ret)
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 88052d29617f..04b5723bf89b 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -31,6 +31,7 @@
31#include <sound/pcm.h> 31#include <sound/pcm.h>
32#include <sound/soc.h> 32#include <sound/soc.h>
33#include <sound/soc-dapm.h> 33#include <sound/soc-dapm.h>
34#include <plat/mcbsp.h>
34 35
35#include <asm/mach-types.h> 36#include <asm/mach-types.h>
36 37
@@ -76,7 +77,7 @@ static int rx51_startup(struct snd_pcm_substream *substream)
76{ 77{
77 struct snd_pcm_runtime *runtime = substream->runtime; 78 struct snd_pcm_runtime *runtime = substream->runtime;
78 struct snd_soc_pcm_runtime *rtd = substream->private_data; 79 struct snd_soc_pcm_runtime *rtd = substream->private_data;
79 struct snd_soc_codec *codec = rtd->socdev->card->codec; 80 struct snd_soc_codec *codec = rtd->codec;
80 81
81 snd_pcm_hw_constraint_minmax(runtime, 82 snd_pcm_hw_constraint_minmax(runtime,
82 SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); 83 SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
@@ -89,8 +90,8 @@ static int rx51_hw_params(struct snd_pcm_substream *substream,
89 struct snd_pcm_hw_params *params) 90 struct snd_pcm_hw_params *params)
90{ 91{
91 struct snd_soc_pcm_runtime *rtd = substream->private_data; 92 struct snd_soc_pcm_runtime *rtd = substream->private_data;
92 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 93 struct snd_soc_dai *codec_dai = rtd->codec_dai;
93 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 94 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
94 int err; 95 int err;
95 96
96 /* Set codec DAI configuration */ 97 /* Set codec DAI configuration */
@@ -145,9 +146,9 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w,
145 struct snd_kcontrol *k, int event) 146 struct snd_kcontrol *k, int event)
146{ 147{
147 if (SND_SOC_DAPM_EVENT_ON(event)) 148 if (SND_SOC_DAPM_EVENT_ON(event))
148 gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 1); 149 gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 1);
149 else 150 else
150 gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 0); 151 gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 0);
151 152
152 return 0; 153 return 0;
153} 154}
@@ -240,9 +241,9 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
240 rx51_get_jack, rx51_set_jack), 241 rx51_get_jack, rx51_set_jack),
241}; 242};
242 243
243static int rx51_aic34_init(struct snd_soc_codec *codec) 244static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
244{ 245{
245 struct snd_soc_card *card = codec->socdev->card; 246 struct snd_soc_codec *codec = rtd->codec;
246 int err; 247 int err;
247 248
248 /* Set up NC codec pins */ 249 /* Set up NC codec pins */
@@ -266,7 +267,7 @@ static int rx51_aic34_init(struct snd_soc_codec *codec)
266 snd_soc_dapm_sync(codec); 267 snd_soc_dapm_sync(codec);
267 268
268 /* AV jack detection */ 269 /* AV jack detection */
269 err = snd_soc_jack_new(card, "AV Jack", 270 err = snd_soc_jack_new(codec, "AV Jack",
270 SND_JACK_VIDEOOUT, &rx51_av_jack); 271 SND_JACK_VIDEOOUT, &rx51_av_jack);
271 if (err) 272 if (err)
272 return err; 273 return err;
@@ -282,32 +283,20 @@ static struct snd_soc_dai_link rx51_dai[] = {
282 { 283 {
283 .name = "TLV320AIC34", 284 .name = "TLV320AIC34",
284 .stream_name = "AIC34", 285 .stream_name = "AIC34",
285 .cpu_dai = &omap_mcbsp_dai[0], 286 .cpu_dai_name = "omap-mcbsp-dai.1",
286 .codec_dai = &aic3x_dai, 287 .codec_dai_name = "tlv320aic3x-hifi",
288 .platform_name = "omap-pcm-audio",
289 .codec_name = "tlv320aic3x-codec.2-0018",
287 .init = rx51_aic34_init, 290 .init = rx51_aic34_init,
288 .ops = &rx51_ops, 291 .ops = &rx51_ops,
289 }, 292 },
290}; 293};
291 294
292/* Audio private data */
293static struct aic3x_setup_data rx51_aic34_setup = {
294 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED,
295 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT,
296};
297
298/* Audio card */ 295/* Audio card */
299static struct snd_soc_card rx51_sound_card = { 296static struct snd_soc_card rx51_sound_card = {
300 .name = "RX-51", 297 .name = "RX-51",
301 .dai_link = rx51_dai, 298 .dai_link = rx51_dai,
302 .num_links = ARRAY_SIZE(rx51_dai), 299 .num_links = ARRAY_SIZE(rx51_dai),
303 .platform = &omap_soc_platform,
304};
305
306/* Audio subsystem */
307static struct snd_soc_device rx51_snd_devdata = {
308 .card = &rx51_sound_card,
309 .codec_dev = &soc_codec_dev_aic3x,
310 .codec_data = &rx51_aic34_setup,
311}; 300};
312 301
313static struct platform_device *rx51_snd_device; 302static struct platform_device *rx51_snd_device;
@@ -330,9 +319,7 @@ static int __init rx51_soc_init(void)
330 goto err1; 319 goto err1;
331 } 320 }
332 321
333 platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata); 322 platform_set_drvdata(rx51_snd_device, &rx51_sound_card);
334 rx51_snd_devdata.dev = &rx51_snd_device->dev;
335 *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
336 323
337 err = platform_device_add(rx51_snd_device); 324 err = platform_device_add(rx51_snd_device);
338 if (err) 325 if (err)
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index 3c85c0f92823..07fbcf7d2411 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -36,9 +36,11 @@
36#include <mach/gpio.h> 36#include <mach/gpio.h>
37#include <plat/mcbsp.h> 37#include <plat/mcbsp.h>
38 38
39/* Register descriptions for twl4030 codec part */
40#include <linux/mfd/twl4030-codec.h>
41
39#include "omap-mcbsp.h" 42#include "omap-mcbsp.h"
40#include "omap-pcm.h" 43#include "omap-pcm.h"
41#include "../codecs/twl4030.h"
42 44
43/* TWL4030 PMBR1 Register */ 45/* TWL4030 PMBR1 Register */
44#define TWL4030_INTBR_PMBR1 0x0D 46#define TWL4030_INTBR_PMBR1 0x0D
@@ -51,8 +53,8 @@ static int sdp3430_hw_params(struct snd_pcm_substream *substream,
51 struct snd_pcm_hw_params *params) 53 struct snd_pcm_hw_params *params)
52{ 54{
53 struct snd_soc_pcm_runtime *rtd = substream->private_data; 55 struct snd_soc_pcm_runtime *rtd = substream->private_data;
54 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 56 struct snd_soc_dai *codec_dai = rtd->codec_dai;
55 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 57 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
56 int ret; 58 int ret;
57 59
58 /* Set codec DAI configuration */ 60 /* Set codec DAI configuration */
@@ -94,8 +96,8 @@ static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
94 struct snd_pcm_hw_params *params) 96 struct snd_pcm_hw_params *params)
95{ 97{
96 struct snd_soc_pcm_runtime *rtd = substream->private_data; 98 struct snd_soc_pcm_runtime *rtd = substream->private_data;
97 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 99 struct snd_soc_dai *codec_dai = rtd->codec_dai;
98 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 100 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
99 int ret; 101 int ret;
100 102
101 /* Set codec DAI configuration */ 103 /* Set codec DAI configuration */
@@ -186,8 +188,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
186 {"Headset Stereophone", NULL, "HSOR"}, 188 {"Headset Stereophone", NULL, "HSOR"},
187}; 189};
188 190
189static int sdp3430_twl4030_init(struct snd_soc_codec *codec) 191static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
190{ 192{
193 struct snd_soc_codec *codec = rtd->codec;
191 int ret; 194 int ret;
192 195
193 /* Add SDP3430 specific widgets */ 196 /* Add SDP3430 specific widgets */
@@ -225,7 +228,7 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec)
225 return ret; 228 return ret;
226 229
227 /* Headset jack detection */ 230 /* Headset jack detection */
228 ret = snd_soc_jack_new(&snd_soc_sdp3430, "Headset Jack", 231 ret = snd_soc_jack_new(codec, "Headset Jack",
229 SND_JACK_HEADSET, &hs_jack); 232 SND_JACK_HEADSET, &hs_jack);
230 if (ret) 233 if (ret)
231 return ret; 234 return ret;
@@ -241,14 +244,15 @@ static int sdp3430_twl4030_init(struct snd_soc_codec *codec)
241 return ret; 244 return ret;
242} 245}
243 246
244static int sdp3430_twl4030_voice_init(struct snd_soc_codec *codec) 247static int sdp3430_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
245{ 248{
249 struct snd_soc_codec *codec = rtd->codec;
246 unsigned short reg; 250 unsigned short reg;
247 251
248 /* Enable voice interface */ 252 /* Enable voice interface */
249 reg = codec->read(codec, TWL4030_REG_VOICE_IF); 253 reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF);
250 reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; 254 reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
251 codec->write(codec, TWL4030_REG_VOICE_IF, reg); 255 codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);
252 256
253 return 0; 257 return 0;
254} 258}
@@ -259,16 +263,20 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
259 { 263 {
260 .name = "TWL4030 I2S", 264 .name = "TWL4030 I2S",
261 .stream_name = "TWL4030 Audio", 265 .stream_name = "TWL4030 Audio",
262 .cpu_dai = &omap_mcbsp_dai[0], 266 .cpu_dai_name = "omap-mcbsp-dai.1",
263 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 267 .codec_dai_name = "twl4030-hifi",
268 .platform_name = "omap-pcm-audio",
269 .codec_name = "twl4030-codec",
264 .init = sdp3430_twl4030_init, 270 .init = sdp3430_twl4030_init,
265 .ops = &sdp3430_ops, 271 .ops = &sdp3430_ops,
266 }, 272 },
267 { 273 {
268 .name = "TWL4030 PCM", 274 .name = "TWL4030 PCM",
269 .stream_name = "TWL4030 Voice", 275 .stream_name = "TWL4030 Voice",
270 .cpu_dai = &omap_mcbsp_dai[1], 276 .cpu_dai_name = "omap-mcbsp-dai.2",
271 .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], 277 .codec_dai_name = "twl4030-voice",
278 .platform_name = "omap-pcm-audio",
279 .codec_name = "twl4030-codec",
272 .init = sdp3430_twl4030_voice_init, 280 .init = sdp3430_twl4030_voice_init,
273 .ops = &sdp3430_voice_ops, 281 .ops = &sdp3430_voice_ops,
274 }, 282 },
@@ -277,25 +285,10 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
277/* Audio machine driver */ 285/* Audio machine driver */
278static struct snd_soc_card snd_soc_sdp3430 = { 286static struct snd_soc_card snd_soc_sdp3430 = {
279 .name = "SDP3430", 287 .name = "SDP3430",
280 .platform = &omap_soc_platform,
281 .dai_link = sdp3430_dai, 288 .dai_link = sdp3430_dai,
282 .num_links = ARRAY_SIZE(sdp3430_dai), 289 .num_links = ARRAY_SIZE(sdp3430_dai),
283}; 290};
284 291
285/* twl4030 setup */
286static struct twl4030_setup_data twl4030_setup = {
287 .ramp_delay_value = 3,
288 .sysclk = 26000,
289 .hs_extmute = 1,
290};
291
292/* Audio subsystem */
293static struct snd_soc_device sdp3430_snd_devdata = {
294 .card = &snd_soc_sdp3430,
295 .codec_dev = &soc_codec_dev_twl4030,
296 .codec_data = &twl4030_setup,
297};
298
299static struct platform_device *sdp3430_snd_device; 292static struct platform_device *sdp3430_snd_device;
300 293
301static int __init sdp3430_soc_init(void) 294static int __init sdp3430_soc_init(void)
@@ -303,10 +296,8 @@ static int __init sdp3430_soc_init(void)
303 int ret; 296 int ret;
304 u8 pin_mux; 297 u8 pin_mux;
305 298
306 if (!machine_is_omap_3430sdp()) { 299 if (!machine_is_omap_3430sdp())
307 pr_debug("Not SDP3430!\n");
308 return -ENODEV; 300 return -ENODEV;
309 }
310 printk(KERN_INFO "SDP3430 SoC init\n"); 301 printk(KERN_INFO "SDP3430 SoC init\n");
311 302
312 sdp3430_snd_device = platform_device_alloc("soc-audio", -1); 303 sdp3430_snd_device = platform_device_alloc("soc-audio", -1);
@@ -315,10 +306,7 @@ static int __init sdp3430_soc_init(void)
315 return -ENOMEM; 306 return -ENOMEM;
316 } 307 }
317 308
318 platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata); 309 platform_set_drvdata(sdp3430_snd_device, &snd_soc_sdp3430);
319 sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev;
320 *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
321 *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
322 310
323 /* Set TWL4030 GPIO6 as EXTMUTE signal */ 311 /* Set TWL4030 GPIO6 as EXTMUTE signal */
324 twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, 312 twl_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux,
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
index 4ebbde6b565f..4b4463db6ba0 100644
--- a/sound/soc/omap/sdp4430.c
+++ b/sound/soc/omap/sdp4430.c
@@ -31,7 +31,6 @@
31#include <plat/mux.h> 31#include <plat/mux.h>
32 32
33#include "mcpdm.h" 33#include "mcpdm.h"
34#include "omap-mcpdm.h"
35#include "omap-pcm.h" 34#include "omap-pcm.h"
36#include "../codecs/twl6040.h" 35#include "../codecs/twl6040.h"
37 36
@@ -41,7 +40,7 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params) 40 struct snd_pcm_hw_params *params)
42{ 41{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data; 42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 43 struct snd_soc_dai *codec_dai = rtd->codec_dai;
45 int clk_id, freq; 44 int clk_id, freq;
46 int ret; 45 int ret;
47 46
@@ -60,6 +59,7 @@ static int sdp4430_hw_params(struct snd_pcm_substream *substream,
60 printk(KERN_ERR "can't set codec system clock\n"); 59 printk(KERN_ERR "can't set codec system clock\n");
61 return ret; 60 return ret;
62 } 61 }
62 return ret;
63} 63}
64 64
65static struct snd_soc_ops sdp4430_ops = { 65static struct snd_soc_ops sdp4430_ops = {
@@ -126,8 +126,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
126 {"Earphone Spk", NULL, "EP"}, 126 {"Earphone Spk", NULL, "EP"},
127}; 127};
128 128
129static int sdp4430_twl6040_init(struct snd_soc_codec *codec) 129static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
130{ 130{
131 struct snd_soc_codec *codec = rtd->codec;
131 int ret; 132 int ret;
132 133
133 /* Add SDP4430 specific controls */ 134 /* Add SDP4430 specific controls */
@@ -164,8 +165,10 @@ static int sdp4430_twl6040_init(struct snd_soc_codec *codec)
164static struct snd_soc_dai_link sdp4430_dai = { 165static struct snd_soc_dai_link sdp4430_dai = {
165 .name = "TWL6040", 166 .name = "TWL6040",
166 .stream_name = "TWL6040", 167 .stream_name = "TWL6040",
167 .cpu_dai = &omap_mcpdm_dai, 168 .cpu_dai_name ="omap-mcpdm-dai",
168 .codec_dai = &twl6040_dai, 169 .codec_dai_name = "twl6040-hifi",
170 .platform_name = "omap-pcm-audio",
171 .codec_name = "twl6040-codec",
169 .init = sdp4430_twl6040_init, 172 .init = sdp4430_twl6040_init,
170 .ops = &sdp4430_ops, 173 .ops = &sdp4430_ops,
171}; 174};
@@ -173,27 +176,18 @@ static struct snd_soc_dai_link sdp4430_dai = {
173/* Audio machine driver */ 176/* Audio machine driver */
174static struct snd_soc_card snd_soc_sdp4430 = { 177static struct snd_soc_card snd_soc_sdp4430 = {
175 .name = "SDP4430", 178 .name = "SDP4430",
176 .platform = &omap_soc_platform,
177 .dai_link = &sdp4430_dai, 179 .dai_link = &sdp4430_dai,
178 .num_links = 1, 180 .num_links = 1,
179}; 181};
180 182
181/* Audio subsystem */
182static struct snd_soc_device sdp4430_snd_devdata = {
183 .card = &snd_soc_sdp4430,
184 .codec_dev = &soc_codec_dev_twl6040,
185};
186
187static struct platform_device *sdp4430_snd_device; 183static struct platform_device *sdp4430_snd_device;
188 184
189static int __init sdp4430_soc_init(void) 185static int __init sdp4430_soc_init(void)
190{ 186{
191 int ret; 187 int ret;
192 188
193 if (!machine_is_omap_4430sdp()) { 189 if (!machine_is_omap_4430sdp())
194 pr_debug("Not SDP4430!\n");
195 return -ENODEV; 190 return -ENODEV;
196 }
197 printk(KERN_INFO "SDP4430 SoC init\n"); 191 printk(KERN_INFO "SDP4430 SoC init\n");
198 192
199 sdp4430_snd_device = platform_device_alloc("soc-audio", -1); 193 sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
@@ -202,8 +196,7 @@ static int __init sdp4430_soc_init(void)
202 return -ENOMEM; 196 return -ENOMEM;
203 } 197 }
204 198
205 platform_set_drvdata(sdp4430_snd_device, &sdp4430_snd_devdata); 199 platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
206 sdp4430_snd_devdata.dev = &sdp4430_snd_device->dev;
207 200
208 ret = platform_device_add(sdp4430_snd_device); 201 ret = platform_device_add(sdp4430_snd_device);
209 if (ret) 202 if (ret)
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
index 50a94ee76ecc..718031eeac34 100644
--- a/sound/soc/omap/zoom2.c
+++ b/sound/soc/omap/zoom2.c
@@ -29,21 +29,23 @@
29#include <asm/mach-types.h> 29#include <asm/mach-types.h>
30#include <mach/hardware.h> 30#include <mach/hardware.h>
31#include <mach/gpio.h> 31#include <mach/gpio.h>
32#include <mach/board-zoom.h>
32#include <plat/mcbsp.h> 33#include <plat/mcbsp.h>
33 34
35/* Register descriptions for twl4030 codec part */
36#include <linux/mfd/twl4030-codec.h>
37
34#include "omap-mcbsp.h" 38#include "omap-mcbsp.h"
35#include "omap-pcm.h" 39#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37 40
38#define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15) 41#define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15)
39#define ZOOM2_HEADSET_EXTMUTE_GPIO 153
40 42
41static int zoom2_hw_params(struct snd_pcm_substream *substream, 43static int zoom2_hw_params(struct snd_pcm_substream *substream,
42 struct snd_pcm_hw_params *params) 44 struct snd_pcm_hw_params *params)
43{ 45{
44 struct snd_soc_pcm_runtime *rtd = substream->private_data; 46 struct snd_soc_pcm_runtime *rtd = substream->private_data;
45 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 47 struct snd_soc_dai *codec_dai = rtd->codec_dai;
46 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 48 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
47 int ret; 49 int ret;
48 50
49 /* Set codec DAI configuration */ 51 /* Set codec DAI configuration */
@@ -85,8 +87,8 @@ static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
85 struct snd_pcm_hw_params *params) 87 struct snd_pcm_hw_params *params)
86{ 88{
87 struct snd_soc_pcm_runtime *rtd = substream->private_data; 89 struct snd_soc_pcm_runtime *rtd = substream->private_data;
88 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 90 struct snd_soc_dai *codec_dai = rtd->codec_dai;
89 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 91 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
90 int ret; 92 int ret;
91 93
92 /* Set codec DAI configuration */ 94 /* Set codec DAI configuration */
@@ -157,8 +159,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
157 {"Aux In", NULL, "AUXR"}, 159 {"Aux In", NULL, "AUXR"},
158}; 160};
159 161
160static int zoom2_twl4030_init(struct snd_soc_codec *codec) 162static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
161{ 163{
164 struct snd_soc_codec *codec = rtd->codec;
162 int ret; 165 int ret;
163 166
164 /* Add Zoom2 specific widgets */ 167 /* Add Zoom2 specific widgets */
@@ -192,14 +195,15 @@ static int zoom2_twl4030_init(struct snd_soc_codec *codec)
192 return ret; 195 return ret;
193} 196}
194 197
195static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec) 198static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
196{ 199{
200 struct snd_soc_codec *codec = rtd->codec;
197 unsigned short reg; 201 unsigned short reg;
198 202
199 /* Enable voice interface */ 203 /* Enable voice interface */
200 reg = codec->read(codec, TWL4030_REG_VOICE_IF); 204 reg = codec->driver->read(codec, TWL4030_REG_VOICE_IF);
201 reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; 205 reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN;
202 codec->write(codec, TWL4030_REG_VOICE_IF, reg); 206 codec->driver->write(codec, TWL4030_REG_VOICE_IF, reg);
203 207
204 return 0; 208 return 0;
205} 209}
@@ -209,16 +213,20 @@ static struct snd_soc_dai_link zoom2_dai[] = {
209 { 213 {
210 .name = "TWL4030 I2S", 214 .name = "TWL4030 I2S",
211 .stream_name = "TWL4030 Audio", 215 .stream_name = "TWL4030 Audio",
212 .cpu_dai = &omap_mcbsp_dai[0], 216 .cpu_dai_name = "omap-mcbsp-dai.1",
213 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], 217 .codec_dai_name = "twl4030-hifi",
218 .platform_name = "omap-pcm-audio",
219 .codec_name = "twl4030-codec",
214 .init = zoom2_twl4030_init, 220 .init = zoom2_twl4030_init,
215 .ops = &zoom2_ops, 221 .ops = &zoom2_ops,
216 }, 222 },
217 { 223 {
218 .name = "TWL4030 PCM", 224 .name = "TWL4030 PCM",
219 .stream_name = "TWL4030 Voice", 225 .stream_name = "TWL4030 Voice",
220 .cpu_dai = &omap_mcbsp_dai[1], 226 .cpu_dai_name = "omap-mcbsp-dai.2",
221 .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], 227 .codec_dai_name = "twl4030-voice",
228 .platform_name = "omap-pcm-audio",
229 .codec_name = "twl4030-codec",
222 .init = zoom2_twl4030_voice_init, 230 .init = zoom2_twl4030_voice_init,
223 .ops = &zoom2_voice_ops, 231 .ops = &zoom2_voice_ops,
224 }, 232 },
@@ -227,42 +235,18 @@ static struct snd_soc_dai_link zoom2_dai[] = {
227/* Audio machine driver */ 235/* Audio machine driver */
228static struct snd_soc_card snd_soc_zoom2 = { 236static struct snd_soc_card snd_soc_zoom2 = {
229 .name = "Zoom2", 237 .name = "Zoom2",
230 .platform = &omap_soc_platform,
231 .dai_link = zoom2_dai, 238 .dai_link = zoom2_dai,
232 .num_links = ARRAY_SIZE(zoom2_dai), 239 .num_links = ARRAY_SIZE(zoom2_dai),
233}; 240};
234 241
235/* EXTMUTE callback function */
236void zoom2_set_hs_extmute(int mute)
237{
238 gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
239}
240
241/* twl4030 setup */
242static struct twl4030_setup_data twl4030_setup = {
243 .ramp_delay_value = 3, /* 161 ms */
244 .sysclk = 26000,
245 .hs_extmute = 1,
246 .set_hs_extmute = zoom2_set_hs_extmute,
247};
248
249/* Audio subsystem */
250static struct snd_soc_device zoom2_snd_devdata = {
251 .card = &snd_soc_zoom2,
252 .codec_dev = &soc_codec_dev_twl4030,
253 .codec_data = &twl4030_setup,
254};
255
256static struct platform_device *zoom2_snd_device; 242static struct platform_device *zoom2_snd_device;
257 243
258static int __init zoom2_soc_init(void) 244static int __init zoom2_soc_init(void)
259{ 245{
260 int ret; 246 int ret;
261 247
262 if (!machine_is_omap_zoom2()) { 248 if (!machine_is_omap_zoom2())
263 pr_debug("Not Zoom2!\n");
264 return -ENODEV; 249 return -ENODEV;
265 }
266 printk(KERN_INFO "Zoom2 SoC init\n"); 250 printk(KERN_INFO "Zoom2 SoC init\n");
267 251
268 zoom2_snd_device = platform_device_alloc("soc-audio", -1); 252 zoom2_snd_device = platform_device_alloc("soc-audio", -1);
@@ -271,11 +255,7 @@ static int __init zoom2_soc_init(void)
271 return -ENOMEM; 255 return -ENOMEM;
272 } 256 }
273 257
274 platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata); 258 platform_set_drvdata(zoom2_snd_device, &snd_soc_zoom2);
275 zoom2_snd_devdata.dev = &zoom2_snd_device->dev;
276 *(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
277 *(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */
278
279 ret = platform_device_add(zoom2_snd_device); 259 ret = platform_device_add(zoom2_snd_device);
280 if (ret) 260 if (ret)
281 goto err1; 261 goto err1;
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index e30c8325f35e..37f191bbfdd9 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -117,6 +117,24 @@ config SND_PXA2XX_SOC_PALM27X
117 Say Y if you want to add support for SoC audio on 117 Say Y if you want to add support for SoC audio on
118 Palm T|X, T5, E2 or LifeDrive handheld computer. 118 Palm T|X, T5, E2 or LifeDrive handheld computer.
119 119
120config SND_SOC_SAARB
121 tristate "SoC Audio support for Marvell Saarb"
122 depends on SND_PXA2XX_SOC && MACH_SAARB
123 select SND_PXA_SOC_SSP
124 select SND_SOC_88PM860X
125 help
126 Say Y if you want to add support for SoC audio on the
127 Marvell Saarb reference platform.
128
129config SND_SOC_TAVOREVB3
130 tristate "SoC Audio support for Marvell Tavor EVB3"
131 depends on SND_PXA2XX_SOC && MACH_TAVOREVB3
132 select SND_PXA_SOC_SSP
133 select SND_SOC_88PM860X
134 help
135 Say Y if you want to add support for SoC audio on the
136 Marvell Saarb reference platform.
137
120config SND_SOC_ZYLONITE 138config SND_SOC_ZYLONITE
121 tristate "SoC Audio support for Marvell Zylonite" 139 tristate "SoC Audio support for Marvell Zylonite"
122 depends on SND_PXA2XX_SOC && MACH_ZYLONITE 140 depends on SND_PXA2XX_SOC && MACH_ZYLONITE
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index caa03d8f4789..07660165ec8d 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -19,6 +19,8 @@ snd-soc-e800-objs := e800_wm9712.o
19snd-soc-spitz-objs := spitz.o 19snd-soc-spitz-objs := spitz.o
20snd-soc-em-x270-objs := em-x270.o 20snd-soc-em-x270-objs := em-x270.o
21snd-soc-palm27x-objs := palm27x.o 21snd-soc-palm27x-objs := palm27x.o
22snd-soc-saarb-objs := saarb.o
23snd-soc-tavorevb3-objs := tavorevb3.o
22snd-soc-zylonite-objs := zylonite.o 24snd-soc-zylonite-objs := zylonite.o
23snd-soc-magician-objs := magician.o 25snd-soc-magician-objs := magician.o
24snd-soc-mioa701-objs := mioa701_wm9713.o 26snd-soc-mioa701-objs := mioa701_wm9713.o
@@ -38,6 +40,8 @@ obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
38obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o 40obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
39obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o 41obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
40obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o 42obj-$(CONFIG_SND_PXA2XX_SOC_Z2) += snd-soc-z2.o
43obj-$(CONFIG_SND_SOC_SAARB) += snd-soc-saarb.o
44obj-$(CONFIG_SND_SOC_TAVOREVB3) += snd-soc-tavorevb3.o
41obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o 45obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
42obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o 46obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
43obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o 47obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index fefe1a57f31a..97e9423615c9 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -30,7 +30,6 @@
30#include <mach/audio.h> 30#include <mach/audio.h>
31 31
32#include "../codecs/wm8731.h" 32#include "../codecs/wm8731.h"
33#include "pxa2xx-pcm.h"
34#include "pxa2xx-i2s.h" 33#include "pxa2xx-i2s.h"
35 34
36#define CORGI_HP 0 35#define CORGI_HP 0
@@ -99,7 +98,7 @@ static void corgi_ext_control(struct snd_soc_codec *codec)
99static int corgi_startup(struct snd_pcm_substream *substream) 98static int corgi_startup(struct snd_pcm_substream *substream)
100{ 99{
101 struct snd_soc_pcm_runtime *rtd = substream->private_data; 100 struct snd_soc_pcm_runtime *rtd = substream->private_data;
102 struct snd_soc_codec *codec = rtd->socdev->card->codec; 101 struct snd_soc_codec *codec = rtd->codec;
103 102
104 /* check the jack status at stream startup */ 103 /* check the jack status at stream startup */
105 corgi_ext_control(codec); 104 corgi_ext_control(codec);
@@ -118,8 +117,8 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
118 struct snd_pcm_hw_params *params) 117 struct snd_pcm_hw_params *params)
119{ 118{
120 struct snd_soc_pcm_runtime *rtd = substream->private_data; 119 struct snd_soc_pcm_runtime *rtd = substream->private_data;
121 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 120 struct snd_soc_dai *codec_dai = rtd->codec_dai;
122 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 121 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
123 unsigned int clk = 0; 122 unsigned int clk = 0;
124 int ret = 0; 123 int ret = 0;
125 124
@@ -150,7 +149,7 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
150 return ret; 149 return ret;
151 150
152 /* set the codec system clock for DAC and ADC */ 151 /* set the codec system clock for DAC and ADC */
153 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, 152 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
154 SND_SOC_CLOCK_IN); 153 SND_SOC_CLOCK_IN);
155 if (ret < 0) 154 if (ret < 0)
156 return ret; 155 return ret;
@@ -272,8 +271,9 @@ static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
272/* 271/*
273 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device 272 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
274 */ 273 */
275static int corgi_wm8731_init(struct snd_soc_codec *codec) 274static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd)
276{ 275{
276 struct snd_soc_codec *codec = rtd->codec;
277 int err; 277 int err;
278 278
279 snd_soc_dapm_nc_pin(codec, "LLINEIN"); 279 snd_soc_dapm_nc_pin(codec, "LLINEIN");
@@ -300,8 +300,10 @@ static int corgi_wm8731_init(struct snd_soc_codec *codec)
300static struct snd_soc_dai_link corgi_dai = { 300static struct snd_soc_dai_link corgi_dai = {
301 .name = "WM8731", 301 .name = "WM8731",
302 .stream_name = "WM8731", 302 .stream_name = "WM8731",
303 .cpu_dai = &pxa_i2s_dai, 303 .cpu_dai_name = "pxa-is2-dai",
304 .codec_dai = &wm8731_dai, 304 .codec_dai_name = "wm8731-hifi",
305 .platform_name = "pxa-pcm-audio",
306 .codec_name = "wm8731-codec-0.001a",
305 .init = corgi_wm8731_init, 307 .init = corgi_wm8731_init,
306 .ops = &corgi_ops, 308 .ops = &corgi_ops,
307}; 309};
@@ -309,17 +311,10 @@ static struct snd_soc_dai_link corgi_dai = {
309/* corgi audio machine driver */ 311/* corgi audio machine driver */
310static struct snd_soc_card snd_soc_corgi = { 312static struct snd_soc_card snd_soc_corgi = {
311 .name = "Corgi", 313 .name = "Corgi",
312 .platform = &pxa2xx_soc_platform,
313 .dai_link = &corgi_dai, 314 .dai_link = &corgi_dai,
314 .num_links = 1, 315 .num_links = 1,
315}; 316};
316 317
317/* corgi audio subsystem */
318static struct snd_soc_device corgi_snd_devdata = {
319 .card = &snd_soc_corgi,
320 .codec_dev = &soc_codec_dev_wm8731,
321};
322
323static struct platform_device *corgi_snd_device; 318static struct platform_device *corgi_snd_device;
324 319
325static int __init corgi_init(void) 320static int __init corgi_init(void)
@@ -334,8 +329,7 @@ static int __init corgi_init(void)
334 if (!corgi_snd_device) 329 if (!corgi_snd_device)
335 return -ENOMEM; 330 return -ENOMEM;
336 331
337 platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata); 332 platform_set_drvdata(corgi_snd_device, &snd_soc_corgi);
338 corgi_snd_devdata.dev = &corgi_snd_device->dev;
339 ret = platform_device_add(corgi_snd_device); 333 ret = platform_device_add(corgi_snd_device);
340 334
341 if (ret) 335 if (ret)
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
index 7cd2f89d7b10..c82cedb602fd 100644
--- a/sound/soc/pxa/e740_wm9705.c
+++ b/sound/soc/pxa/e740_wm9705.c
@@ -24,7 +24,6 @@
24#include <asm/mach-types.h> 24#include <asm/mach-types.h>
25 25
26#include "../codecs/wm9705.h" 26#include "../codecs/wm9705.h"
27#include "pxa2xx-pcm.h"
28#include "pxa2xx-ac97.h" 27#include "pxa2xx-ac97.h"
29 28
30 29
@@ -90,8 +89,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
90 {"Mic Amp", NULL, "Mic (Internal)"}, 89 {"Mic Amp", NULL, "Mic (Internal)"},
91}; 90};
92 91
93static int e740_ac97_init(struct snd_soc_codec *codec) 92static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd)
94{ 93{
94 struct snd_soc_codec *codec = rtd->codec;
95
95 snd_soc_dapm_nc_pin(codec, "HPOUTL"); 96 snd_soc_dapm_nc_pin(codec, "HPOUTL");
96 snd_soc_dapm_nc_pin(codec, "HPOUTR"); 97 snd_soc_dapm_nc_pin(codec, "HPOUTR");
97 snd_soc_dapm_nc_pin(codec, "PHONE"); 98 snd_soc_dapm_nc_pin(codec, "PHONE");
@@ -116,30 +117,28 @@ static struct snd_soc_dai_link e740_dai[] = {
116 { 117 {
117 .name = "AC97", 118 .name = "AC97",
118 .stream_name = "AC97 HiFi", 119 .stream_name = "AC97 HiFi",
119 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 120 .cpu_dai_name = "pxa-ac97.0",
120 .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], 121 .codec_dai_name = "wm9705-hifi",
122 .platform_name = "pxa-pcm-audio",
123 .codec_name = "wm9705-codec",
121 .init = e740_ac97_init, 124 .init = e740_ac97_init,
122 }, 125 },
123 { 126 {
124 .name = "AC97 Aux", 127 .name = "AC97 Aux",
125 .stream_name = "AC97 Aux", 128 .stream_name = "AC97 Aux",
126 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 129 .cpu_dai_name = "pxa-ac97.1",
127 .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], 130 .codec_dai_name = "wm9705-aux",
131 .platform_name = "pxa-pcm-audio",
132 .codec_name = "wm9705-codec",
128 }, 133 },
129}; 134};
130 135
131static struct snd_soc_card e740 = { 136static struct snd_soc_card e740 = {
132 .name = "Toshiba e740", 137 .name = "Toshiba e740",
133 .platform = &pxa2xx_soc_platform,
134 .dai_link = e740_dai, 138 .dai_link = e740_dai,
135 .num_links = ARRAY_SIZE(e740_dai), 139 .num_links = ARRAY_SIZE(e740_dai),
136}; 140};
137 141
138static struct snd_soc_device e740_snd_devdata = {
139 .card = &e740,
140 .codec_dev = &soc_codec_dev_wm9705,
141};
142
143static struct platform_device *e740_snd_device; 142static struct platform_device *e740_snd_device;
144 143
145static int __init e740_init(void) 144static int __init e740_init(void)
@@ -178,8 +177,7 @@ static int __init e740_init(void)
178 goto free_apwr_gpio; 177 goto free_apwr_gpio;
179 } 178 }
180 179
181 platform_set_drvdata(e740_snd_device, &e740_snd_devdata); 180 platform_set_drvdata(e740_snd_device, &e740);
182 e740_snd_devdata.dev = &e740_snd_device->dev;
183 ret = platform_device_add(e740_snd_device); 181 ret = platform_device_add(e740_snd_device);
184 182
185 if (!ret) 183 if (!ret)
@@ -200,6 +198,9 @@ free_mic_amp_gpio:
200static void __exit e740_exit(void) 198static void __exit e740_exit(void)
201{ 199{
202 platform_device_unregister(e740_snd_device); 200 platform_device_unregister(e740_snd_device);
201 gpio_free(GPIO_E740_WM9705_nAVDD2);
202 gpio_free(GPIO_E740_AMP_ON);
203 gpio_free(GPIO_E740_MIC_ON);
203} 204}
204 205
205module_init(e740_init); 206module_init(e740_init);
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
index 8dceccc5e059..4c143803a75e 100644
--- a/sound/soc/pxa/e750_wm9705.c
+++ b/sound/soc/pxa/e750_wm9705.c
@@ -24,7 +24,6 @@
24#include <asm/mach-types.h> 24#include <asm/mach-types.h>
25 25
26#include "../codecs/wm9705.h" 26#include "../codecs/wm9705.h"
27#include "pxa2xx-pcm.h"
28#include "pxa2xx-ac97.h" 27#include "pxa2xx-ac97.h"
29 28
30static int e750_spk_amp_event(struct snd_soc_dapm_widget *w, 29static int e750_spk_amp_event(struct snd_soc_dapm_widget *w,
@@ -72,8 +71,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
72 {"MIC1", NULL, "Mic (Internal)"}, 71 {"MIC1", NULL, "Mic (Internal)"},
73}; 72};
74 73
75static int e750_ac97_init(struct snd_soc_codec *codec) 74static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd)
76{ 75{
76 struct snd_soc_codec *codec = rtd->codec;
77
77 snd_soc_dapm_nc_pin(codec, "LOUT"); 78 snd_soc_dapm_nc_pin(codec, "LOUT");
78 snd_soc_dapm_nc_pin(codec, "ROUT"); 79 snd_soc_dapm_nc_pin(codec, "ROUT");
79 snd_soc_dapm_nc_pin(codec, "PHONE"); 80 snd_soc_dapm_nc_pin(codec, "PHONE");
@@ -98,31 +99,29 @@ static struct snd_soc_dai_link e750_dai[] = {
98 { 99 {
99 .name = "AC97", 100 .name = "AC97",
100 .stream_name = "AC97 HiFi", 101 .stream_name = "AC97 HiFi",
101 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 102 .cpu_dai_name = "pxa-ac97.0",
102 .codec_dai = &wm9705_dai[WM9705_DAI_AC97_HIFI], 103 .codec_dai_name = "wm9705-hifi",
104 .platform_name = "pxa-pcm-audio",
105 .codec_name = "wm9705-codec",
103 .init = e750_ac97_init, 106 .init = e750_ac97_init,
104 /* use ops to check startup state */ 107 /* use ops to check startup state */
105 }, 108 },
106 { 109 {
107 .name = "AC97 Aux", 110 .name = "AC97 Aux",
108 .stream_name = "AC97 Aux", 111 .stream_name = "AC97 Aux",
109 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 112 .cpu_dai_name = "pxa-ac97.1",
110 .codec_dai = &wm9705_dai[WM9705_DAI_AC97_AUX], 113 .codec_dai_name ="wm9705-aux",
114 .platform_name = "pxa-pcm-audio",
115 .codec_name = "wm9705-codec",
111 }, 116 },
112}; 117};
113 118
114static struct snd_soc_card e750 = { 119static struct snd_soc_card e750 = {
115 .name = "Toshiba e750", 120 .name = "Toshiba e750",
116 .platform = &pxa2xx_soc_platform,
117 .dai_link = e750_dai, 121 .dai_link = e750_dai,
118 .num_links = ARRAY_SIZE(e750_dai), 122 .num_links = ARRAY_SIZE(e750_dai),
119}; 123};
120 124
121static struct snd_soc_device e750_snd_devdata = {
122 .card = &e750,
123 .codec_dev = &soc_codec_dev_wm9705,
124};
125
126static struct platform_device *e750_snd_device; 125static struct platform_device *e750_snd_device;
127 126
128static int __init e750_init(void) 127static int __init e750_init(void)
@@ -154,8 +153,7 @@ static int __init e750_init(void)
154 goto free_spk_amp_gpio; 153 goto free_spk_amp_gpio;
155 } 154 }
156 155
157 platform_set_drvdata(e750_snd_device, &e750_snd_devdata); 156 platform_set_drvdata(e750_snd_device, &e750);
158 e750_snd_devdata.dev = &e750_snd_device->dev;
159 ret = platform_device_add(e750_snd_device); 157 ret = platform_device_add(e750_snd_device);
160 158
161 if (!ret) 159 if (!ret)
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index bc019cdce429..d42e5fe832c5 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -23,7 +23,6 @@
23#include <mach/eseries-gpio.h> 23#include <mach/eseries-gpio.h>
24 24
25#include "../codecs/wm9712.h" 25#include "../codecs/wm9712.h"
26#include "pxa2xx-pcm.h"
27#include "pxa2xx-ac97.h" 26#include "pxa2xx-ac97.h"
28 27
29static int e800_spk_amp_event(struct snd_soc_dapm_widget *w, 28static int e800_spk_amp_event(struct snd_soc_dapm_widget *w,
@@ -73,8 +72,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
73 {"MIC2", NULL, "Mic (Internal2)"}, 72 {"MIC2", NULL, "Mic (Internal2)"},
74}; 73};
75 74
76static int e800_ac97_init(struct snd_soc_codec *codec) 75static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd)
77{ 76{
77 struct snd_soc_codec *codec = rtd->codec;
78
78 snd_soc_dapm_new_controls(codec, e800_dapm_widgets, 79 snd_soc_dapm_new_controls(codec, e800_dapm_widgets,
79 ARRAY_SIZE(e800_dapm_widgets)); 80 ARRAY_SIZE(e800_dapm_widgets));
80 81
@@ -88,30 +89,28 @@ static struct snd_soc_dai_link e800_dai[] = {
88 { 89 {
89 .name = "AC97", 90 .name = "AC97",
90 .stream_name = "AC97 HiFi", 91 .stream_name = "AC97 HiFi",
91 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 92 .cpu_dai_name = "pxa-ac97.0",
92 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 93 .codec_dai_name = "wm9712-hifi",
94 .platform_name = "pxa-pcm-audio",
95 .codec_name = "wm9712-codec",
93 .init = e800_ac97_init, 96 .init = e800_ac97_init,
94 }, 97 },
95 { 98 {
96 .name = "AC97 Aux", 99 .name = "AC97 Aux",
97 .stream_name = "AC97 Aux", 100 .stream_name = "AC97 Aux",
98 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 101 .cpu_dai_name = "pxa-ac97.1",
99 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 102 .codec_dai_name ="wm9712-aux",
103 .platform_name = "pxa-pcm-audio",
104 .codec_name = "wm9712-codec",
100 }, 105 },
101}; 106};
102 107
103static struct snd_soc_card e800 = { 108static struct snd_soc_card e800 = {
104 .name = "Toshiba e800", 109 .name = "Toshiba e800",
105 .platform = &pxa2xx_soc_platform,
106 .dai_link = e800_dai, 110 .dai_link = e800_dai,
107 .num_links = ARRAY_SIZE(e800_dai), 111 .num_links = ARRAY_SIZE(e800_dai),
108}; 112};
109 113
110static struct snd_soc_device e800_snd_devdata = {
111 .card = &e800,
112 .codec_dev = &soc_codec_dev_wm9712,
113};
114
115static struct platform_device *e800_snd_device; 114static struct platform_device *e800_snd_device;
116 115
117static int __init e800_init(void) 116static int __init e800_init(void)
@@ -141,8 +140,7 @@ static int __init e800_init(void)
141 if (!e800_snd_device) 140 if (!e800_snd_device)
142 return -ENOMEM; 141 return -ENOMEM;
143 142
144 platform_set_drvdata(e800_snd_device, &e800_snd_devdata); 143 platform_set_drvdata(e800_snd_device, &e800);
145 e800_snd_devdata.dev = &e800_snd_device->dev;
146 ret = platform_device_add(e800_snd_device); 144 ret = platform_device_add(e800_snd_device);
147 145
148 if (!ret) 146 if (!ret)
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index f4756e4025fd..eadf9d351a04 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -32,36 +32,33 @@
32#include <mach/audio.h> 32#include <mach/audio.h>
33 33
34#include "../codecs/wm9712.h" 34#include "../codecs/wm9712.h"
35#include "pxa2xx-pcm.h"
36#include "pxa2xx-ac97.h" 35#include "pxa2xx-ac97.h"
37 36
38static struct snd_soc_dai_link em_x270_dai[] = { 37static struct snd_soc_dai_link em_x270_dai[] = {
39 { 38 {
40 .name = "AC97", 39 .name = "AC97",
41 .stream_name = "AC97 HiFi", 40 .stream_name = "AC97 HiFi",
42 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 41 .cpu_dai_name = "pxa-ac97.0",
43 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 42 .codec_dai_name = "wm9712-hifi",
43 .platform_name = "pxa-pcm-audio",
44 .codec_name = "wm9712-codec",
44 }, 45 },
45 { 46 {
46 .name = "AC97 Aux", 47 .name = "AC97 Aux",
47 .stream_name = "AC97 Aux", 48 .stream_name = "AC97 Aux",
48 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 49 .cpu_dai_name = "pxa-ac97.1",
49 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 50 .codec_dai_name ="wm9712-aux",
51 .platform_name = "pxa-pcm-audio",
52 .codec_name = "wm9712-codec",
50 }, 53 },
51}; 54};
52 55
53static struct snd_soc_card em_x270 = { 56static struct snd_soc_card em_x270 = {
54 .name = "EM-X270", 57 .name = "EM-X270",
55 .platform = &pxa2xx_soc_platform,
56 .dai_link = em_x270_dai, 58 .dai_link = em_x270_dai,
57 .num_links = ARRAY_SIZE(em_x270_dai), 59 .num_links = ARRAY_SIZE(em_x270_dai),
58}; 60};
59 61
60static struct snd_soc_device em_x270_snd_devdata = {
61 .card = &em_x270,
62 .codec_dev = &soc_codec_dev_wm9712,
63};
64
65static struct platform_device *em_x270_snd_device; 62static struct platform_device *em_x270_snd_device;
66 63
67static int __init em_x270_init(void) 64static int __init em_x270_init(void)
@@ -76,8 +73,7 @@ static int __init em_x270_init(void)
76 if (!em_x270_snd_device) 73 if (!em_x270_snd_device)
77 return -ENOMEM; 74 return -ENOMEM;
78 75
79 platform_set_drvdata(em_x270_snd_device, &em_x270_snd_devdata); 76 platform_set_drvdata(em_x270_snd_device, &em_x270);
80 em_x270_snd_devdata.dev = &em_x270_snd_device->dev;
81 ret = platform_device_add(em_x270_snd_device); 77 ret = platform_device_add(em_x270_snd_device);
82 78
83 if (ret) 79 if (ret)
diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c
index 405587a01160..154fc6f23438 100644
--- a/sound/soc/pxa/imote2.c
+++ b/sound/soc/pxa/imote2.c
@@ -6,14 +6,13 @@
6 6
7#include "../codecs/wm8940.h" 7#include "../codecs/wm8940.h"
8#include "pxa2xx-i2s.h" 8#include "pxa2xx-i2s.h"
9#include "pxa2xx-pcm.h"
10 9
11static int imote2_asoc_hw_params(struct snd_pcm_substream *substream, 10static int imote2_asoc_hw_params(struct snd_pcm_substream *substream,
12 struct snd_pcm_hw_params *params) 11 struct snd_pcm_hw_params *params)
13{ 12{
14 struct snd_soc_pcm_runtime *rtd = substream->private_data; 13 struct snd_soc_pcm_runtime *rtd = substream->private_data;
15 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 14 struct snd_soc_dai *codec_dai = rtd->codec_dai;
16 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 15 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
17 unsigned int clk = 0; 16 unsigned int clk = 0;
18 int ret; 17 int ret;
19 18
@@ -64,23 +63,19 @@ static struct snd_soc_ops imote2_asoc_ops = {
64static struct snd_soc_dai_link imote2_dai = { 63static struct snd_soc_dai_link imote2_dai = {
65 .name = "WM8940", 64 .name = "WM8940",
66 .stream_name = "WM8940", 65 .stream_name = "WM8940",
67 .cpu_dai = &pxa_i2s_dai, 66 .cpu_dai_name = "pxa2xx-i2s",
68 .codec_dai = &wm8940_dai, 67 .codec_dai_name = "wm8940-hifi",
68 .platform_name = "pxa-pcm-audio",
69 .codec_name = "wm8940-codec.0-0034",
69 .ops = &imote2_asoc_ops, 70 .ops = &imote2_asoc_ops,
70}; 71};
71 72
72static struct snd_soc_card snd_soc_imote2 = { 73static struct snd_soc_card snd_soc_imote2 = {
73 .name = "Imote2", 74 .name = "Imote2",
74 .platform = &pxa2xx_soc_platform,
75 .dai_link = &imote2_dai, 75 .dai_link = &imote2_dai,
76 .num_links = 1, 76 .num_links = 1,
77}; 77};
78 78
79static struct snd_soc_device imote2_snd_devdata = {
80 .card = &snd_soc_imote2,
81 .codec_dev = &soc_codec_dev_wm8940,
82};
83
84static struct platform_device *imote2_snd_device; 79static struct platform_device *imote2_snd_device;
85 80
86static int __init imote2_asoc_init(void) 81static int __init imote2_asoc_init(void)
@@ -93,8 +88,7 @@ static int __init imote2_asoc_init(void)
93 if (!imote2_snd_device) 88 if (!imote2_snd_device)
94 return -ENOMEM; 89 return -ENOMEM;
95 90
96 platform_set_drvdata(imote2_snd_device, &imote2_snd_devdata); 91 platform_set_drvdata(imote2_snd_device, &snd_soc_imote2);
97 imote2_snd_devdata.dev = &imote2_snd_device->dev;
98 ret = platform_device_add(imote2_snd_device); 92 ret = platform_device_add(imote2_snd_device);
99 if (ret) 93 if (ret)
100 platform_device_put(imote2_snd_device); 94 platform_device_put(imote2_snd_device);
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 4c8d99a8d386..b8207ced4072 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -32,7 +32,6 @@
32#include <mach/magician.h> 32#include <mach/magician.h>
33#include <asm/mach-types.h> 33#include <asm/mach-types.h>
34#include "../codecs/uda1380.h" 34#include "../codecs/uda1380.h"
35#include "pxa2xx-pcm.h"
36#include "pxa2xx-i2s.h" 35#include "pxa2xx-i2s.h"
37#include "pxa-ssp.h" 36#include "pxa-ssp.h"
38 37
@@ -71,7 +70,7 @@ static void magician_ext_control(struct snd_soc_codec *codec)
71static int magician_startup(struct snd_pcm_substream *substream) 70static int magician_startup(struct snd_pcm_substream *substream)
72{ 71{
73 struct snd_soc_pcm_runtime *rtd = substream->private_data; 72 struct snd_soc_pcm_runtime *rtd = substream->private_data;
74 struct snd_soc_codec *codec = rtd->socdev->card->codec; 73 struct snd_soc_codec *codec = rtd->codec;
75 74
76 /* check the jack status at stream startup */ 75 /* check the jack status at stream startup */
77 magician_ext_control(codec); 76 magician_ext_control(codec);
@@ -86,8 +85,8 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
86 struct snd_pcm_hw_params *params) 85 struct snd_pcm_hw_params *params)
87{ 86{
88 struct snd_soc_pcm_runtime *rtd = substream->private_data; 87 struct snd_soc_pcm_runtime *rtd = substream->private_data;
89 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 88 struct snd_soc_dai *codec_dai = rtd->codec_dai;
90 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 89 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
91 unsigned int acps, acds, width, rate; 90 unsigned int acps, acds, width, rate;
92 unsigned int div4 = PXA_SSP_CLK_SCDB_4; 91 unsigned int div4 = PXA_SSP_CLK_SCDB_4;
93 int ret = 0; 92 int ret = 0;
@@ -227,8 +226,8 @@ static int magician_capture_hw_params(struct snd_pcm_substream *substream,
227 struct snd_pcm_hw_params *params) 226 struct snd_pcm_hw_params *params)
228{ 227{
229 struct snd_soc_pcm_runtime *rtd = substream->private_data; 228 struct snd_soc_pcm_runtime *rtd = substream->private_data;
230 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 229 struct snd_soc_dai *codec_dai = rtd->codec_dai;
231 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 230 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
232 int ret = 0; 231 int ret = 0;
233 232
234 /* set codec DAI configuration */ 233 /* set codec DAI configuration */
@@ -393,8 +392,9 @@ static const struct snd_kcontrol_new uda1380_magician_controls[] = {
393/* 392/*
394 * Logic for a uda1380 as connected on a HTC Magician 393 * Logic for a uda1380 as connected on a HTC Magician
395 */ 394 */
396static int magician_uda1380_init(struct snd_soc_codec *codec) 395static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
397{ 396{
397 struct snd_soc_codec *codec = rtd->codec;
398 int err; 398 int err;
399 399
400 /* NC codec pins */ 400 /* NC codec pins */
@@ -427,16 +427,20 @@ static struct snd_soc_dai_link magician_dai[] = {
427{ 427{
428 .name = "uda1380", 428 .name = "uda1380",
429 .stream_name = "UDA1380 Playback", 429 .stream_name = "UDA1380 Playback",
430 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1], 430 .cpu_dai_name = "pxa-ssp-dai.0",
431 .codec_dai = &uda1380_dai[UDA1380_DAI_PLAYBACK], 431 .codec_dai_name = "uda1380-hifi-playback",
432 .platform_name = "pxa-pcm-audio",
433 .codec_name = "uda1380-codec.0-0018",
432 .init = magician_uda1380_init, 434 .init = magician_uda1380_init,
433 .ops = &magician_playback_ops, 435 .ops = &magician_playback_ops,
434}, 436},
435{ 437{
436 .name = "uda1380", 438 .name = "uda1380",
437 .stream_name = "UDA1380 Capture", 439 .stream_name = "UDA1380 Capture",
438 .cpu_dai = &pxa_i2s_dai, 440 .cpu_dai_name = "pxa2xx-i2s",
439 .codec_dai = &uda1380_dai[UDA1380_DAI_CAPTURE], 441 .codec_dai_name = "uda1380-hifi-capture",
442 .platform_name = "pxa-pcm-audio",
443 .codec_name = "uda1380-codec.0-0018",
440 .ops = &magician_capture_ops, 444 .ops = &magician_capture_ops,
441} 445}
442}; 446};
@@ -446,13 +450,7 @@ static struct snd_soc_card snd_soc_card_magician = {
446 .name = "Magician", 450 .name = "Magician",
447 .dai_link = magician_dai, 451 .dai_link = magician_dai,
448 .num_links = ARRAY_SIZE(magician_dai), 452 .num_links = ARRAY_SIZE(magician_dai),
449 .platform = &pxa2xx_soc_platform,
450};
451 453
452/* magician audio subsystem */
453static struct snd_soc_device magician_snd_devdata = {
454 .card = &snd_soc_card_magician,
455 .codec_dev = &soc_codec_dev_uda1380,
456}; 454};
457 455
458static struct platform_device *magician_snd_device; 456static struct platform_device *magician_snd_device;
@@ -514,8 +512,7 @@ static int __init magician_init(void)
514 goto err_pdev; 512 goto err_pdev;
515 } 513 }
516 514
517 platform_set_drvdata(magician_snd_device, &magician_snd_devdata); 515 platform_set_drvdata(magician_snd_device, &snd_soc_card_magician);
518 magician_snd_devdata.dev = &magician_snd_device->dev;
519 ret = platform_device_add(magician_snd_device); 516 ret = platform_device_add(magician_snd_device);
520 if (ret) { 517 if (ret) {
521 platform_device_put(magician_snd_device); 518 platform_device_put(magician_snd_device);
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 19eda8bbfdaf..f284cc54bc80 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -54,7 +54,6 @@
54#include <sound/initval.h> 54#include <sound/initval.h>
55#include <sound/ac97_codec.h> 55#include <sound/ac97_codec.h>
56 56
57#include "pxa2xx-pcm.h"
58#include "pxa2xx-ac97.h" 57#include "pxa2xx-ac97.h"
59#include "../codecs/wm9713.h" 58#include "../codecs/wm9713.h"
60 59
@@ -128,8 +127,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
128 {"Rear Speaker", NULL, "SPKR"}, 127 {"Rear Speaker", NULL, "SPKR"},
129}; 128};
130 129
131static int mioa701_wm9713_init(struct snd_soc_codec *codec) 130static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)
132{ 131{
132 struct snd_soc_codec *codec = rtd->codec;
133 unsigned short reg; 133 unsigned short reg;
134 134
135 /* Add mioa701 specific widgets */ 135 /* Add mioa701 specific widgets */
@@ -139,12 +139,12 @@ static int mioa701_wm9713_init(struct snd_soc_codec *codec)
139 snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map)); 139 snd_soc_dapm_add_routes(codec, ARRAY_AND_SIZE(audio_map));
140 140
141 /* Prepare GPIO8 for rear speaker amplifier */ 141 /* Prepare GPIO8 for rear speaker amplifier */
142 reg = codec->read(codec, AC97_GPIO_CFG); 142 reg = codec->driver->read(codec, AC97_GPIO_CFG);
143 codec->write(codec, AC97_GPIO_CFG, reg | 0x0100); 143 codec->driver->write(codec, AC97_GPIO_CFG, reg | 0x0100);
144 144
145 /* Prepare MIC input */ 145 /* Prepare MIC input */
146 reg = codec->read(codec, AC97_3D_CONTROL); 146 reg = codec->driver->read(codec, AC97_3D_CONTROL);
147 codec->write(codec, AC97_3D_CONTROL, reg | 0xc000); 147 codec->driver->write(codec, AC97_3D_CONTROL, reg | 0xc000);
148 148
149 snd_soc_dapm_enable_pin(codec, "Front Speaker"); 149 snd_soc_dapm_enable_pin(codec, "Front Speaker");
150 snd_soc_dapm_enable_pin(codec, "Rear Speaker"); 150 snd_soc_dapm_enable_pin(codec, "Rear Speaker");
@@ -162,32 +162,30 @@ static struct snd_soc_dai_link mioa701_dai[] = {
162 { 162 {
163 .name = "AC97", 163 .name = "AC97",
164 .stream_name = "AC97 HiFi", 164 .stream_name = "AC97 HiFi",
165 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 165 .cpu_dai_name = "pxa-ac97.0",
166 .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], 166 .codec_dai_name = "wm9713-hifi",
167 .codec_name = "wm9713-codec",
167 .init = mioa701_wm9713_init, 168 .init = mioa701_wm9713_init,
169 .platform_name = "pxa-pcm-audio",
168 .ops = &mioa701_ops, 170 .ops = &mioa701_ops,
169 }, 171 },
170 { 172 {
171 .name = "AC97 Aux", 173 .name = "AC97 Aux",
172 .stream_name = "AC97 Aux", 174 .stream_name = "AC97 Aux",
173 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 175 .cpu_dai_name = "pxa-ac97.1",
174 .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], 176 .codec_dai_name ="wm9713-aux",
177 .codec_name = "wm9713-codec",
178 .platform_name = "pxa-pcm-audio",
175 .ops = &mioa701_ops, 179 .ops = &mioa701_ops,
176 }, 180 },
177}; 181};
178 182
179static struct snd_soc_card mioa701 = { 183static struct snd_soc_card mioa701 = {
180 .name = "MioA701", 184 .name = "MioA701",
181 .platform = &pxa2xx_soc_platform,
182 .dai_link = mioa701_dai, 185 .dai_link = mioa701_dai,
183 .num_links = ARRAY_SIZE(mioa701_dai), 186 .num_links = ARRAY_SIZE(mioa701_dai),
184}; 187};
185 188
186static struct snd_soc_device mioa701_snd_devdata = {
187 .card = &mioa701,
188 .codec_dev = &soc_codec_dev_wm9713,
189};
190
191static struct platform_device *mioa701_snd_device; 189static struct platform_device *mioa701_snd_device;
192 190
193static int mioa701_wm9713_probe(struct platform_device *pdev) 191static int mioa701_wm9713_probe(struct platform_device *pdev)
@@ -205,8 +203,7 @@ static int mioa701_wm9713_probe(struct platform_device *pdev)
205 if (!mioa701_snd_device) 203 if (!mioa701_snd_device)
206 return -ENOMEM; 204 return -ENOMEM;
207 205
208 platform_set_drvdata(mioa701_snd_device, &mioa701_snd_devdata); 206 platform_set_drvdata(mioa701_snd_device, &mioa701);
209 mioa701_snd_devdata.dev = &mioa701_snd_device->dev;
210 207
211 ret = platform_device_add(mioa701_snd_device); 208 ret = platform_device_add(mioa701_snd_device);
212 if (!ret) 209 if (!ret)
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 1f96e3227be5..13f6d485d571 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -29,7 +29,6 @@
29#include <mach/palmasoc.h> 29#include <mach/palmasoc.h>
30 30
31#include "../codecs/wm9712.h" 31#include "../codecs/wm9712.h"
32#include "pxa2xx-pcm.h"
33#include "pxa2xx-ac97.h" 32#include "pxa2xx-ac97.h"
34 33
35static struct snd_soc_jack hs_jack; 34static struct snd_soc_jack hs_jack;
@@ -75,8 +74,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
75 74
76static struct snd_soc_card palm27x_asoc; 75static struct snd_soc_card palm27x_asoc;
77 76
78static int palm27x_ac97_init(struct snd_soc_codec *codec) 77static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
79{ 78{
79 struct snd_soc_codec *codec = rtd->codec;
80 int err; 80 int err;
81 81
82 /* add palm27x specific widgets */ 82 /* add palm27x specific widgets */
@@ -112,7 +112,7 @@ static int palm27x_ac97_init(struct snd_soc_codec *codec)
112 return err; 112 return err;
113 113
114 /* Jack detection API stuff */ 114 /* Jack detection API stuff */
115 err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack", 115 err = snd_soc_jack_new(codec, "Headphone Jack",
116 SND_JACK_HEADPHONE, &hs_jack); 116 SND_JACK_HEADPHONE, &hs_jack);
117 if (err) 117 if (err)
118 return err; 118 return err;
@@ -132,30 +132,28 @@ static struct snd_soc_dai_link palm27x_dai[] = {
132{ 132{
133 .name = "AC97 HiFi", 133 .name = "AC97 HiFi",
134 .stream_name = "AC97 HiFi", 134 .stream_name = "AC97 HiFi",
135 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 135 .cpu_dai_name = "pxa-ac97.0",
136 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 136 .codec_dai_name = "wm9712-hifi",
137 .codec_name = "wm9712-codec",
138 .platform_name = "pxa-pcm-audio",
137 .init = palm27x_ac97_init, 139 .init = palm27x_ac97_init,
138}, 140},
139{ 141{
140 .name = "AC97 Aux", 142 .name = "AC97 Aux",
141 .stream_name = "AC97 Aux", 143 .stream_name = "AC97 Aux",
142 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 144 .cpu_dai_name = "pxa-ac97.1",
143 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 145 .codec_dai_name = "wm9712-aux",
146 .codec_name = "wm9712-codec",
147 .platform_name = "pxa-pcm-audio",
144}, 148},
145}; 149};
146 150
147static struct snd_soc_card palm27x_asoc = { 151static struct snd_soc_card palm27x_asoc = {
148 .name = "Palm/PXA27x", 152 .name = "Palm/PXA27x",
149 .platform = &pxa2xx_soc_platform,
150 .dai_link = palm27x_dai, 153 .dai_link = palm27x_dai,
151 .num_links = ARRAY_SIZE(palm27x_dai), 154 .num_links = ARRAY_SIZE(palm27x_dai),
152}; 155};
153 156
154static struct snd_soc_device palm27x_snd_devdata = {
155 .card = &palm27x_asoc,
156 .codec_dev = &soc_codec_dev_wm9712,
157};
158
159static struct platform_device *palm27x_snd_device; 157static struct platform_device *palm27x_snd_device;
160 158
161static int palm27x_asoc_probe(struct platform_device *pdev) 159static int palm27x_asoc_probe(struct platform_device *pdev)
@@ -178,8 +176,7 @@ static int palm27x_asoc_probe(struct platform_device *pdev)
178 if (!palm27x_snd_device) 176 if (!palm27x_snd_device)
179 return -ENOMEM; 177 return -ENOMEM;
180 178
181 platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); 179 platform_set_drvdata(palm27x_snd_device, &palm27x_asoc);
182 palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
183 ret = platform_device_add(palm27x_snd_device); 180 ret = platform_device_add(palm27x_snd_device);
184 181
185 if (ret != 0) 182 if (ret != 0)
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index c5f36e0eab58..af84ee9c5e11 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -31,7 +31,6 @@
31#include <mach/audio.h> 31#include <mach/audio.h>
32 32
33#include "../codecs/wm8731.h" 33#include "../codecs/wm8731.h"
34#include "pxa2xx-pcm.h"
35#include "pxa2xx-i2s.h" 34#include "pxa2xx-i2s.h"
36 35
37#define POODLE_HP 1 36#define POODLE_HP 1
@@ -76,7 +75,7 @@ static void poodle_ext_control(struct snd_soc_codec *codec)
76static int poodle_startup(struct snd_pcm_substream *substream) 75static int poodle_startup(struct snd_pcm_substream *substream)
77{ 76{
78 struct snd_soc_pcm_runtime *rtd = substream->private_data; 77 struct snd_soc_pcm_runtime *rtd = substream->private_data;
79 struct snd_soc_codec *codec = rtd->socdev->card->codec; 78 struct snd_soc_codec *codec = rtd->codec;
80 79
81 /* check the jack status at stream startup */ 80 /* check the jack status at stream startup */
82 poodle_ext_control(codec); 81 poodle_ext_control(codec);
@@ -97,8 +96,8 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
97 struct snd_pcm_hw_params *params) 96 struct snd_pcm_hw_params *params)
98{ 97{
99 struct snd_soc_pcm_runtime *rtd = substream->private_data; 98 struct snd_soc_pcm_runtime *rtd = substream->private_data;
100 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 99 struct snd_soc_dai *codec_dai = rtd->codec_dai;
101 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 100 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
102 unsigned int clk = 0; 101 unsigned int clk = 0;
103 int ret = 0; 102 int ret = 0;
104 103
@@ -129,7 +128,7 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
129 return ret; 128 return ret;
130 129
131 /* set the codec system clock for DAC and ADC */ 130 /* set the codec system clock for DAC and ADC */
132 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, clk, 131 ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
133 SND_SOC_CLOCK_IN); 132 SND_SOC_CLOCK_IN);
134 if (ret < 0) 133 if (ret < 0)
135 return ret; 134 return ret;
@@ -237,8 +236,9 @@ static const struct snd_kcontrol_new wm8731_poodle_controls[] = {
237/* 236/*
238 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device 237 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
239 */ 238 */
240static int poodle_wm8731_init(struct snd_soc_codec *codec) 239static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd)
241{ 240{
241 struct snd_soc_codec *codec = rtd->codec;
242 int err; 242 int err;
243 243
244 snd_soc_dapm_nc_pin(codec, "LLINEIN"); 244 snd_soc_dapm_nc_pin(codec, "LLINEIN");
@@ -266,8 +266,10 @@ static int poodle_wm8731_init(struct snd_soc_codec *codec)
266static struct snd_soc_dai_link poodle_dai = { 266static struct snd_soc_dai_link poodle_dai = {
267 .name = "WM8731", 267 .name = "WM8731",
268 .stream_name = "WM8731", 268 .stream_name = "WM8731",
269 .cpu_dai = &pxa_i2s_dai, 269 .cpu_dai_name = "pxa2xx-i2s",
270 .codec_dai = &wm8731_dai, 270 .codec_dai_name = "wm8731-hifi",
271 .platform_name = "pxa-pcm-audio",
272 .codec_name = "wm8731-codec.0-001a",
271 .init = poodle_wm8731_init, 273 .init = poodle_wm8731_init,
272 .ops = &poodle_ops, 274 .ops = &poodle_ops,
273}; 275};
@@ -275,15 +277,9 @@ static struct snd_soc_dai_link poodle_dai = {
275/* poodle audio machine driver */ 277/* poodle audio machine driver */
276static struct snd_soc_card snd_soc_poodle = { 278static struct snd_soc_card snd_soc_poodle = {
277 .name = "Poodle", 279 .name = "Poodle",
278 .platform = &pxa2xx_soc_platform,
279 .dai_link = &poodle_dai, 280 .dai_link = &poodle_dai,
280 .num_links = 1, 281 .num_links = 1,
281}; 282 .owner = THIS_MODULE,
282
283/* poodle audio subsystem */
284static struct snd_soc_device poodle_snd_devdata = {
285 .card = &snd_soc_poodle,
286 .codec_dev = &soc_codec_dev_wm8731,
287}; 283};
288 284
289static struct platform_device *poodle_snd_device; 285static struct platform_device *poodle_snd_device;
@@ -307,8 +303,7 @@ static int __init poodle_init(void)
307 if (!poodle_snd_device) 303 if (!poodle_snd_device)
308 return -ENOMEM; 304 return -ENOMEM;
309 305
310 platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata); 306 platform_set_drvdata(poodle_snd_device, &snd_soc_poodle);
311 poodle_snd_devdata.dev = &poodle_snd_device->dev;
312 ret = platform_device_add(poodle_snd_device); 307 ret = platform_device_add(poodle_snd_device);
313 308
314 if (ret) 309 if (ret)
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index a1fd23e0e3d0..b439eee462cb 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -35,7 +35,7 @@
35#include <mach/audio.h> 35#include <mach/audio.h>
36#include <plat/ssp.h> 36#include <plat/ssp.h>
37 37
38#include "pxa2xx-pcm.h" 38#include "../../arm/pxa2xx-pcm.h"
39#include "pxa-ssp.h" 39#include "pxa-ssp.h"
40 40
41/* 41/*
@@ -108,11 +108,9 @@ pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)
108} 108}
109 109
110static int pxa_ssp_startup(struct snd_pcm_substream *substream, 110static int pxa_ssp_startup(struct snd_pcm_substream *substream,
111 struct snd_soc_dai *dai) 111 struct snd_soc_dai *cpu_dai)
112{ 112{
113 struct snd_soc_pcm_runtime *rtd = substream->private_data; 113 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
114 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
115 struct ssp_priv *priv = cpu_dai->private_data;
116 struct ssp_device *ssp = priv->ssp; 114 struct ssp_device *ssp = priv->ssp;
117 int ret = 0; 115 int ret = 0;
118 116
@@ -128,11 +126,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
128} 126}
129 127
130static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, 128static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
131 struct snd_soc_dai *dai) 129 struct snd_soc_dai *cpu_dai)
132{ 130{
133 struct snd_soc_pcm_runtime *rtd = substream->private_data; 131 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
134 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
135 struct ssp_priv *priv = cpu_dai->private_data;
136 struct ssp_device *ssp = priv->ssp; 132 struct ssp_device *ssp = priv->ssp;
137 133
138 if (!cpu_dai->active) { 134 if (!cpu_dai->active) {
@@ -148,7 +144,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
148 144
149static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) 145static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
150{ 146{
151 struct ssp_priv *priv = cpu_dai->private_data; 147 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
152 struct ssp_device *ssp = priv->ssp; 148 struct ssp_device *ssp = priv->ssp;
153 149
154 if (!cpu_dai->active) 150 if (!cpu_dai->active)
@@ -166,7 +162,7 @@ static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
166 162
167static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) 163static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
168{ 164{
169 struct ssp_priv *priv = cpu_dai->private_data; 165 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
170 struct ssp_device *ssp = priv->ssp; 166 struct ssp_device *ssp = priv->ssp;
171 uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; 167 uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE;
172 168
@@ -230,7 +226,7 @@ static u32 pxa_ssp_get_scr(struct ssp_device *ssp)
230static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 226static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
231 int clk_id, unsigned int freq, int dir) 227 int clk_id, unsigned int freq, int dir)
232{ 228{
233 struct ssp_priv *priv = cpu_dai->private_data; 229 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
234 struct ssp_device *ssp = priv->ssp; 230 struct ssp_device *ssp = priv->ssp;
235 int val; 231 int val;
236 232
@@ -287,7 +283,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
287static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, 283static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
288 int div_id, int div) 284 int div_id, int div)
289{ 285{
290 struct ssp_priv *priv = cpu_dai->private_data; 286 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
291 struct ssp_device *ssp = priv->ssp; 287 struct ssp_device *ssp = priv->ssp;
292 int val; 288 int val;
293 289
@@ -338,7 +334,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
338static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, 334static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
339 int source, unsigned int freq_in, unsigned int freq_out) 335 int source, unsigned int freq_in, unsigned int freq_out)
340{ 336{
341 struct ssp_priv *priv = cpu_dai->private_data; 337 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
342 struct ssp_device *ssp = priv->ssp; 338 struct ssp_device *ssp = priv->ssp;
343 u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70; 339 u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70;
344 340
@@ -407,7 +403,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
407static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, 403static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
408 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) 404 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
409{ 405{
410 struct ssp_priv *priv = cpu_dai->private_data; 406 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
411 struct ssp_device *ssp = priv->ssp; 407 struct ssp_device *ssp = priv->ssp;
412 u32 sscr0; 408 u32 sscr0;
413 409
@@ -442,7 +438,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
442static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, 438static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
443 int tristate) 439 int tristate)
444{ 440{
445 struct ssp_priv *priv = cpu_dai->private_data; 441 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
446 struct ssp_device *ssp = priv->ssp; 442 struct ssp_device *ssp = priv->ssp;
447 u32 sscr1; 443 u32 sscr1;
448 444
@@ -464,11 +460,9 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
464static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, 460static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
465 unsigned int fmt) 461 unsigned int fmt)
466{ 462{
467 struct ssp_priv *priv = cpu_dai->private_data; 463 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
468 struct ssp_device *ssp = priv->ssp; 464 struct ssp_device *ssp = priv->ssp;
469 u32 sscr0; 465 u32 sscr0, sscr1, sspsp, scfr;
470 u32 sscr1;
471 u32 sspsp;
472 466
473 /* check if we need to change anything at all */ 467 /* check if we need to change anything at all */
474 if (priv->dai_fmt == fmt) 468 if (priv->dai_fmt == fmt)
@@ -483,16 +477,16 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
483 477
484 /* reset port settings */ 478 /* reset port settings */
485 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & 479 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) &
486 (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); 480 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
487 sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); 481 sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
488 sspsp = 0; 482 sspsp = 0;
489 483
490 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 484 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
491 case SND_SOC_DAIFMT_CBM_CFM: 485 case SND_SOC_DAIFMT_CBM_CFM:
492 sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; 486 sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR | SSCR1_SCFR;
493 break; 487 break;
494 case SND_SOC_DAIFMT_CBM_CFS: 488 case SND_SOC_DAIFMT_CBM_CFS:
495 sscr1 |= SSCR1_SCLKDIR; 489 sscr1 |= SSCR1_SCLKDIR | SSCR1_SCFR;
496 break; 490 break;
497 case SND_SOC_DAIFMT_CBS_CFS: 491 case SND_SOC_DAIFMT_CBS_CFS:
498 break; 492 break;
@@ -538,6 +532,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
538 pxa_ssp_write_reg(ssp, SSCR1, sscr1); 532 pxa_ssp_write_reg(ssp, SSCR1, sscr1);
539 pxa_ssp_write_reg(ssp, SSPSP, sspsp); 533 pxa_ssp_write_reg(ssp, SSPSP, sspsp);
540 534
535 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
536 case SND_SOC_DAIFMT_CBM_CFM:
537 case SND_SOC_DAIFMT_CBM_CFS:
538 scfr = pxa_ssp_read_reg(ssp, SSCR1) | SSCR1_SCFR;
539 pxa_ssp_write_reg(ssp, SSCR1, scfr);
540
541 while (pxa_ssp_read_reg(ssp, SSSR) & SSSR_BSY)
542 cpu_relax();
543 break;
544 }
545
541 dump_registers(ssp); 546 dump_registers(ssp);
542 547
543 /* Since we are configuring the timings for the format by hand 548 /* Since we are configuring the timings for the format by hand
@@ -555,11 +560,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
555 */ 560 */
556static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, 561static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
557 struct snd_pcm_hw_params *params, 562 struct snd_pcm_hw_params *params,
558 struct snd_soc_dai *dai) 563 struct snd_soc_dai *cpu_dai)
559{ 564{
560 struct snd_soc_pcm_runtime *rtd = substream->private_data; 565 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
561 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
562 struct ssp_priv *priv = cpu_dai->private_data;
563 struct ssp_device *ssp = priv->ssp; 566 struct ssp_device *ssp = priv->ssp;
564 int chn = params_channels(params); 567 int chn = params_channels(params);
565 u32 sscr0; 568 u32 sscr0;
@@ -568,7 +571,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
568 int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; 571 int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf;
569 struct pxa2xx_pcm_dma_params *dma_data; 572 struct pxa2xx_pcm_dma_params *dma_data;
570 573
571 dma_data = snd_soc_dai_get_dma_data(dai, substream); 574 dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
572 575
573 /* generate correct DMA params */ 576 /* generate correct DMA params */
574 kfree(dma_data); 577 kfree(dma_data);
@@ -581,7 +584,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
581 ((chn == 2) && (ttsa != 1)) || (width == 32), 584 ((chn == 2) && (ttsa != 1)) || (width == 32),
582 substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 585 substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
583 586
584 snd_soc_dai_set_dma_data(dai, substream, dma_data); 587 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
585 588
586 /* we can only change the settings if the port is not in use */ 589 /* we can only change the settings if the port is not in use */
587 if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) 590 if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
@@ -589,10 +592,8 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
589 592
590 /* clear selected SSP bits */ 593 /* clear selected SSP bits */
591 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS); 594 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
592 pxa_ssp_write_reg(ssp, SSCR0, sscr0);
593 595
594 /* bit size */ 596 /* bit size */
595 sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
596 switch (params_format(params)) { 597 switch (params_format(params)) {
597 case SNDRV_PCM_FORMAT_S16_LE: 598 case SNDRV_PCM_FORMAT_S16_LE:
598#ifdef CONFIG_PXA3xx 599#ifdef CONFIG_PXA3xx
@@ -668,12 +669,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
668} 669}
669 670
670static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, 671static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
671 struct snd_soc_dai *dai) 672 struct snd_soc_dai *cpu_dai)
672{ 673{
673 struct snd_soc_pcm_runtime *rtd = substream->private_data;
674 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
675 int ret = 0; 674 int ret = 0;
676 struct ssp_priv *priv = cpu_dai->private_data; 675 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
677 struct ssp_device *ssp = priv->ssp; 676 struct ssp_device *ssp = priv->ssp;
678 int val; 677 int val;
679 678
@@ -729,8 +728,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
729 return ret; 728 return ret;
730} 729}
731 730
732static int pxa_ssp_probe(struct platform_device *pdev, 731static int pxa_ssp_probe(struct snd_soc_dai *dai)
733 struct snd_soc_dai *dai)
734{ 732{
735 struct ssp_priv *priv; 733 struct ssp_priv *priv;
736 int ret; 734 int ret;
@@ -746,7 +744,7 @@ static int pxa_ssp_probe(struct platform_device *pdev,
746 } 744 }
747 745
748 priv->dai_fmt = (unsigned int) -1; 746 priv->dai_fmt = (unsigned int) -1;
749 dai->private_data = priv; 747 snd_soc_dai_set_drvdata(dai, priv);
750 748
751 return 0; 749 return 0;
752 750
@@ -755,11 +753,13 @@ err_priv:
755 return ret; 753 return ret;
756} 754}
757 755
758static void pxa_ssp_remove(struct platform_device *pdev, 756static int pxa_ssp_remove(struct snd_soc_dai *dai)
759 struct snd_soc_dai *dai)
760{ 757{
761 struct ssp_priv *priv = dai->private_data; 758 struct ssp_priv *priv = snd_soc_dai_get_drvdata(dai);
759
762 pxa_ssp_free(priv->ssp); 760 pxa_ssp_free(priv->ssp);
761 kfree(priv);
762 return 0;
763} 763}
764 764
765#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 765#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
@@ -784,10 +784,7 @@ static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
784 .set_tristate = pxa_ssp_set_dai_tristate, 784 .set_tristate = pxa_ssp_set_dai_tristate,
785}; 785};
786 786
787struct snd_soc_dai pxa_ssp_dai[] = { 787static struct snd_soc_dai_driver pxa_ssp_dai = {
788 {
789 .name = "pxa2xx-ssp1",
790 .id = 0,
791 .probe = pxa_ssp_probe, 788 .probe = pxa_ssp_probe,
792 .remove = pxa_ssp_remove, 789 .remove = pxa_ssp_remove,
793 .suspend = pxa_ssp_suspend, 790 .suspend = pxa_ssp_suspend,
@@ -805,81 +802,38 @@ struct snd_soc_dai pxa_ssp_dai[] = {
805 .formats = PXA_SSP_FORMATS, 802 .formats = PXA_SSP_FORMATS,
806 }, 803 },
807 .ops = &pxa_ssp_dai_ops, 804 .ops = &pxa_ssp_dai_ops,
805};
806
807static __devinit int asoc_ssp_probe(struct platform_device *pdev)
808{
809 return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai);
810}
811
812static int __devexit asoc_ssp_remove(struct platform_device *pdev)
813{
814 snd_soc_unregister_dai(&pdev->dev);
815 return 0;
816}
817
818static struct platform_driver asoc_ssp_driver = {
819 .driver = {
820 .name = "pxa-ssp-dai",
821 .owner = THIS_MODULE,
808 }, 822 },
809 { .name = "pxa2xx-ssp2", 823
810 .id = 1, 824 .probe = asoc_ssp_probe,
811 .probe = pxa_ssp_probe, 825 .remove = __devexit_p(asoc_ssp_remove),
812 .remove = pxa_ssp_remove,
813 .suspend = pxa_ssp_suspend,
814 .resume = pxa_ssp_resume,
815 .playback = {
816 .channels_min = 1,
817 .channels_max = 8,
818 .rates = PXA_SSP_RATES,
819 .formats = PXA_SSP_FORMATS,
820 },
821 .capture = {
822 .channels_min = 1,
823 .channels_max = 8,
824 .rates = PXA_SSP_RATES,
825 .formats = PXA_SSP_FORMATS,
826 },
827 .ops = &pxa_ssp_dai_ops,
828 },
829 {
830 .name = "pxa2xx-ssp3",
831 .id = 2,
832 .probe = pxa_ssp_probe,
833 .remove = pxa_ssp_remove,
834 .suspend = pxa_ssp_suspend,
835 .resume = pxa_ssp_resume,
836 .playback = {
837 .channels_min = 1,
838 .channels_max = 8,
839 .rates = PXA_SSP_RATES,
840 .formats = PXA_SSP_FORMATS,
841 },
842 .capture = {
843 .channels_min = 1,
844 .channels_max = 8,
845 .rates = PXA_SSP_RATES,
846 .formats = PXA_SSP_FORMATS,
847 },
848 .ops = &pxa_ssp_dai_ops,
849 },
850 {
851 .name = "pxa2xx-ssp4",
852 .id = 3,
853 .probe = pxa_ssp_probe,
854 .remove = pxa_ssp_remove,
855 .suspend = pxa_ssp_suspend,
856 .resume = pxa_ssp_resume,
857 .playback = {
858 .channels_min = 1,
859 .channels_max = 8,
860 .rates = PXA_SSP_RATES,
861 .formats = PXA_SSP_FORMATS,
862 },
863 .capture = {
864 .channels_min = 1,
865 .channels_max = 8,
866 .rates = PXA_SSP_RATES,
867 .formats = PXA_SSP_FORMATS,
868 },
869 .ops = &pxa_ssp_dai_ops,
870 },
871}; 826};
872EXPORT_SYMBOL_GPL(pxa_ssp_dai);
873 827
874static int __init pxa_ssp_init(void) 828static int __init pxa_ssp_init(void)
875{ 829{
876 return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); 830 return platform_driver_register(&asoc_ssp_driver);
877} 831}
878module_init(pxa_ssp_init); 832module_init(pxa_ssp_init);
879 833
880static void __exit pxa_ssp_exit(void) 834static void __exit pxa_ssp_exit(void)
881{ 835{
882 snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); 836 platform_driver_unregister(&asoc_ssp_driver);
883} 837}
884module_exit(pxa_ssp_exit); 838module_exit(pxa_ssp_exit);
885 839
diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h
index 91deadd55675..bc79da221c0d 100644
--- a/sound/soc/pxa/pxa-ssp.h
+++ b/sound/soc/pxa/pxa-ssp.h
@@ -42,6 +42,4 @@
42 42
43#define PXA_SSP_PLL_OUT 0 43#define PXA_SSP_PLL_OUT 0
44 44
45extern struct snd_soc_dai pxa_ssp_dai[4];
46
47#endif 45#endif
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index d314115e3dd7..ac51c6d25c42 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -24,7 +24,6 @@
24#include <mach/dma.h> 24#include <mach/dma.h>
25#include <mach/audio.h> 25#include <mach/audio.h>
26 26
27#include "pxa2xx-pcm.h"
28#include "pxa2xx-ac97.h" 27#include "pxa2xx-ac97.h"
29 28
30static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97) 29static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
@@ -104,24 +103,21 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
104#define pxa2xx_ac97_resume NULL 103#define pxa2xx_ac97_resume NULL
105#endif 104#endif
106 105
107static int pxa2xx_ac97_probe(struct platform_device *pdev, 106static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
108 struct snd_soc_dai *dai)
109{ 107{
110 return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev)); 108 return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
111} 109}
112 110
113static void pxa2xx_ac97_remove(struct platform_device *pdev, 111static int pxa2xx_ac97_remove(struct snd_soc_dai *dai)
114 struct snd_soc_dai *dai)
115{ 112{
116 pxa2xx_ac97_hw_remove(to_platform_device(dai->dev)); 113 pxa2xx_ac97_hw_remove(to_platform_device(dai->dev));
114 return 0;
117} 115}
118 116
119static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, 117static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
120 struct snd_pcm_hw_params *params, 118 struct snd_pcm_hw_params *params,
121 struct snd_soc_dai *dai) 119 struct snd_soc_dai *cpu_dai)
122{ 120{
123 struct snd_soc_pcm_runtime *rtd = substream->private_data;
124 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
125 struct pxa2xx_pcm_dma_params *dma_data; 121 struct pxa2xx_pcm_dma_params *dma_data;
126 122
127 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 123 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -136,10 +132,8 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
136 132
137static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, 133static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
138 struct snd_pcm_hw_params *params, 134 struct snd_pcm_hw_params *params,
139 struct snd_soc_dai *dai) 135 struct snd_soc_dai *cpu_dai)
140{ 136{
141 struct snd_soc_pcm_runtime *rtd = substream->private_data;
142 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
143 struct pxa2xx_pcm_dma_params *dma_data; 137 struct pxa2xx_pcm_dma_params *dma_data;
144 138
145 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 139 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -154,11 +148,8 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
154 148
155static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, 149static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
156 struct snd_pcm_hw_params *params, 150 struct snd_pcm_hw_params *params,
157 struct snd_soc_dai *dai) 151 struct snd_soc_dai *cpu_dai)
158{ 152{
159 struct snd_soc_pcm_runtime *rtd = substream->private_data;
160 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
161
162 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 153 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
163 return -ENODEV; 154 return -ENODEV;
164 else 155 else
@@ -188,10 +179,9 @@ static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
188 * There is only 1 physical AC97 interface for pxa2xx, but it 179 * There is only 1 physical AC97 interface for pxa2xx, but it
189 * has extra fifo's that can be used for aux DACs and ADCs. 180 * has extra fifo's that can be used for aux DACs and ADCs.
190 */ 181 */
191struct snd_soc_dai pxa_ac97_dai[] = { 182static struct snd_soc_dai_driver pxa_ac97_dai[] = {
192{ 183{
193 .name = "pxa2xx-ac97", 184 .name = "pxa2xx-ac97",
194 .id = 0,
195 .ac97_control = 1, 185 .ac97_control = 1,
196 .probe = pxa2xx_ac97_probe, 186 .probe = pxa2xx_ac97_probe,
197 .remove = pxa2xx_ac97_remove, 187 .remove = pxa2xx_ac97_remove,
@@ -213,7 +203,6 @@ struct snd_soc_dai pxa_ac97_dai[] = {
213}, 203},
214{ 204{
215 .name = "pxa2xx-ac97-aux", 205 .name = "pxa2xx-ac97-aux",
216 .id = 1,
217 .ac97_control = 1, 206 .ac97_control = 1,
218 .playback = { 207 .playback = {
219 .stream_name = "AC97 Aux Playback", 208 .stream_name = "AC97 Aux Playback",
@@ -231,7 +220,6 @@ struct snd_soc_dai pxa_ac97_dai[] = {
231}, 220},
232{ 221{
233 .name = "pxa2xx-ac97-mic", 222 .name = "pxa2xx-ac97-mic",
234 .id = 2,
235 .ac97_control = 1, 223 .ac97_control = 1,
236 .capture = { 224 .capture = {
237 .stream_name = "AC97 Mic Capture", 225 .stream_name = "AC97 Mic Capture",
@@ -243,36 +231,26 @@ struct snd_soc_dai pxa_ac97_dai[] = {
243}, 231},
244}; 232};
245 233
246EXPORT_SYMBOL_GPL(pxa_ac97_dai);
247EXPORT_SYMBOL_GPL(soc_ac97_ops); 234EXPORT_SYMBOL_GPL(soc_ac97_ops);
248 235
249static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) 236static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
250{ 237{
251 int i; 238 if (pdev->id != -1) {
252 pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data;
253
254 if (pdev->id >= 0) {
255 dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); 239 dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n");
256 return -ENXIO; 240 return -ENXIO;
257 } 241 }
258 242
259 for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) {
260 pxa_ac97_dai[i].dev = &pdev->dev;
261 if (pdata && pdata->codec_pdata[0])
262 pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata[0];
263 }
264
265 /* Punt most of the init to the SoC probe; we may need the machine 243 /* Punt most of the init to the SoC probe; we may need the machine
266 * driver to do interesting things with the clocking to get us up 244 * driver to do interesting things with the clocking to get us up
267 * and running. 245 * and running.
268 */ 246 */
269 return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); 247 return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai,
248 ARRAY_SIZE(pxa_ac97_dai));
270} 249}
271 250
272static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev) 251static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
273{ 252{
274 snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); 253 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai));
275
276 return 0; 254 return 0;
277} 255}
278 256
diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h
index e390de8edcd4..eda891e6f31b 100644
--- a/sound/soc/pxa/pxa2xx-ac97.h
+++ b/sound/soc/pxa/pxa2xx-ac97.h
@@ -14,8 +14,6 @@
14#define PXA2XX_DAI_AC97_AUX 1 14#define PXA2XX_DAI_AC97_AUX 1
15#define PXA2XX_DAI_AC97_MIC 2 15#define PXA2XX_DAI_AC97_MIC 2
16 16
17extern struct snd_soc_dai pxa_ac97_dai[3];
18
19/* platform data */ 17/* platform data */
20extern struct snd_ac97_bus_ops pxa2xx_ac97_ops; 18extern struct snd_ac97_bus_ops pxa2xx_ac97_ops;
21 19
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index c1a5275721e4..11be5952a506 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -27,7 +27,6 @@
27#include <mach/dma.h> 27#include <mach/dma.h>
28#include <mach/audio.h> 28#include <mach/audio.h>
29 29
30#include "pxa2xx-pcm.h"
31#include "pxa2xx-i2s.h" 30#include "pxa2xx-i2s.h"
32 31
33/* 32/*
@@ -80,6 +79,7 @@ struct pxa_i2s_port {
80}; 79};
81static struct pxa_i2s_port pxa_i2s; 80static struct pxa_i2s_port pxa_i2s;
82static struct clk *clk_i2s; 81static struct clk *clk_i2s;
82static int clk_ena = 0;
83 83
84static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = { 84static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
85 .name = "I2S PCM Stereo out", 85 .name = "I2S PCM Stereo out",
@@ -101,7 +101,7 @@ static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
101 struct snd_soc_dai *dai) 101 struct snd_soc_dai *dai)
102{ 102{
103 struct snd_soc_pcm_runtime *rtd = substream->private_data; 103 struct snd_soc_pcm_runtime *rtd = substream->private_data;
104 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 104 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
105 105
106 if (IS_ERR(clk_i2s)) 106 if (IS_ERR(clk_i2s))
107 return PTR_ERR(clk_i2s); 107 return PTR_ERR(clk_i2s);
@@ -162,13 +162,11 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
162 struct snd_pcm_hw_params *params, 162 struct snd_pcm_hw_params *params,
163 struct snd_soc_dai *dai) 163 struct snd_soc_dai *dai)
164{ 164{
165 struct snd_soc_pcm_runtime *rtd = substream->private_data;
166 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
167 struct pxa2xx_pcm_dma_params *dma_data; 165 struct pxa2xx_pcm_dma_params *dma_data;
168 166
169 BUG_ON(IS_ERR(clk_i2s)); 167 BUG_ON(IS_ERR(clk_i2s));
170 clk_enable(clk_i2s); 168 clk_enable(clk_i2s);
171 dai->private_data = dai; 169 clk_ena = 1;
172 pxa_i2s_wait(); 170 pxa_i2s_wait();
173 171
174 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 172 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -176,7 +174,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
176 else 174 else
177 dma_data = &pxa2xx_i2s_pcm_stereo_in; 175 dma_data = &pxa2xx_i2s_pcm_stereo_in;
178 176
179 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); 177 snd_soc_dai_set_dma_data(dai, substream, dma_data);
180 178
181 /* is port used by another stream */ 179 /* is port used by another stream */
182 if (!(SACR0 & SACR0_ENB)) { 180 if (!(SACR0 & SACR0_ENB)) {
@@ -259,9 +257,9 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
259 if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) { 257 if ((SACR1 & (SACR1_DREC | SACR1_DRPL)) == (SACR1_DREC | SACR1_DRPL)) {
260 SACR0 &= ~SACR0_ENB; 258 SACR0 &= ~SACR0_ENB;
261 pxa_i2s_wait(); 259 pxa_i2s_wait();
262 if (dai->private_data != NULL) { 260 if (clk_ena) {
263 clk_disable(clk_i2s); 261 clk_disable(clk_i2s);
264 dai->private_data = NULL; 262 clk_ena = 0;
265 } 263 }
266 } 264 }
267} 265}
@@ -300,6 +298,35 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
300#define pxa2xx_i2s_resume NULL 298#define pxa2xx_i2s_resume NULL
301#endif 299#endif
302 300
301static int pxa2xx_i2s_probe(struct snd_soc_dai *dai)
302{
303 clk_i2s = clk_get(dai->dev, "I2SCLK");
304 if (IS_ERR(clk_i2s))
305 return PTR_ERR(clk_i2s);
306
307 /*
308 * PXA Developer's Manual:
309 * If SACR0[ENB] is toggled in the middle of a normal operation,
310 * the SACR0[RST] bit must also be set and cleared to reset all
311 * I2S controller registers.
312 */
313 SACR0 = SACR0_RST;
314 SACR0 = 0;
315 /* Make sure RPL and REC are disabled */
316 SACR1 = SACR1_DRPL | SACR1_DREC;
317 /* Along with FIFO servicing */
318 SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
319
320 return 0;
321}
322
323static int pxa2xx_i2s_remove(struct snd_soc_dai *dai)
324{
325 clk_put(clk_i2s);
326 clk_i2s = ERR_PTR(-ENOENT);
327 return 0;
328}
329
303#define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 330#define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
304 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ 331 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
305 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) 332 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
@@ -313,9 +340,9 @@ static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
313 .set_sysclk = pxa2xx_i2s_set_dai_sysclk, 340 .set_sysclk = pxa2xx_i2s_set_dai_sysclk,
314}; 341};
315 342
316struct snd_soc_dai pxa_i2s_dai = { 343static struct snd_soc_dai_driver pxa_i2s_dai = {
317 .name = "pxa2xx-i2s", 344 .probe = pxa2xx_i2s_probe,
318 .id = 0, 345 .remove = pxa2xx_i2s_remove,
319 .suspend = pxa2xx_i2s_suspend, 346 .suspend = pxa2xx_i2s_suspend,
320 .resume = pxa2xx_i2s_resume, 347 .resume = pxa2xx_i2s_resume,
321 .playback = { 348 .playback = {
@@ -332,49 +359,20 @@ struct snd_soc_dai pxa_i2s_dai = {
332 .symmetric_rates = 1, 359 .symmetric_rates = 1,
333}; 360};
334 361
335EXPORT_SYMBOL_GPL(pxa_i2s_dai); 362static int pxa2xx_i2s_drv_probe(struct platform_device *pdev)
336
337static int pxa2xx_i2s_probe(struct platform_device *dev)
338{ 363{
339 int ret; 364 return snd_soc_register_dai(&pdev->dev, &pxa_i2s_dai);
340
341 clk_i2s = clk_get(&dev->dev, "I2SCLK");
342 if (IS_ERR(clk_i2s))
343 return PTR_ERR(clk_i2s);
344
345 pxa_i2s_dai.dev = &dev->dev;
346 pxa_i2s_dai.private_data = NULL;
347 ret = snd_soc_register_dai(&pxa_i2s_dai);
348 if (ret != 0)
349 clk_put(clk_i2s);
350
351 /*
352 * PXA Developer's Manual:
353 * If SACR0[ENB] is toggled in the middle of a normal operation,
354 * the SACR0[RST] bit must also be set and cleared to reset all
355 * I2S controller registers.
356 */
357 SACR0 = SACR0_RST;
358 SACR0 = 0;
359 /* Make sure RPL and REC are disabled */
360 SACR1 = SACR1_DRPL | SACR1_DREC;
361 /* Along with FIFO servicing */
362 SAIMR &= ~(SAIMR_RFS | SAIMR_TFS);
363
364 return ret;
365} 365}
366 366
367static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) 367static int __devexit pxa2xx_i2s_drv_remove(struct platform_device *pdev)
368{ 368{
369 snd_soc_unregister_dai(&pxa_i2s_dai); 369 snd_soc_unregister_dai(&pdev->dev);
370 clk_put(clk_i2s);
371 clk_i2s = ERR_PTR(-ENOENT);
372 return 0; 370 return 0;
373} 371}
374 372
375static struct platform_driver pxa2xx_i2s_driver = { 373static struct platform_driver pxa2xx_i2s_driver = {
376 .probe = pxa2xx_i2s_probe, 374 .probe = pxa2xx_i2s_drv_probe,
377 .remove = __devexit_p(pxa2xx_i2s_remove), 375 .remove = __devexit_p(pxa2xx_i2s_drv_remove),
378 376
379 .driver = { 377 .driver = {
380 .name = "pxa2xx-i2s", 378 .name = "pxa2xx-i2s",
@@ -400,3 +398,4 @@ module_exit(pxa2xx_i2s_exit);
400MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); 398MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk");
401MODULE_DESCRIPTION("pxa2xx I2S SoC Interface"); 399MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
402MODULE_LICENSE("GPL"); 400MODULE_LICENSE("GPL");
401MODULE_ALIAS("platform:pxa2xx-i2s");
diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h
index e2def441153e..070f3c6059fe 100644
--- a/sound/soc/pxa/pxa2xx-i2s.h
+++ b/sound/soc/pxa/pxa2xx-i2s.h
@@ -15,6 +15,4 @@
15/* I2S clock */ 15/* I2S clock */
16#define PXA2XX_I2S_SYSCLK 0 16#define PXA2XX_I2S_SYSCLK 0
17 17
18extern struct snd_soc_dai pxa_i2s_dai;
19
20#endif 18#endif
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index adc7e6f15f93..02fb66416ddc 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -16,7 +16,6 @@
16#include <sound/soc.h> 16#include <sound/soc.h>
17#include <sound/pxa2xx-lib.h> 17#include <sound/pxa2xx-lib.h>
18 18
19#include "pxa2xx-pcm.h"
20#include "../../arm/pxa2xx-pcm.h" 19#include "../../arm/pxa2xx-pcm.h"
21 20
22static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, 21static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -28,7 +27,7 @@ static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
28 struct pxa2xx_pcm_dma_params *dma; 27 struct pxa2xx_pcm_dma_params *dma;
29 int ret; 28 int ret;
30 29
31 dma = snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 30 dma = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
32 31
33 /* return if this is a bufferless transfer e.g. 32 /* return if this is a bufferless transfer e.g.
34 * codec <--> BT codec or GSM modem -- lg FIXME */ 33 * codec <--> BT codec or GSM modem -- lg FIXME */
@@ -95,14 +94,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
95 if (!card->dev->coherent_dma_mask) 94 if (!card->dev->coherent_dma_mask)
96 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 95 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
97 96
98 if (dai->playback.channels_min) { 97 if (dai->driver->playback.channels_min) {
99 ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, 98 ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
100 SNDRV_PCM_STREAM_PLAYBACK); 99 SNDRV_PCM_STREAM_PLAYBACK);
101 if (ret) 100 if (ret)
102 goto out; 101 goto out;
103 } 102 }
104 103
105 if (dai->capture.channels_min) { 104 if (dai->driver->capture.channels_min) {
106 ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, 105 ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
107 SNDRV_PCM_STREAM_CAPTURE); 106 SNDRV_PCM_STREAM_CAPTURE);
108 if (ret) 107 if (ret)
@@ -112,25 +111,44 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
112 return ret; 111 return ret;
113} 112}
114 113
115struct snd_soc_platform pxa2xx_soc_platform = { 114static struct snd_soc_platform_driver pxa2xx_soc_platform = {
116 .name = "pxa2xx-audio", 115 .ops = &pxa2xx_pcm_ops,
117 .pcm_ops = &pxa2xx_pcm_ops,
118 .pcm_new = pxa2xx_soc_pcm_new, 116 .pcm_new = pxa2xx_soc_pcm_new,
119 .pcm_free = pxa2xx_pcm_free_dma_buffers, 117 .pcm_free = pxa2xx_pcm_free_dma_buffers,
120}; 118};
121EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
122 119
123static int __init pxa2xx_soc_platform_init(void) 120static int __devinit pxa2xx_soc_platform_probe(struct platform_device *pdev)
124{ 121{
125 return snd_soc_register_platform(&pxa2xx_soc_platform); 122 return snd_soc_register_platform(&pdev->dev, &pxa2xx_soc_platform);
126} 123}
127module_init(pxa2xx_soc_platform_init);
128 124
129static void __exit pxa2xx_soc_platform_exit(void) 125static int __devexit pxa2xx_soc_platform_remove(struct platform_device *pdev)
130{ 126{
131 snd_soc_unregister_platform(&pxa2xx_soc_platform); 127 snd_soc_unregister_platform(&pdev->dev);
128 return 0;
129}
130
131static struct platform_driver pxa_pcm_driver = {
132 .driver = {
133 .name = "pxa-pcm-audio",
134 .owner = THIS_MODULE,
135 },
136
137 .probe = pxa2xx_soc_platform_probe,
138 .remove = __devexit_p(pxa2xx_soc_platform_remove),
139};
140
141static int __init snd_pxa_pcm_init(void)
142{
143 return platform_driver_register(&pxa_pcm_driver);
144}
145module_init(snd_pxa_pcm_init);
146
147static void __exit snd_pxa_pcm_exit(void)
148{
149 platform_driver_unregister(&pxa_pcm_driver);
132} 150}
133module_exit(pxa2xx_soc_platform_exit); 151module_exit(snd_pxa_pcm_exit);
134 152
135MODULE_AUTHOR("Nicolas Pitre"); 153MODULE_AUTHOR("Nicolas Pitre");
136MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); 154MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h
deleted file mode 100644
index 60c3b20aeeb4..000000000000
--- a/sound/soc/pxa/pxa2xx-pcm.h
+++ /dev/null
@@ -1,19 +0,0 @@
1/*
2 * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip
3 *
4 * Author: Nicolas Pitre
5 * Created: Nov 30, 2004
6 * Copyright: MontaVista Software, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _PXA2XX_PCM_H
14#define _PXA2XX_PCM_H
15
16/* platform data */
17extern struct snd_soc_platform pxa2xx_soc_platform;
18
19#endif
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
index 7e3f41696c41..2cda82bc5d2e 100644
--- a/sound/soc/pxa/raumfeld.c
+++ b/sound/soc/pxa/raumfeld.c
@@ -26,9 +26,6 @@
26 26
27#include <asm/mach-types.h> 27#include <asm/mach-types.h>
28 28
29#include "../codecs/cs4270.h"
30#include "../codecs/ak4104.h"
31#include "pxa2xx-pcm.h"
32#include "pxa-ssp.h" 29#include "pxa-ssp.h"
33 30
34#define GPIO_SPDIF_RESET (38) 31#define GPIO_SPDIF_RESET (38)
@@ -71,7 +68,7 @@ static void raumfeld_enable_audio(bool en)
71static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream) 68static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream)
72{ 69{
73 struct snd_soc_pcm_runtime *rtd = substream->private_data; 70 struct snd_soc_pcm_runtime *rtd = substream->private_data;
74 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 71 struct snd_soc_dai *codec_dai = rtd->codec_dai;
75 72
76 /* set freq to 0 to enable all possible codec sample rates */ 73 /* set freq to 0 to enable all possible codec sample rates */
77 return snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); 74 return snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
@@ -80,7 +77,7 @@ static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream)
80static void raumfeld_cs4270_shutdown(struct snd_pcm_substream *substream) 77static void raumfeld_cs4270_shutdown(struct snd_pcm_substream *substream)
81{ 78{
82 struct snd_soc_pcm_runtime *rtd = substream->private_data; 79 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 80 struct snd_soc_dai *codec_dai = rtd->codec_dai;
84 81
85 /* set freq to 0 to enable all possible codec sample rates */ 82 /* set freq to 0 to enable all possible codec sample rates */
86 snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0); 83 snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
@@ -90,8 +87,8 @@ static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream,
90 struct snd_pcm_hw_params *params) 87 struct snd_pcm_hw_params *params)
91{ 88{
92 struct snd_soc_pcm_runtime *rtd = substream->private_data; 89 struct snd_soc_pcm_runtime *rtd = substream->private_data;
93 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 90 struct snd_soc_dai *codec_dai = rtd->codec_dai;
94 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 91 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
95 unsigned int fmt, clk = 0; 92 unsigned int fmt, clk = 0;
96 int ret = 0; 93 int ret = 0;
97 94
@@ -167,32 +164,14 @@ static int raumfeld_line_resume(struct platform_device *pdev)
167 return 0; 164 return 0;
168} 165}
169 166
170static struct snd_soc_dai_link raumfeld_line_dai = {
171 .name = "CS4270",
172 .stream_name = "CS4270",
173 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1],
174 .codec_dai = &cs4270_dai,
175 .ops = &raumfeld_cs4270_ops,
176};
177
178static struct snd_soc_card snd_soc_line_raumfeld = {
179 .name = "Raumfeld analog",
180 .platform = &pxa2xx_soc_platform,
181 .dai_link = &raumfeld_line_dai,
182 .suspend_post = raumfeld_line_suspend,
183 .resume_pre = raumfeld_line_resume,
184 .num_links = 1,
185};
186
187
188/* AK4104 */ 167/* AK4104 */
189 168
190static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream, 169static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream,
191 struct snd_pcm_hw_params *params) 170 struct snd_pcm_hw_params *params)
192{ 171{
193 struct snd_soc_pcm_runtime *rtd = substream->private_data; 172 struct snd_soc_pcm_runtime *rtd = substream->private_data;
194 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 173 struct snd_soc_dai *codec_dai = rtd->codec_dai;
195 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 174 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
196 int fmt, ret = 0, clk = 0; 175 int fmt, ret = 0, clk = 0;
197 176
198 switch (params_rate(params)) { 177 switch (params_rate(params)) {
@@ -247,34 +226,35 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {
247 .hw_params = raumfeld_ak4104_hw_params, 226 .hw_params = raumfeld_ak4104_hw_params,
248}; 227};
249 228
250static struct snd_soc_dai_link raumfeld_spdif_dai = { 229static struct snd_soc_dai_link raumfeld_dai[] = {
230{
251 .name = "ak4104", 231 .name = "ak4104",
252 .stream_name = "Playback", 232 .stream_name = "Playback",
253 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP2], 233 .cpu_dai_name = "pxa-ssp-dai.1",
254 .codec_dai = &ak4104_dai, 234 .codec_dai_name = "ak4104-hifi",
235 .platform_name = "pxa-pcm-audio",
255 .ops = &raumfeld_ak4104_ops, 236 .ops = &raumfeld_ak4104_ops,
256}; 237 .codec_name = "ak4104-codec.0",
257 238},
258static struct snd_soc_card snd_soc_spdif_raumfeld = { 239{
259 .name = "Raumfeld S/PDIF", 240 .name = "CS4270",
260 .platform = &pxa2xx_soc_platform, 241 .stream_name = "CS4270",
261 .dai_link = &raumfeld_spdif_dai, 242 .cpu_dai_name = "pxa-ssp-dai.0",
262 .num_links = 1 243 .platform_name = "pxa-pcm-audio",
263}; 244 .codec_dai_name = "cs4270-hifi",
264 245 .codec_name = "cs4270-codec.0-0048",
265/* raumfeld_audio audio subsystem */ 246 .ops = &raumfeld_cs4270_ops,
266static struct snd_soc_device raumfeld_line_devdata = { 247},};
267 .card = &snd_soc_line_raumfeld,
268 .codec_dev = &soc_codec_device_cs4270,
269};
270 248
271static struct snd_soc_device raumfeld_spdif_devdata = { 249static struct snd_soc_card snd_soc_raumfeld = {
272 .card = &snd_soc_spdif_raumfeld, 250 .name = "Raumfeld",
273 .codec_dev = &soc_codec_device_ak4104, 251 .dai_link = raumfeld_dai,
252 .suspend_post = raumfeld_line_suspend,
253 .resume_pre = raumfeld_line_resume,
254 .num_links = ARRAY_SIZE(raumfeld_dai),
274}; 255};
275 256
276static struct platform_device *raumfeld_audio_line_device; 257static struct platform_device *raumfeld_audio_device;
277static struct platform_device *raumfeld_audio_spdif_device;
278 258
279static int __init raumfeld_audio_init(void) 259static int __init raumfeld_audio_init(void)
280{ 260{
@@ -292,38 +272,19 @@ static int __init raumfeld_audio_init(void)
292 272
293 set_max9485_clk(MAX9485_MCLK_FREQ_122880); 273 set_max9485_clk(MAX9485_MCLK_FREQ_122880);
294 274
295 /* LINE */ 275 /* Register LINE and SPDIF */
296 raumfeld_audio_line_device = platform_device_alloc("soc-audio", 0); 276 raumfeld_audio_device = platform_device_alloc("soc-audio", 0);
297 if (!raumfeld_audio_line_device) 277 if (!raumfeld_audio_device)
298 return -ENOMEM; 278 return -ENOMEM;
299 279
300 platform_set_drvdata(raumfeld_audio_line_device, 280 platform_set_drvdata(raumfeld_audio_device,
301 &raumfeld_line_devdata); 281 &snd_soc_raumfeld);
302 raumfeld_line_devdata.dev = &raumfeld_audio_line_device->dev; 282 ret = platform_device_add(raumfeld_audio_device);
303 ret = platform_device_add(raumfeld_audio_line_device);
304 if (ret)
305 platform_device_put(raumfeld_audio_line_device);
306 283
307 /* no S/PDIF on Speakers */ 284 /* no S/PDIF on Speakers */
308 if (machine_is_raumfeld_speaker()) 285 if (machine_is_raumfeld_speaker())
309 return ret; 286 return ret;
310 287
311 /* S/PDIF */
312 raumfeld_audio_spdif_device = platform_device_alloc("soc-audio", 1);
313 if (!raumfeld_audio_spdif_device) {
314 platform_device_put(raumfeld_audio_line_device);
315 return -ENOMEM;
316 }
317
318 platform_set_drvdata(raumfeld_audio_spdif_device,
319 &raumfeld_spdif_devdata);
320 raumfeld_spdif_devdata.dev = &raumfeld_audio_spdif_device->dev;
321 ret = platform_device_add(raumfeld_audio_spdif_device);
322 if (ret) {
323 platform_device_put(raumfeld_audio_line_device);
324 platform_device_put(raumfeld_audio_spdif_device);
325 }
326
327 raumfeld_enable_audio(true); 288 raumfeld_enable_audio(true);
328 289
329 return ret; 290 return ret;
@@ -333,10 +294,7 @@ static void __exit raumfeld_audio_exit(void)
333{ 294{
334 raumfeld_enable_audio(false); 295 raumfeld_enable_audio(false);
335 296
336 platform_device_unregister(raumfeld_audio_line_device); 297 platform_device_unregister(raumfeld_audio_device);
337
338 if (machine_is_raumfeld_connector())
339 platform_device_unregister(raumfeld_audio_spdif_device);
340 298
341 i2c_unregister_device(max9486_client); 299 i2c_unregister_device(max9486_client);
342 300
diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c
new file mode 100644
index 000000000000..d63cb474b4e1
--- /dev/null
+++ b/sound/soc/pxa/saarb.c
@@ -0,0 +1,200 @@
1/*
2 * saarb.c -- SoC audio for saarb
3 *
4 * Copyright (C) 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/device.h>
15#include <linux/clk.h>
16#include <linux/i2c.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22#include <sound/jack.h>
23
24#include <asm/mach-types.h>
25
26#include "../codecs/88pm860x-codec.h"
27#include "pxa-ssp.h"
28
29static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd);
30
31static struct platform_device *saarb_snd_device;
32
33static struct snd_soc_jack hs_jack, mic_jack;
34
35static struct snd_soc_jack_pin hs_jack_pins[] = {
36 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
37};
38
39static struct snd_soc_jack_pin mic_jack_pins[] = {
40 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, },
41};
42
43/* saarb machine dapm widgets */
44static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = {
45 SND_SOC_DAPM_HP("Headphone Stereophone", NULL),
46 SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
47 SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
48 SND_SOC_DAPM_SPK("Ext Speaker", NULL),
49 SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
50 SND_SOC_DAPM_MIC("Headset Mic", NULL),
51 SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
52};
53
54/* saarb machine audio map */
55static const struct snd_soc_dapm_route audio_map[] = {
56 {"Headset Stereophone", NULL, "HS1"},
57 {"Headset Stereophone", NULL, "HS2"},
58
59 {"Ext Speaker", NULL, "LSP"},
60 {"Ext Speaker", NULL, "LSN"},
61
62 {"Lineout Out 1", NULL, "LINEOUT1"},
63 {"Lineout Out 2", NULL, "LINEOUT2"},
64
65 {"MIC1P", NULL, "Mic1 Bias"},
66 {"MIC1N", NULL, "Mic1 Bias"},
67 {"Mic1 Bias", NULL, "Ext Mic 1"},
68
69 {"MIC2P", NULL, "Mic1 Bias"},
70 {"MIC2N", NULL, "Mic1 Bias"},
71 {"Mic1 Bias", NULL, "Headset Mic 2"},
72
73 {"MIC3P", NULL, "Mic3 Bias"},
74 {"MIC3N", NULL, "Mic3 Bias"},
75 {"Mic3 Bias", NULL, "Ext Mic 3"},
76};
77
78static int saarb_i2s_hw_params(struct snd_pcm_substream *substream,
79 struct snd_pcm_hw_params *params)
80{
81 struct snd_soc_pcm_runtime *rtd = substream->private_data;
82 struct snd_soc_dai *codec_dai = rtd->codec_dai;
83 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
84 int width = snd_pcm_format_physical_width(params_format(params));
85 int ret;
86
87 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
88 PM860X_CLK_DIR_OUT);
89 if (ret < 0)
90 return ret;
91
92 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
93 if (ret < 0)
94 return ret;
95
96 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
97 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
98 if (ret < 0)
99 return ret;
100 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
101 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
102 if (ret < 0)
103 return ret;
104
105 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
106
107 return ret;
108}
109
110static struct snd_soc_ops saarb_i2s_ops = {
111 .hw_params = saarb_i2s_hw_params,
112};
113
114static struct snd_soc_dai_link saarb_dai[] = {
115 {
116 .name = "88PM860x I2S",
117 .stream_name = "I2S Audio",
118 .cpu_dai_name = "pxa-ssp-dai.1",
119 .codec_dai_name = "88pm860x-i2s",
120 .platform_name = "pxa-pcm-audio",
121 .codec_name = "88pm860x-codec",
122 .init = saarb_pm860x_init,
123 .ops = &saarb_i2s_ops,
124 },
125};
126
127static struct snd_soc_card snd_soc_card_saarb = {
128 .name = "Saarb",
129 .dai_link = saarb_dai,
130 .num_links = ARRAY_SIZE(saarb_dai),
131};
132
133static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
134{
135 struct snd_soc_codec *codec = rtd->codec;
136 int ret;
137
138 snd_soc_dapm_new_controls(codec, saarb_dapm_widgets,
139 ARRAY_SIZE(saarb_dapm_widgets));
140 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
141
142 /* connected pins */
143 snd_soc_dapm_enable_pin(codec, "Ext Speaker");
144 snd_soc_dapm_enable_pin(codec, "Ext Mic 1");
145 snd_soc_dapm_enable_pin(codec, "Ext Mic 3");
146 snd_soc_dapm_disable_pin(codec, "Headset Mic 2");
147 snd_soc_dapm_disable_pin(codec, "Headset Stereophone");
148
149 ret = snd_soc_dapm_sync(codec);
150 if (ret)
151 return ret;
152
153 /* Headset jack detection */
154 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
155 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
156 &hs_jack);
157 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
158 hs_jack_pins);
159 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
160 &mic_jack);
161 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
162 mic_jack_pins);
163
164 /* headphone, microphone detection & headset short detection */
165 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
166 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
167 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
168 return 0;
169}
170
171static int __init saarb_init(void)
172{
173 int ret;
174
175 if (!machine_is_saarb())
176 return -ENODEV;
177 saarb_snd_device = platform_device_alloc("soc-audio", -1);
178 if (!saarb_snd_device)
179 return -ENOMEM;
180
181 platform_set_drvdata(saarb_snd_device, &snd_soc_card_saarb);
182
183 ret = platform_device_add(saarb_snd_device);
184 if (ret)
185 platform_device_put(saarb_snd_device);
186
187 return ret;
188}
189
190static void __exit saarb_exit(void)
191{
192 platform_device_unregister(saarb_snd_device);
193}
194
195module_init(saarb_init);
196module_exit(saarb_exit);
197
198MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
199MODULE_DESCRIPTION("ALSA SoC 88PM860x Saarb");
200MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index d256f5f313b5..f470f360f4dd 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -28,7 +28,6 @@
28#include <asm/mach-types.h> 28#include <asm/mach-types.h>
29#include <mach/spitz.h> 29#include <mach/spitz.h>
30#include "../codecs/wm8750.h" 30#include "../codecs/wm8750.h"
31#include "pxa2xx-pcm.h"
32#include "pxa2xx-i2s.h" 31#include "pxa2xx-i2s.h"
33 32
34#define SPITZ_HP 0 33#define SPITZ_HP 0
@@ -107,7 +106,7 @@ static void spitz_ext_control(struct snd_soc_codec *codec)
107static int spitz_startup(struct snd_pcm_substream *substream) 106static int spitz_startup(struct snd_pcm_substream *substream)
108{ 107{
109 struct snd_soc_pcm_runtime *rtd = substream->private_data; 108 struct snd_soc_pcm_runtime *rtd = substream->private_data;
110 struct snd_soc_codec *codec = rtd->socdev->card->codec; 109 struct snd_soc_codec *codec = rtd->codec;
111 110
112 /* check the jack status at stream startup */ 111 /* check the jack status at stream startup */
113 spitz_ext_control(codec); 112 spitz_ext_control(codec);
@@ -118,8 +117,8 @@ static int spitz_hw_params(struct snd_pcm_substream *substream,
118 struct snd_pcm_hw_params *params) 117 struct snd_pcm_hw_params *params)
119{ 118{
120 struct snd_soc_pcm_runtime *rtd = substream->private_data; 119 struct snd_soc_pcm_runtime *rtd = substream->private_data;
121 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 120 struct snd_soc_dai *codec_dai = rtd->codec_dai;
122 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 121 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
123 unsigned int clk = 0; 122 unsigned int clk = 0;
124 int ret = 0; 123 int ret = 0;
125 124
@@ -274,8 +273,9 @@ static const struct snd_kcontrol_new wm8750_spitz_controls[] = {
274/* 273/*
275 * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device 274 * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device
276 */ 275 */
277static int spitz_wm8750_init(struct snd_soc_codec *codec) 276static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd)
278{ 277{
278 struct snd_soc_codec *codec = rtd->codec;
279 int err; 279 int err;
280 280
281 /* NC codec pins */ 281 /* NC codec pins */
@@ -308,8 +308,10 @@ static int spitz_wm8750_init(struct snd_soc_codec *codec)
308static struct snd_soc_dai_link spitz_dai = { 308static struct snd_soc_dai_link spitz_dai = {
309 .name = "wm8750", 309 .name = "wm8750",
310 .stream_name = "WM8750", 310 .stream_name = "WM8750",
311 .cpu_dai = &pxa_i2s_dai, 311 .cpu_dai_name = "pxa-is2",
312 .codec_dai = &wm8750_dai, 312 .codec_dai_name = "wm8750-hifi",
313 .platform_name = "pxa-pcm-audio",
314 .codec_name = "wm8750-codec.0-001a",
313 .init = spitz_wm8750_init, 315 .init = spitz_wm8750_init,
314 .ops = &spitz_ops, 316 .ops = &spitz_ops,
315}; 317};
@@ -317,17 +319,10 @@ static struct snd_soc_dai_link spitz_dai = {
317/* spitz audio machine driver */ 319/* spitz audio machine driver */
318static struct snd_soc_card snd_soc_spitz = { 320static struct snd_soc_card snd_soc_spitz = {
319 .name = "Spitz", 321 .name = "Spitz",
320 .platform = &pxa2xx_soc_platform,
321 .dai_link = &spitz_dai, 322 .dai_link = &spitz_dai,
322 .num_links = 1, 323 .num_links = 1,
323}; 324};
324 325
325/* spitz audio subsystem */
326static struct snd_soc_device spitz_snd_devdata = {
327 .card = &snd_soc_spitz,
328 .codec_dev = &soc_codec_dev_wm8750,
329};
330
331static struct platform_device *spitz_snd_device; 326static struct platform_device *spitz_snd_device;
332 327
333static int __init spitz_init(void) 328static int __init spitz_init(void)
@@ -341,8 +336,7 @@ static int __init spitz_init(void)
341 if (!spitz_snd_device) 336 if (!spitz_snd_device)
342 return -ENOMEM; 337 return -ENOMEM;
343 338
344 platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata); 339 platform_set_drvdata(spitz_snd_device, &snd_soc_spitz);
345 spitz_snd_devdata.dev = &spitz_snd_device->dev;
346 ret = platform_device_add(spitz_snd_device); 340 ret = platform_device_add(spitz_snd_device);
347 341
348 if (ret) 342 if (ret)
diff --git a/sound/soc/pxa/tavorevb3.c b/sound/soc/pxa/tavorevb3.c
new file mode 100644
index 000000000000..248c283fc4df
--- /dev/null
+++ b/sound/soc/pxa/tavorevb3.c
@@ -0,0 +1,200 @@
1/*
2 * tavorevb3.c -- SoC audio for Tavor EVB3
3 *
4 * Copyright (C) 2010 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/module.h>
13#include <linux/moduleparam.h>
14#include <linux/device.h>
15#include <linux/clk.h>
16#include <linux/i2c.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/pcm_params.h>
20#include <sound/soc.h>
21#include <sound/soc-dapm.h>
22#include <sound/jack.h>
23
24#include <asm/mach-types.h>
25
26#include "../codecs/88pm860x-codec.h"
27#include "pxa-ssp.h"
28
29static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd);
30
31static struct platform_device *evb3_snd_device;
32
33static struct snd_soc_jack hs_jack, mic_jack;
34
35static struct snd_soc_jack_pin hs_jack_pins[] = {
36 { .pin = "Headset Stereophone", .mask = SND_JACK_HEADPHONE, },
37};
38
39static struct snd_soc_jack_pin mic_jack_pins[] = {
40 { .pin = "Headset Mic 2", .mask = SND_JACK_MICROPHONE, },
41};
42
43/* tavorevb3 machine dapm widgets */
44static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = {
45 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
46 SND_SOC_DAPM_LINE("Lineout Out 1", NULL),
47 SND_SOC_DAPM_LINE("Lineout Out 2", NULL),
48 SND_SOC_DAPM_SPK("Ext Speaker", NULL),
49 SND_SOC_DAPM_MIC("Ext Mic 1", NULL),
50 SND_SOC_DAPM_MIC("Headset Mic 2", NULL),
51 SND_SOC_DAPM_MIC("Ext Mic 3", NULL),
52};
53
54/* tavorevb3 machine audio map */
55static const struct snd_soc_dapm_route audio_map[] = {
56 {"Headset Stereophone", NULL, "HS1"},
57 {"Headset Stereophone", NULL, "HS2"},
58
59 {"Ext Speaker", NULL, "LSP"},
60 {"Ext Speaker", NULL, "LSN"},
61
62 {"Lineout Out 1", NULL, "LINEOUT1"},
63 {"Lineout Out 2", NULL, "LINEOUT2"},
64
65 {"MIC1P", NULL, "Mic1 Bias"},
66 {"MIC1N", NULL, "Mic1 Bias"},
67 {"Mic1 Bias", NULL, "Ext Mic 1"},
68
69 {"MIC2P", NULL, "Mic1 Bias"},
70 {"MIC2N", NULL, "Mic1 Bias"},
71 {"Mic1 Bias", NULL, "Headset Mic 2"},
72
73 {"MIC3P", NULL, "Mic3 Bias"},
74 {"MIC3N", NULL, "Mic3 Bias"},
75 {"Mic3 Bias", NULL, "Ext Mic 3"},
76};
77
78static int evb3_i2s_hw_params(struct snd_pcm_substream *substream,
79 struct snd_pcm_hw_params *params)
80{
81 struct snd_soc_pcm_runtime *rtd = substream->private_data;
82 struct snd_soc_dai *codec_dai = rtd->codec_dai;
83 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
84 int width = snd_pcm_format_physical_width(params_format(params));
85 int ret;
86
87 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_NET_PLL, 0,
88 PM860X_CLK_DIR_OUT);
89 if (ret < 0)
90 return ret;
91
92 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, PM860X_CLK_DIR_OUT);
93 if (ret < 0)
94 return ret;
95
96 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
97 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
98 if (ret < 0)
99 return ret;
100
101 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
102 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
103 if (ret < 0)
104 return ret;
105
106 ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
107 return ret;
108}
109
110static struct snd_soc_ops evb3_i2s_ops = {
111 .hw_params = evb3_i2s_hw_params,
112};
113
114static struct snd_soc_dai_link evb3_dai[] = {
115 {
116 .name = "88PM860x I2S",
117 .stream_name = "I2S Audio",
118 .cpu_dai_name = "pxa-ssp-dai.1",
119 .codec_dai_name = "88pm860x-i2s",
120 .platform_name = "pxa-pcm-audio",
121 .codec_name = "88pm860x-codec",
122 .init = evb3_pm860x_init,
123 .ops = &evb3_i2s_ops,
124 },
125};
126
127static struct snd_soc_card snd_soc_card_evb3 = {
128 .name = "Tavor EVB3",
129 .dai_link = evb3_dai,
130 .num_links = ARRAY_SIZE(evb3_dai),
131};
132
133static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
134{
135 struct snd_soc_codec *codec = rtd->codec;
136 int ret;
137
138 snd_soc_dapm_new_controls(codec, evb3_dapm_widgets,
139 ARRAY_SIZE(evb3_dapm_widgets));
140 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
141
142 /* connected pins */
143 snd_soc_dapm_enable_pin(codec, "Ext Speaker");
144 snd_soc_dapm_enable_pin(codec, "Ext Mic 1");
145 snd_soc_dapm_enable_pin(codec, "Ext Mic 3");
146 snd_soc_dapm_disable_pin(codec, "Headset Mic 2");
147 snd_soc_dapm_disable_pin(codec, "Headset Stereophone");
148
149 ret = snd_soc_dapm_sync(codec);
150 if (ret)
151 return ret;
152
153 /* Headset jack detection */
154 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
155 | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
156 &hs_jack);
157 snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
158 hs_jack_pins);
159 snd_soc_jack_new(codec, "Microphone Jack", SND_JACK_MICROPHONE,
160 &mic_jack);
161 snd_soc_jack_add_pins(&mic_jack, ARRAY_SIZE(mic_jack_pins),
162 mic_jack_pins);
163
164 /* headphone, microphone detection & headset short detection */
165 pm860x_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADPHONE,
166 SND_JACK_BTN_0, SND_JACK_BTN_1, SND_JACK_BTN_2);
167 pm860x_mic_jack_detect(codec, &hs_jack, SND_JACK_MICROPHONE);
168 return 0;
169}
170
171static int __init tavorevb3_init(void)
172{
173 int ret;
174
175 if (!machine_is_tavorevb3())
176 return -ENODEV;
177 evb3_snd_device = platform_device_alloc("soc-audio", -1);
178 if (!evb3_snd_device)
179 return -ENOMEM;
180
181 platform_set_drvdata(evb3_snd_device, &snd_soc_card_evb3);
182
183 ret = platform_device_add(evb3_snd_device);
184 if (ret)
185 platform_device_put(evb3_snd_device);
186
187 return ret;
188}
189
190static void __exit tavorevb3_exit(void)
191{
192 platform_device_unregister(evb3_snd_device);
193}
194
195module_init(tavorevb3_init);
196module_exit(tavorevb3_exit);
197
198MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
199MODULE_DESCRIPTION("ALSA SoC 88PM860x Tavor EVB3");
200MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index dbbd3e9d1637..a3bfb2e8b70f 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -33,7 +33,6 @@
33#include <mach/audio.h> 33#include <mach/audio.h>
34 34
35#include "../codecs/wm9712.h" 35#include "../codecs/wm9712.h"
36#include "pxa2xx-pcm.h"
37#include "pxa2xx-ac97.h" 36#include "pxa2xx-ac97.h"
38 37
39static struct snd_soc_card tosa; 38static struct snd_soc_card tosa;
@@ -80,7 +79,7 @@ static void tosa_ext_control(struct snd_soc_codec *codec)
80static int tosa_startup(struct snd_pcm_substream *substream) 79static int tosa_startup(struct snd_pcm_substream *substream)
81{ 80{
82 struct snd_soc_pcm_runtime *rtd = substream->private_data; 81 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_codec *codec = rtd->socdev->card->codec; 82 struct snd_soc_codec *codec = rtd->card->codec;
84 83
85 /* check the jack status at stream startup */ 84 /* check the jack status at stream startup */
86 tosa_ext_control(codec); 85 tosa_ext_control(codec);
@@ -184,8 +183,9 @@ static const struct snd_kcontrol_new tosa_controls[] = {
184 tosa_set_spk), 183 tosa_set_spk),
185}; 184};
186 185
187static int tosa_ac97_init(struct snd_soc_codec *codec) 186static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
188{ 187{
188 struct snd_soc_codec *codec = rtd->codec;
189 int err; 189 int err;
190 190
191 snd_soc_dapm_nc_pin(codec, "OUT3"); 191 snd_soc_dapm_nc_pin(codec, "OUT3");
@@ -212,16 +212,20 @@ static struct snd_soc_dai_link tosa_dai[] = {
212{ 212{
213 .name = "AC97", 213 .name = "AC97",
214 .stream_name = "AC97 HiFi", 214 .stream_name = "AC97 HiFi",
215 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 215 .cpu_dai_name = "pxa-ac97.0",
216 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], 216 .codec_dai_name = "wm9712-hifi",
217 .platform_name = "pxa-pcm-audio",
218 .codec_name = "wm9712-codec",
217 .init = tosa_ac97_init, 219 .init = tosa_ac97_init,
218 .ops = &tosa_ops, 220 .ops = &tosa_ops,
219}, 221},
220{ 222{
221 .name = "AC97 Aux", 223 .name = "AC97 Aux",
222 .stream_name = "AC97 Aux", 224 .stream_name = "AC97 Aux",
223 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 225 .cpu_dai_name = "pxa-ac97.1",
224 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], 226 .codec_dai_name = "wm9712-aux",
227 .platform_name = "pxa-pcm-audio",
228 .codec_name = "wm9712-codec",
225 .ops = &tosa_ops, 229 .ops = &tosa_ops,
226}, 230},
227}; 231};
@@ -248,18 +252,12 @@ static int tosa_remove(struct platform_device *dev)
248 252
249static struct snd_soc_card tosa = { 253static struct snd_soc_card tosa = {
250 .name = "Tosa", 254 .name = "Tosa",
251 .platform = &pxa2xx_soc_platform,
252 .dai_link = tosa_dai, 255 .dai_link = tosa_dai,
253 .num_links = ARRAY_SIZE(tosa_dai), 256 .num_links = ARRAY_SIZE(tosa_dai),
254 .probe = tosa_probe, 257 .probe = tosa_probe,
255 .remove = tosa_remove, 258 .remove = tosa_remove,
256}; 259};
257 260
258static struct snd_soc_device tosa_snd_devdata = {
259 .card = &tosa,
260 .codec_dev = &soc_codec_dev_wm9712,
261};
262
263static struct platform_device *tosa_snd_device; 261static struct platform_device *tosa_snd_device;
264 262
265static int __init tosa_init(void) 263static int __init tosa_init(void)
@@ -275,8 +273,7 @@ static int __init tosa_init(void)
275 goto err_alloc; 273 goto err_alloc;
276 } 274 }
277 275
278 platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata); 276 platform_set_drvdata(tosa_snd_device, &tosa);
279 tosa_snd_devdata.dev = &tosa_snd_device->dev;
280 ret = platform_device_add(tosa_snd_device); 277 ret = platform_device_add(tosa_snd_device);
281 278
282 if (!ret) 279 if (!ret)
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c
index 4e4d2fa8ddc5..4cc841b44182 100644
--- a/sound/soc/pxa/z2.c
+++ b/sound/soc/pxa/z2.c
@@ -30,7 +30,6 @@
30#include <mach/z2.h> 30#include <mach/z2.h>
31 31
32#include "../codecs/wm8750.h" 32#include "../codecs/wm8750.h"
33#include "pxa2xx-pcm.h"
34#include "pxa2xx-i2s.h" 33#include "pxa2xx-i2s.h"
35 34
36static struct snd_soc_card snd_soc_z2; 35static struct snd_soc_card snd_soc_z2;
@@ -39,8 +38,8 @@ static int z2_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params) 38 struct snd_pcm_hw_params *params)
40{ 39{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data; 40 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 41 struct snd_soc_dai *codec_dai = rtd->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 42 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
44 unsigned int clk = 0; 43 unsigned int clk = 0;
45 int ret = 0; 44 int ret = 0;
46 45
@@ -138,8 +137,9 @@ static const struct snd_soc_dapm_route audio_map[] = {
138/* 137/*
139 * Logic for a wm8750 as connected on a Z2 Device 138 * Logic for a wm8750 as connected on a Z2 Device
140 */ 139 */
141static int z2_wm8750_init(struct snd_soc_codec *codec) 140static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
142{ 141{
142 struct snd_soc_codec *codec = rtd->codec;
143 int ret; 143 int ret;
144 144
145 /* NC codec pins */ 145 /* NC codec pins */
@@ -160,7 +160,7 @@ static int z2_wm8750_init(struct snd_soc_codec *codec)
160 goto err; 160 goto err;
161 161
162 /* Jack detection API stuff */ 162 /* Jack detection API stuff */
163 ret = snd_soc_jack_new(&snd_soc_z2, "Headset Jack", SND_JACK_HEADSET, 163 ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
164 &hs_jack); 164 &hs_jack);
165 if (ret) 165 if (ret)
166 goto err; 166 goto err;
@@ -189,8 +189,10 @@ static struct snd_soc_ops z2_ops = {
189static struct snd_soc_dai_link z2_dai = { 189static struct snd_soc_dai_link z2_dai = {
190 .name = "wm8750", 190 .name = "wm8750",
191 .stream_name = "WM8750", 191 .stream_name = "WM8750",
192 .cpu_dai = &pxa_i2s_dai, 192 .cpu_dai_name = "pxa2xx-i2s",
193 .codec_dai = &wm8750_dai, 193 .codec_dai_name = "wm8750-hifi",
194 .platform_name = "pxa-pcm-audio",
195 .codec_name = "wm8750-codec.0-001a",
194 .init = z2_wm8750_init, 196 .init = z2_wm8750_init,
195 .ops = &z2_ops, 197 .ops = &z2_ops,
196}; 198};
@@ -198,17 +200,10 @@ static struct snd_soc_dai_link z2_dai = {
198/* z2 audio machine driver */ 200/* z2 audio machine driver */
199static struct snd_soc_card snd_soc_z2 = { 201static struct snd_soc_card snd_soc_z2 = {
200 .name = "Z2", 202 .name = "Z2",
201 .platform = &pxa2xx_soc_platform,
202 .dai_link = &z2_dai, 203 .dai_link = &z2_dai,
203 .num_links = 1, 204 .num_links = 1,
204}; 205};
205 206
206/* z2 audio subsystem */
207static struct snd_soc_device z2_snd_devdata = {
208 .card = &snd_soc_z2,
209 .codec_dev = &soc_codec_dev_wm8750,
210};
211
212static struct platform_device *z2_snd_device; 207static struct platform_device *z2_snd_device;
213 208
214static int __init z2_init(void) 209static int __init z2_init(void)
@@ -222,8 +217,7 @@ static int __init z2_init(void)
222 if (!z2_snd_device) 217 if (!z2_snd_device)
223 return -ENOMEM; 218 return -ENOMEM;
224 219
225 platform_set_drvdata(z2_snd_device, &z2_snd_devdata); 220 platform_set_drvdata(z2_snd_device, &snd_soc_z2);
226 z2_snd_devdata.dev = &z2_snd_device->dev;
227 ret = platform_device_add(z2_snd_device); 221 ret = platform_device_add(z2_snd_device);
228 222
229 if (ret) 223 if (ret)
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index dd678ae24398..d27e05af7759 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -23,7 +23,6 @@
23#include <sound/soc-dapm.h> 23#include <sound/soc-dapm.h>
24 24
25#include "../codecs/wm9713.h" 25#include "../codecs/wm9713.h"
26#include "pxa2xx-pcm.h"
27#include "pxa2xx-ac97.h" 26#include "pxa2xx-ac97.h"
28#include "pxa-ssp.h" 27#include "pxa-ssp.h"
29 28
@@ -71,10 +70,12 @@ static const struct snd_soc_dapm_route audio_map[] = {
71 { "Multiactor", NULL, "SPKR" }, 70 { "Multiactor", NULL, "SPKR" },
72}; 71};
73 72
74static int zylonite_wm9713_init(struct snd_soc_codec *codec) 73static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd)
75{ 74{
75 struct snd_soc_codec *codec = rtd->codec;
76
76 if (clk_pout) 77 if (clk_pout)
77 snd_soc_dai_set_pll(&codec->dai[0], 0, 0, 78 snd_soc_dai_set_pll(rtd->codec_dai, 0, 0,
78 clk_get_rate(pout), 0); 79 clk_get_rate(pout), 0);
79 80
80 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, 81 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
@@ -94,8 +95,8 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
94 struct snd_pcm_hw_params *params) 95 struct snd_pcm_hw_params *params)
95{ 96{
96 struct snd_soc_pcm_runtime *rtd = substream->private_data; 97 struct snd_soc_pcm_runtime *rtd = substream->private_data;
97 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 98 struct snd_soc_dai *codec_dai = rtd->codec_dai;
98 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 99 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
99 unsigned int pll_out = 0; 100 unsigned int pll_out = 0;
100 unsigned int wm9713_div = 0; 101 unsigned int wm9713_div = 0;
101 int ret = 0; 102 int ret = 0;
@@ -163,21 +164,27 @@ static struct snd_soc_dai_link zylonite_dai[] = {
163{ 164{
164 .name = "AC97", 165 .name = "AC97",
165 .stream_name = "AC97 HiFi", 166 .stream_name = "AC97 HiFi",
166 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], 167 .codec_name = "wm9713-codec",
167 .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], 168 .platform_name = "pxa-pcm-audio",
169 .cpu_dai_name = "pxa-ac97.0",
170 .codec_name = "wm9713-hifi",
168 .init = zylonite_wm9713_init, 171 .init = zylonite_wm9713_init,
169}, 172},
170{ 173{
171 .name = "AC97 Aux", 174 .name = "AC97 Aux",
172 .stream_name = "AC97 Aux", 175 .stream_name = "AC97 Aux",
173 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], 176 .codec_name = "wm9713-codec",
174 .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], 177 .platform_name = "pxa-pcm-audio",
178 .cpu_dai_name = "pxa-ac97.1",
179 .codec_name = "wm9713-aux",
175}, 180},
176{ 181{
177 .name = "WM9713 Voice", 182 .name = "WM9713 Voice",
178 .stream_name = "WM9713 Voice", 183 .stream_name = "WM9713 Voice",
179 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3], 184 .codec_name = "wm9713-codec",
180 .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE], 185 .platform_name = "pxa-pcm-audio",
186 .cpu_dai_name = "pxa-ssp-dai.2",
187 .codec_name = "wm9713-voice",
181 .ops = &zylonite_voice_ops, 188 .ops = &zylonite_voice_ops,
182}, 189},
183}; 190};
@@ -248,14 +255,9 @@ static struct snd_soc_card zylonite = {
248 .remove = &zylonite_remove, 255 .remove = &zylonite_remove,
249 .suspend_post = &zylonite_suspend_post, 256 .suspend_post = &zylonite_suspend_post,
250 .resume_pre = &zylonite_resume_pre, 257 .resume_pre = &zylonite_resume_pre,
251 .platform = &pxa2xx_soc_platform,
252 .dai_link = zylonite_dai, 258 .dai_link = zylonite_dai,
253 .num_links = ARRAY_SIZE(zylonite_dai), 259 .num_links = ARRAY_SIZE(zylonite_dai),
254}; 260 .owner = THIS_MODULE,
255
256static struct snd_soc_device zylonite_snd_ac97_devdata = {
257 .card = &zylonite,
258 .codec_dev = &soc_codec_dev_wm9713,
259}; 261};
260 262
261static struct platform_device *zylonite_snd_ac97_device; 263static struct platform_device *zylonite_snd_ac97_device;
@@ -268,9 +270,7 @@ static int __init zylonite_init(void)
268 if (!zylonite_snd_ac97_device) 270 if (!zylonite_snd_ac97_device)
269 return -ENOMEM; 271 return -ENOMEM;
270 272
271 platform_set_drvdata(zylonite_snd_ac97_device, 273 platform_set_drvdata(zylonite_snd_ac97_device, &zylonite);
272 &zylonite_snd_ac97_devdata);
273 zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev;
274 274
275 ret = platform_device_add(zylonite_snd_ac97_device); 275 ret = platform_device_add(zylonite_snd_ac97_device);
276 if (ret != 0) 276 if (ret != 0)
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 213963ac3c28..8a6b53ccd203 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -36,6 +36,10 @@ config SND_S3C_SOC_AC97
36 tristate 36 tristate
37 select SND_SOC_AC97_BUS 37 select SND_SOC_AC97_BUS
38 38
39config SND_S5P_SOC_SPDIF
40 tristate
41 select SND_SOC_SPDIF
42
39config SND_S3C24XX_SOC_NEO1973_WM8753 43config SND_S3C24XX_SOC_NEO1973_WM8753
40 tristate "SoC I2S Audio support for NEO1973 - WM8753" 44 tristate "SoC I2S Audio support for NEO1973 - WM8753"
41 depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01 45 depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA01
@@ -118,6 +122,14 @@ config SND_S3C24XX_SOC_SIMTEC_HERMES
118 select SND_SOC_TLV320AIC3X 122 select SND_SOC_TLV320AIC3X
119 select SND_S3C24XX_SOC_SIMTEC 123 select SND_S3C24XX_SOC_SIMTEC
120 124
125config SND_S3C24XX_SOC_RX1950_UDA1380
126 tristate "Audio support for the HP iPAQ RX1950"
127 depends on SND_S3C24XX_SOC && MACH_RX1950
128 select SND_S3C24XX_SOC_I2S
129 select SND_SOC_UDA1380
130 help
131 This driver provides audio support for HP iPAQ RX1950 PDA.
132
121config SND_SOC_SMDK_WM9713 133config SND_SOC_SMDK_WM9713
122 tristate "SoC AC97 Audio support for SMDK with WM9713" 134 tristate "SoC AC97 Audio support for SMDK with WM9713"
123 depends on SND_S3C24XX_SOC && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110) 135 depends on SND_S3C24XX_SOC && (MACH_SMDK6410 || MACH_SMDKC100 || MACH_SMDKV210 || MACH_SMDKC110)
@@ -131,3 +143,28 @@ config SND_S3C64XX_SOC_SMARTQ
131 depends on SND_S3C24XX_SOC && MACH_SMARTQ 143 depends on SND_S3C24XX_SOC && MACH_SMARTQ
132 select SND_S3C64XX_SOC_I2S 144 select SND_S3C64XX_SOC_I2S
133 select SND_SOC_WM8750 145 select SND_SOC_WM8750
146
147config SND_S5PC110_SOC_AQUILA_WM8994
148 tristate "SoC I2S Audio support for AQUILA - WM8994"
149 depends on SND_S3C24XX_SOC && MACH_AQUILA
150 select SND_S3C64XX_SOC_I2S_V4
151 select SND_SOC_WM8994
152 help
153 Say Y if you want to add support for SoC audio on aquila
154 with the WM8994.
155
156config SND_S5PV210_SOC_GONI_WM8994
157 tristate "SoC I2S Audio support for GONI - WM8994"
158 depends on SND_S3C24XX_SOC && MACH_GONI
159 select SND_S3C64XX_SOC_I2S_V4
160 select SND_SOC_WM8994
161 help
162 Say Y if you want to add support for SoC audio on goni
163 with the WM8994.
164
165config SND_SOC_SMDK_SPDIF
166 tristate "SoC S/PDIF Audio support for SMDK"
167 depends on SND_S3C24XX_SOC && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210)
168 select SND_S5P_SOC_SPDIF
169 help
170 Say Y if you want to add support for SoC S/PDIF audio on the SMDK.
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 50172c385d90..ee8f41d6df99 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -7,6 +7,7 @@ snd-soc-s3c-ac97-objs := s3c-ac97.o
7snd-soc-s3c64xx-i2s-v4-objs := s3c64xx-i2s-v4.o 7snd-soc-s3c64xx-i2s-v4-objs := s3c64xx-i2s-v4.o
8snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o 8snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
9snd-soc-s3c-pcm-objs := s3c-pcm.o 9snd-soc-s3c-pcm-objs := s3c-pcm.o
10snd-soc-samsung-spdif-objs := spdif.o
10 11
11obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o 12obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
12obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o 13obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
@@ -16,6 +17,7 @@ obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o
16obj-$(CONFIG_SND_S3C64XX_SOC_I2S_V4) += snd-soc-s3c64xx-i2s-v4.o 17obj-$(CONFIG_SND_S3C64XX_SOC_I2S_V4) += snd-soc-s3c64xx-i2s-v4.o
17obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o 18obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
18obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o 19obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o
20obj-$(CONFIG_SND_S5P_SOC_SPDIF) += snd-soc-samsung-spdif.o
19 21
20# S3C24XX Machine Support 22# S3C24XX Machine Support
21snd-soc-jive-wm8750-objs := jive_wm8750.o 23snd-soc-jive-wm8750-objs := jive_wm8750.o
@@ -27,9 +29,13 @@ snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
27snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o 29snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o
28snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o 30snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o
29snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o 31snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o
32snd-soc-rx1950-uda1380-objs := rx1950_uda1380.o
30snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o 33snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o
31snd-soc-smdk-wm9713-objs := smdk_wm9713.o 34snd-soc-smdk-wm9713-objs := smdk_wm9713.o
32snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o 35snd-soc-s3c64xx-smartq-wm8987-objs := smartq_wm8987.o
36snd-soc-aquila-wm8994-objs := aquila_wm8994.o
37snd-soc-goni-wm8994-objs := goni_wm8994.o
38snd-soc-smdk-spdif-objs := smdk_spdif.o
33 39
34obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o 40obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
35obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 41obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -40,6 +46,10 @@ obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
40obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o 46obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o
41obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o 47obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
42obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o 48obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
49obj-$(CONFIG_SND_S3C24XX_SOC_RX1950_UDA1380) += snd-soc-rx1950-uda1380.o
43obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o 50obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o
44obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o 51obj-$(CONFIG_SND_SOC_SMDK_WM9713) += snd-soc-smdk-wm9713.o
45obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o 52obj-$(CONFIG_SND_S3C64XX_SOC_SMARTQ) += snd-soc-s3c64xx-smartq-wm8987.o
53obj-$(CONFIG_SND_S5PC110_SOC_AQUILA_WM8994) += snd-soc-aquila-wm8994.o
54obj-$(CONFIG_SND_S5PV210_SOC_GONI_WM8994) += snd-soc-goni-wm8994.o
55obj-$(CONFIG_SND_SOC_SMDK_SPDIF) += snd-soc-smdk-spdif.o
diff --git a/sound/soc/s3c24xx/aquila_wm8994.c b/sound/soc/s3c24xx/aquila_wm8994.c
new file mode 100644
index 000000000000..235d1973f7d0
--- /dev/null
+++ b/sound/soc/s3c24xx/aquila_wm8994.c
@@ -0,0 +1,295 @@
1/*
2 * aquila_wm8994.c
3 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/jack.h>
21#include <asm/mach-types.h>
22#include <mach/gpio.h>
23#include <mach/regs-clock.h>
24
25#include <linux/mfd/wm8994/core.h>
26#include <linux/mfd/wm8994/registers.h>
27#include "../codecs/wm8994.h"
28#include "s3c-dma.h"
29#include "s3c64xx-i2s.h"
30
31static struct snd_soc_card aquila;
32static struct platform_device *aquila_snd_device;
33
34/* 3.5 pie jack */
35static struct snd_soc_jack jack;
36
37/* 3.5 pie jack detection DAPM pins */
38static struct snd_soc_jack_pin jack_pins[] = {
39 {
40 .pin = "Headset Mic",
41 .mask = SND_JACK_MICROPHONE,
42 }, {
43 .pin = "Headset Stereophone",
44 .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL |
45 SND_JACK_AVOUT,
46 },
47};
48
49/* 3.5 pie jack detection gpios */
50static struct snd_soc_jack_gpio jack_gpios[] = {
51 {
52 .gpio = S5PV210_GPH0(6),
53 .name = "DET_3.5",
54 .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL |
55 SND_JACK_AVOUT,
56 .debounce_time = 200,
57 },
58};
59
60static const struct snd_soc_dapm_widget aquila_dapm_widgets[] = {
61 SND_SOC_DAPM_SPK("Ext Spk", NULL),
62 SND_SOC_DAPM_SPK("Ext Rcv", NULL),
63 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
64 SND_SOC_DAPM_MIC("Headset Mic", NULL),
65 SND_SOC_DAPM_MIC("Main Mic", NULL),
66 SND_SOC_DAPM_MIC("2nd Mic", NULL),
67 SND_SOC_DAPM_LINE("Radio In", NULL),
68};
69
70static const struct snd_soc_dapm_route aquila_dapm_routes[] = {
71 {"Ext Spk", NULL, "SPKOUTLP"},
72 {"Ext Spk", NULL, "SPKOUTLN"},
73
74 {"Ext Rcv", NULL, "HPOUT2N"},
75 {"Ext Rcv", NULL, "HPOUT2P"},
76
77 {"Headset Stereophone", NULL, "HPOUT1L"},
78 {"Headset Stereophone", NULL, "HPOUT1R"},
79
80 {"IN1RN", NULL, "Headset Mic"},
81 {"IN1RP", NULL, "Headset Mic"},
82
83 {"IN1RN", NULL, "2nd Mic"},
84 {"IN1RP", NULL, "2nd Mic"},
85
86 {"IN1LN", NULL, "Main Mic"},
87 {"IN1LP", NULL, "Main Mic"},
88
89 {"IN2LN", NULL, "Radio In"},
90 {"IN2RN", NULL, "Radio In"},
91};
92
93static int aquila_wm8994_init(struct snd_soc_pcm_runtime *rtd)
94{
95 struct snd_soc_codec *codec = rtd->codec;
96 int ret;
97
98 /* add aquila specific widgets */
99 snd_soc_dapm_new_controls(codec, aquila_dapm_widgets,
100 ARRAY_SIZE(aquila_dapm_widgets));
101
102 /* set up aquila specific audio routes */
103 snd_soc_dapm_add_routes(codec, aquila_dapm_routes,
104 ARRAY_SIZE(aquila_dapm_routes));
105
106 /* set endpoints to not connected */
107 snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN");
108 snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP");
109 snd_soc_dapm_nc_pin(codec, "LINEOUT1N");
110 snd_soc_dapm_nc_pin(codec, "LINEOUT1P");
111 snd_soc_dapm_nc_pin(codec, "LINEOUT2N");
112 snd_soc_dapm_nc_pin(codec, "LINEOUT2P");
113 snd_soc_dapm_nc_pin(codec, "SPKOUTRN");
114 snd_soc_dapm_nc_pin(codec, "SPKOUTRP");
115
116 snd_soc_dapm_sync(codec);
117
118 /* Headset jack detection */
119 ret = snd_soc_jack_new(&aquila, "Headset Jack",
120 SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
121 &jack);
122 if (ret)
123 return ret;
124
125 ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
126 if (ret)
127 return ret;
128
129 ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
130 if (ret)
131 return ret;
132
133 return 0;
134}
135
136static int aquila_hifi_hw_params(struct snd_pcm_substream *substream,
137 struct snd_pcm_hw_params *params)
138{
139 struct snd_soc_pcm_runtime *rtd = substream->private_data;
140 struct snd_soc_dai *codec_dai = rtd->codec_dai;
141 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
142 unsigned int pll_out = 24000000;
143 int ret = 0;
144
145 /* set the cpu DAI configuration */
146 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
147 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
148 if (ret < 0)
149 return ret;
150
151 /* set the cpu system clock */
152 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
153 0, SND_SOC_CLOCK_IN);
154 if (ret < 0)
155 return ret;
156
157 /* set codec DAI configuration */
158 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
159 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
160 if (ret < 0)
161 return ret;
162
163 /* set the codec FLL */
164 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
165 params_rate(params) * 256);
166 if (ret < 0)
167 return ret;
168
169 /* set the codec system clock */
170 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
171 params_rate(params) * 256, SND_SOC_CLOCK_IN);
172 if (ret < 0)
173 return ret;
174
175 return 0;
176}
177
178static struct snd_soc_ops aquila_hifi_ops = {
179 .hw_params = aquila_hifi_hw_params,
180};
181
182static int aquila_voice_hw_params(struct snd_pcm_substream *substream,
183 struct snd_pcm_hw_params *params)
184{
185 struct snd_soc_pcm_runtime *rtd = substream->private_data;
186 struct snd_soc_dai *codec_dai = rtd->codec_dai;
187 unsigned int pll_out = 24000000;
188 int ret = 0;
189
190 if (params_rate(params) != 8000)
191 return -EINVAL;
192
193 /* set codec DAI configuration */
194 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
195 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
196 if (ret < 0)
197 return ret;
198
199 /* set the codec FLL */
200 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
201 params_rate(params) * 256);
202 if (ret < 0)
203 return ret;
204
205 /* set the codec system clock */
206 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
207 params_rate(params) * 256, SND_SOC_CLOCK_IN);
208 if (ret < 0)
209 return ret;
210
211 return 0;
212}
213
214static struct snd_soc_dai_driver voice_dai = {
215 .name = "aquila-voice-dai",
216 .playback = {
217 .channels_min = 1,
218 .channels_max = 2,
219 .rates = SNDRV_PCM_RATE_8000,
220 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
221 .capture = {
222 .channels_min = 1,
223 .channels_max = 2,
224 .rates = SNDRV_PCM_RATE_8000,
225 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
226};
227
228static struct snd_soc_ops aquila_voice_ops = {
229 .hw_params = aquila_voice_hw_params,
230};
231
232static struct snd_soc_dai_link aquila_dai[] = {
233{
234 .name = "WM8994",
235 .stream_name = "WM8994 HiFi",
236 .cpu_dai_name = "s3c64xx-i2s-v4",
237 .codec_dai_name = "wm8994-hifi",
238 .platform_name = "s3c24xx-pcm-audio",
239 .codec_name = "wm8994-codec.0-0x1a",
240 .init = aquila_wm8994_init,
241 .ops = &aquila_hifi_ops,
242}, {
243 .name = "WM8994 Voice",
244 .stream_name = "Voice",
245 .cpu_dai_name = "aquila-voice-dai",
246 .codec_dai_name = "wm8994-voice",
247 .platform_name = "s3c24xx-pcm-audio",
248 .codec_name = "wm8994-codec.0-0x1a",
249 .ops = &aquila_voice_ops,
250},
251};
252
253static struct snd_soc_card aquila = {
254 .name = "aquila",
255 .dai_link = aquila_dai,
256 .num_links = ARRAY_SIZE(aquila_dai),
257};
258
259static int __init aquila_init(void)
260{
261 int ret;
262
263 if (!machine_is_aquila())
264 return -ENODEV;
265
266 aquila_snd_device = platform_device_alloc("soc-audio", -1);
267 if (!aquila_snd_device)
268 return -ENOMEM;
269
270 /* register voice DAI here */
271 ret = snd_soc_register_dai(&aquila_snd_device->dev, &voice_dai);
272 if (ret)
273 return ret;
274
275 platform_set_drvdata(aquila_snd_device, &aquila);
276 ret = platform_device_add(aquila_snd_device);
277
278 if (ret)
279 platform_device_put(aquila_snd_device);
280
281 return ret;
282}
283
284static void __exit aquila_exit(void)
285{
286 platform_device_unregister(aquila_snd_device);
287}
288
289module_init(aquila_init);
290module_exit(aquila_exit);
291
292/* Module information */
293MODULE_DESCRIPTION("ALSA SoC WM8994 Aquila(S5PC110)");
294MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
295MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/goni_wm8994.c b/sound/soc/s3c24xx/goni_wm8994.c
new file mode 100644
index 000000000000..694f702cc8e2
--- /dev/null
+++ b/sound/soc/s3c24xx/goni_wm8994.c
@@ -0,0 +1,298 @@
1/*
2 * goni_wm8994.c
3 *
4 * Copyright (C) 2010 Samsung Electronics Co.Ltd
5 * Author: Chanwoo Choi <cw00.choi@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/moduleparam.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/jack.h>
21#include <asm/mach-types.h>
22#include <mach/gpio.h>
23#include <mach/regs-clock.h>
24
25#include <linux/mfd/wm8994/core.h>
26#include <linux/mfd/wm8994/registers.h>
27#include "../codecs/wm8994.h"
28#include "s3c-dma.h"
29#include "s3c64xx-i2s.h"
30
31static struct snd_soc_card goni;
32static struct platform_device *goni_snd_device;
33
34/* 3.5 pie jack */
35static struct snd_soc_jack jack;
36
37/* 3.5 pie jack detection DAPM pins */
38static struct snd_soc_jack_pin jack_pins[] = {
39 {
40 .pin = "Headset Mic",
41 .mask = SND_JACK_MICROPHONE,
42 }, {
43 .pin = "Headset Stereophone",
44 .mask = SND_JACK_HEADPHONE | SND_JACK_MECHANICAL |
45 SND_JACK_AVOUT,
46 },
47};
48
49/* 3.5 pie jack detection gpios */
50static struct snd_soc_jack_gpio jack_gpios[] = {
51 {
52 .gpio = S5PV210_GPH0(6),
53 .name = "DET_3.5",
54 .report = SND_JACK_HEADSET | SND_JACK_MECHANICAL |
55 SND_JACK_AVOUT,
56 .debounce_time = 200,
57 },
58};
59
60static const struct snd_soc_dapm_widget goni_dapm_widgets[] = {
61 SND_SOC_DAPM_SPK("Ext Left Spk", NULL),
62 SND_SOC_DAPM_SPK("Ext Right Spk", NULL),
63 SND_SOC_DAPM_SPK("Ext Rcv", NULL),
64 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
65 SND_SOC_DAPM_MIC("Headset Mic", NULL),
66 SND_SOC_DAPM_MIC("Main Mic", NULL),
67 SND_SOC_DAPM_MIC("2nd Mic", NULL),
68 SND_SOC_DAPM_LINE("Radio In", NULL),
69};
70
71static const struct snd_soc_dapm_route goni_dapm_routes[] = {
72 {"Ext Left Spk", NULL, "SPKOUTLP"},
73 {"Ext Left Spk", NULL, "SPKOUTLN"},
74
75 {"Ext Right Spk", NULL, "SPKOUTRP"},
76 {"Ext Right Spk", NULL, "SPKOUTRN"},
77
78 {"Ext Rcv", NULL, "HPOUT2N"},
79 {"Ext Rcv", NULL, "HPOUT2P"},
80
81 {"Headset Stereophone", NULL, "HPOUT1L"},
82 {"Headset Stereophone", NULL, "HPOUT1R"},
83
84 {"IN1RN", NULL, "Headset Mic"},
85 {"IN1RP", NULL, "Headset Mic"},
86
87 {"IN1RN", NULL, "2nd Mic"},
88 {"IN1RP", NULL, "2nd Mic"},
89
90 {"IN1LN", NULL, "Main Mic"},
91 {"IN1LP", NULL, "Main Mic"},
92
93 {"IN2LN", NULL, "Radio In"},
94 {"IN2RN", NULL, "Radio In"},
95};
96
97static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
98{
99 struct snd_soc_codec *codec = rtd->codec;
100 int ret;
101
102 /* add goni specific widgets */
103 snd_soc_dapm_new_controls(codec, goni_dapm_widgets,
104 ARRAY_SIZE(goni_dapm_widgets));
105
106 /* set up goni specific audio routes */
107 snd_soc_dapm_add_routes(codec, goni_dapm_routes,
108 ARRAY_SIZE(goni_dapm_routes));
109
110 /* set endpoints to not connected */
111 snd_soc_dapm_nc_pin(codec, "IN2LP:VXRN");
112 snd_soc_dapm_nc_pin(codec, "IN2RP:VXRP");
113 snd_soc_dapm_nc_pin(codec, "LINEOUT1N");
114 snd_soc_dapm_nc_pin(codec, "LINEOUT1P");
115 snd_soc_dapm_nc_pin(codec, "LINEOUT2N");
116 snd_soc_dapm_nc_pin(codec, "LINEOUT2P");
117
118 snd_soc_dapm_sync(codec);
119
120 /* Headset jack detection */
121 ret = snd_soc_jack_new(&goni, "Headset Jack",
122 SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
123 &jack);
124 if (ret)
125 return ret;
126
127 ret = snd_soc_jack_add_pins(&jack, ARRAY_SIZE(jack_pins), jack_pins);
128 if (ret)
129 return ret;
130
131 ret = snd_soc_jack_add_gpios(&jack, ARRAY_SIZE(jack_gpios), jack_gpios);
132 if (ret)
133 return ret;
134
135 return 0;
136}
137
138static int goni_hifi_hw_params(struct snd_pcm_substream *substream,
139 struct snd_pcm_hw_params *params)
140{
141 struct snd_soc_pcm_runtime *rtd = substream->private_data;
142 struct snd_soc_dai *codec_dai = rtd->codec_dai;
143 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
144 unsigned int pll_out = 24000000;
145 int ret = 0;
146
147 /* set the cpu DAI configuration */
148 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
149 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
150 if (ret < 0)
151 return ret;
152
153 /* set the cpu system clock */
154 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
155 0, SND_SOC_CLOCK_IN);
156 if (ret < 0)
157 return ret;
158
159 /* set codec DAI configuration */
160 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
161 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
162 if (ret < 0)
163 return ret;
164
165 /* set the codec FLL */
166 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, 0, pll_out,
167 params_rate(params) * 256);
168 if (ret < 0)
169 return ret;
170
171 /* set the codec system clock */
172 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL1,
173 params_rate(params) * 256, SND_SOC_CLOCK_IN);
174 if (ret < 0)
175 return ret;
176
177 return 0;
178}
179
180static struct snd_soc_ops goni_hifi_ops = {
181 .hw_params = goni_hifi_hw_params,
182};
183
184static int goni_voice_hw_params(struct snd_pcm_substream *substream,
185 struct snd_pcm_hw_params *params)
186{
187 struct snd_soc_pcm_runtime *rtd = substream->private_data;
188 struct snd_soc_dai *codec_dai = rtd->codec_dai;
189 unsigned int pll_out = 24000000;
190 int ret = 0;
191
192 if (params_rate(params) != 8000)
193 return -EINVAL;
194
195 /* set codec DAI configuration */
196 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_LEFT_J |
197 SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
198 if (ret < 0)
199 return ret;
200
201 /* set the codec FLL */
202 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL2, 0, pll_out,
203 params_rate(params) * 256);
204 if (ret < 0)
205 return ret;
206
207 /* set the codec system clock */
208 ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_FLL2,
209 params_rate(params) * 256, SND_SOC_CLOCK_IN);
210 if (ret < 0)
211 return ret;
212
213 return 0;
214}
215
216static struct snd_soc_dai_driver voice_dai = {
217 .name = "goni-voice-dai",
218 .id = 0,
219 .playback = {
220 .channels_min = 1,
221 .channels_max = 2,
222 .rates = SNDRV_PCM_RATE_8000,
223 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
224 .capture = {
225 .channels_min = 1,
226 .channels_max = 2,
227 .rates = SNDRV_PCM_RATE_8000,
228 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
229};
230
231static struct snd_soc_ops goni_voice_ops = {
232 .hw_params = goni_voice_hw_params,
233};
234
235static struct snd_soc_dai_link goni_dai[] = {
236{
237 .name = "WM8994",
238 .stream_name = "WM8994 HiFi",
239 .cpu_dai_name = "s3c64xx-i2s-v4",
240 .codec_dai_name = "wm8994-hifi",
241 .platform_name = "s3c24xx-pcm-audio",
242 .codec_name = "wm8994-codec.0-0x1a",
243 .init = goni_wm8994_init,
244 .ops = &goni_hifi_ops,
245}, {
246 .name = "WM8994 Voice",
247 .stream_name = "Voice",
248 .cpu_dai_name = "goni-voice-dai",
249 .codec_dai_name = "wm8994-voice",
250 .platform_name = "s3c24xx-pcm-audio",
251 .codec_name = "wm8994-codec.0-0x1a",
252 .ops = &goni_voice_ops,
253},
254};
255
256static struct snd_soc_card goni = {
257 .name = "goni",
258 .dai_link = goni_dai,
259 .num_links = ARRAY_SIZE(goni_dai),
260};
261
262static int __init goni_init(void)
263{
264 int ret;
265
266 if (!machine_is_goni())
267 return -ENODEV;
268
269 goni_snd_device = platform_device_alloc("soc-audio", -1);
270 if (!goni_snd_device)
271 return -ENOMEM;
272
273 /* register voice DAI here */
274 ret = snd_soc_register_dai(&goni_snd_device->dev, &voice_dai);
275 if (ret)
276 return ret;
277
278 platform_set_drvdata(goni_snd_device, &goni);
279 ret = platform_device_add(goni_snd_device);
280
281 if (ret)
282 platform_device_put(goni_snd_device);
283
284 return ret;
285}
286
287static void __exit goni_exit(void)
288{
289 platform_device_unregister(goni_snd_device);
290}
291
292module_init(goni_init);
293module_exit(goni_exit);
294
295/* Module information */
296MODULE_DESCRIPTION("ALSA SoC WM8994 GONI(S5PV210)");
297MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
298MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c
index 8c108b121c10..49605cd83947 100644
--- a/sound/soc/s3c24xx/jive_wm8750.c
+++ b/sound/soc/s3c24xx/jive_wm8750.c
@@ -49,8 +49,8 @@ static int jive_hw_params(struct snd_pcm_substream *substream,
49 struct snd_pcm_hw_params *params) 49 struct snd_pcm_hw_params *params)
50{ 50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data; 51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
52 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 52 struct snd_soc_dai *codec_dai = rtd->codec_dai;
53 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 53 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
54 struct s3c_i2sv2_rate_calc div; 54 struct s3c_i2sv2_rate_calc div;
55 unsigned int clk = 0; 55 unsigned int clk = 0;
56 int ret = 0; 56 int ret = 0;
@@ -108,8 +108,9 @@ static struct snd_soc_ops jive_ops = {
108 .hw_params = jive_hw_params, 108 .hw_params = jive_hw_params,
109}; 109};
110 110
111static int jive_wm8750_init(struct snd_soc_codec *codec) 111static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
112{ 112{
113 struct snd_soc_codec *codec = rtd->codec;
113 int err; 114 int err;
114 115
115 /* These endpoints are not being used. */ 116 /* These endpoints are not being used. */
@@ -138,8 +139,10 @@ static int jive_wm8750_init(struct snd_soc_codec *codec)
138static struct snd_soc_dai_link jive_dai = { 139static struct snd_soc_dai_link jive_dai = {
139 .name = "wm8750", 140 .name = "wm8750",
140 .stream_name = "WM8750", 141 .stream_name = "WM8750",
141 .cpu_dai = &s3c2412_i2s_dai, 142 .cpu_dai_name = "s3c2412-i2s",
142 .codec_dai = &wm8750_dai, 143 .codec_dai_name = "wm8750-hifi",
144 .platform_name = "s3c24xx-pcm-audio",
145 .codec_name = "wm8750-codec.0-0x1a",
143 .init = jive_wm8750_init, 146 .init = jive_wm8750_init,
144 .ops = &jive_ops, 147 .ops = &jive_ops,
145}; 148};
@@ -147,17 +150,10 @@ static struct snd_soc_dai_link jive_dai = {
147/* jive audio machine driver */ 150/* jive audio machine driver */
148static struct snd_soc_card snd_soc_machine_jive = { 151static struct snd_soc_card snd_soc_machine_jive = {
149 .name = "Jive", 152 .name = "Jive",
150 .platform = &s3c24xx_soc_platform,
151 .dai_link = &jive_dai, 153 .dai_link = &jive_dai,
152 .num_links = 1, 154 .num_links = 1,
153}; 155};
154 156
155/* jive audio subsystem */
156static struct snd_soc_device jive_snd_devdata = {
157 .card = &snd_soc_machine_jive,
158 .codec_dev = &soc_codec_dev_wm8750,
159};
160
161static struct platform_device *jive_snd_device; 157static struct platform_device *jive_snd_device;
162 158
163static int __init jive_init(void) 159static int __init jive_init(void)
@@ -173,8 +169,7 @@ static int __init jive_init(void)
173 if (!jive_snd_device) 169 if (!jive_snd_device)
174 return -ENOMEM; 170 return -ENOMEM;
175 171
176 platform_set_drvdata(jive_snd_device, &jive_snd_devdata); 172 platform_set_drvdata(jive_snd_device, &snd_soc_machine_jive);
177 jive_snd_devdata.dev = &jive_snd_device->dev;
178 ret = platform_device_add(jive_snd_device); 173 ret = platform_device_add(jive_snd_device);
179 174
180 if (ret) 175 if (ret)
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c
index ffa954fe6931..abe64abe8c84 100644
--- a/sound/soc/s3c24xx/ln2440sbc_alc650.c
+++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c
@@ -23,7 +23,6 @@
23#include <sound/soc.h> 23#include <sound/soc.h>
24#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
25 25
26#include "../codecs/ac97.h"
27#include "s3c-dma.h" 26#include "s3c-dma.h"
28#include "s3c-ac97.h" 27#include "s3c-ac97.h"
29 28
@@ -33,23 +32,19 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {
33{ 32{
34 .name = "AC97", 33 .name = "AC97",
35 .stream_name = "AC97 HiFi", 34 .stream_name = "AC97 HiFi",
36 .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], 35 .cpu_dai_name = "s3c-ac97",
37 .codec_dai = &ac97_dai, 36 .codec_dai_name = "ac97-hifi",
37 .codec_name = "ac97-codec",
38 .platform_name = "s3c24xx-pcm-audio",
38}, 39},
39}; 40};
40 41
41static struct snd_soc_card ln2440sbc = { 42static struct snd_soc_card ln2440sbc = {
42 .name = "LN2440SBC", 43 .name = "LN2440SBC",
43 .platform = &s3c24xx_soc_platform,
44 .dai_link = ln2440sbc_dai, 44 .dai_link = ln2440sbc_dai,
45 .num_links = ARRAY_SIZE(ln2440sbc_dai), 45 .num_links = ARRAY_SIZE(ln2440sbc_dai),
46}; 46};
47 47
48static struct snd_soc_device ln2440sbc_snd_ac97_devdata = {
49 .card = &ln2440sbc,
50 .codec_dev = &soc_codec_dev_ac97,
51};
52
53static struct platform_device *ln2440sbc_snd_ac97_device; 48static struct platform_device *ln2440sbc_snd_ac97_device;
54 49
55static int __init ln2440sbc_init(void) 50static int __init ln2440sbc_init(void)
@@ -60,9 +55,7 @@ static int __init ln2440sbc_init(void)
60 if (!ln2440sbc_snd_ac97_device) 55 if (!ln2440sbc_snd_ac97_device)
61 return -ENOMEM; 56 return -ENOMEM;
62 57
63 platform_set_drvdata(ln2440sbc_snd_ac97_device, 58 platform_set_drvdata(ln2440sbc_snd_ac97_device, &ln2440sbc);
64 &ln2440sbc_snd_ac97_devdata);
65 ln2440sbc_snd_ac97_devdata.dev = &ln2440sbc_snd_ac97_device->dev;
66 ret = platform_device_add(ln2440sbc_snd_ac97_device); 59 ret = platform_device_add(ln2440sbc_snd_ac97_device);
67 60
68 if (ret) 61 if (ret)
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
index 4719558289d4..e97bdf150a03 100644
--- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
@@ -41,8 +41,8 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params) 41 struct snd_pcm_hw_params *params)
42{ 42{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data; 43 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 44 struct snd_soc_dai *codec_dai = rtd->codec_dai;
45 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 45 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
46 unsigned int pll_out = 0, bclk = 0; 46 unsigned int pll_out = 0, bclk = 0;
47 int ret = 0; 47 int ret = 0;
48 unsigned long iis_clkrate; 48 unsigned long iis_clkrate;
@@ -130,7 +130,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
130static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) 130static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
131{ 131{
132 struct snd_soc_pcm_runtime *rtd = substream->private_data; 132 struct snd_soc_pcm_runtime *rtd = substream->private_data;
133 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 133 struct snd_soc_dai *codec_dai = rtd->codec_dai;
134 134
135 /* disable the PLL */ 135 /* disable the PLL */
136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0); 136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
@@ -149,7 +149,7 @@ static int neo1973_gta02_voice_hw_params(
149 struct snd_pcm_hw_params *params) 149 struct snd_pcm_hw_params *params)
150{ 150{
151 struct snd_soc_pcm_runtime *rtd = substream->private_data; 151 struct snd_soc_pcm_runtime *rtd = substream->private_data;
152 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 152 struct snd_soc_dai *codec_dai = rtd->codec_dai;
153 unsigned int pcmdiv = 0; 153 unsigned int pcmdiv = 0;
154 int ret = 0; 154 int ret = 0;
155 unsigned long iis_clkrate; 155 unsigned long iis_clkrate;
@@ -194,7 +194,7 @@ static int neo1973_gta02_voice_hw_params(
194static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) 194static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
195{ 195{
196 struct snd_soc_pcm_runtime *rtd = substream->private_data; 196 struct snd_soc_pcm_runtime *rtd = substream->private_data;
197 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 197 struct snd_soc_dai *codec_dai = rtd->codec_dai;
198 198
199 /* disable the PLL */ 199 /* disable the PLL */
200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0); 200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
@@ -262,7 +262,7 @@ static int lm4853_event(struct snd_soc_dapm_widget *w,
262 struct snd_kcontrol *k, 262 struct snd_kcontrol *k,
263 int event) 263 int event)
264{ 264{
265 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); 265 gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(event));
266 266
267 return 0; 267 return 0;
268} 268}
@@ -330,8 +330,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
330 * This is an example machine initialisation for a wm8753 connected to a 330 * This is an example machine initialisation for a wm8753 connected to a
331 * neo1973 GTA02. 331 * neo1973 GTA02.
332 */ 332 */
333static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) 333static int neo1973_gta02_wm8753_init(struct snd_soc_pcm_runtime *rtd)
334{ 334{
335 struct snd_soc_codec *codec = rtd->codec;
335 int err; 336 int err;
336 337
337 /* set up NC codec pins */ 338 /* set up NC codec pins */
@@ -378,9 +379,8 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
378/* 379/*
379 * BT Codec DAI 380 * BT Codec DAI
380 */ 381 */
381static struct snd_soc_dai bt_dai = { 382static struct snd_soc_dai_driver bt_dai = {
382 .name = "Bluetooth", 383 .name = "bluetooth-dai",
383 .id = 0,
384 .playback = { 384 .playback = {
385 .channels_min = 1, 385 .channels_min = 1,
386 .channels_max = 1, 386 .channels_max = 1,
@@ -397,32 +397,30 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = {
397{ /* Hifi Playback - for similatious use with voice below */ 397{ /* Hifi Playback - for similatious use with voice below */
398 .name = "WM8753", 398 .name = "WM8753",
399 .stream_name = "WM8753 HiFi", 399 .stream_name = "WM8753 HiFi",
400 .cpu_dai = &s3c24xx_i2s_dai, 400 .cpu_dai_name = "s3c24xx-i2s",
401 .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], 401 .codec_dai_name = "wm8753-hifi",
402 .init = neo1973_gta02_wm8753_init, 402 .init = neo1973_gta02_wm8753_init,
403 .platform_name = "s3c24xx-pcm-audio",
404 .codec_name = "wm8753-codec.0-0x1a",
403 .ops = &neo1973_gta02_hifi_ops, 405 .ops = &neo1973_gta02_hifi_ops,
404}, 406},
405{ /* Voice via BT */ 407{ /* Voice via BT */
406 .name = "Bluetooth", 408 .name = "Bluetooth",
407 .stream_name = "Voice", 409 .stream_name = "Voice",
408 .cpu_dai = &bt_dai, 410 .cpu_dai_name = "bluetooth-dai",
409 .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], 411 .codec_dai_name = "wm8753-voice",
410 .ops = &neo1973_gta02_voice_ops, 412 .ops = &neo1973_gta02_voice_ops,
413 .codec_name = "wm8753-codec.0-0x1a",
414 .platform_name = "s3c24xx-pcm-audio",
411}, 415},
412}; 416};
413 417
414static struct snd_soc_card neo1973_gta02 = { 418static struct snd_soc_card neo1973_gta02 = {
415 .name = "neo1973-gta02", 419 .name = "neo1973-gta02",
416 .platform = &s3c24xx_soc_platform,
417 .dai_link = neo1973_gta02_dai, 420 .dai_link = neo1973_gta02_dai,
418 .num_links = ARRAY_SIZE(neo1973_gta02_dai), 421 .num_links = ARRAY_SIZE(neo1973_gta02_dai),
419}; 422};
420 423
421static struct snd_soc_device neo1973_gta02_snd_devdata = {
422 .card = &neo1973_gta02,
423 .codec_dev = &soc_codec_dev_wm8753,
424};
425
426static struct platform_device *neo1973_gta02_snd_device; 424static struct platform_device *neo1973_gta02_snd_device;
427 425
428static int __init neo1973_gta02_init(void) 426static int __init neo1973_gta02_init(void)
@@ -435,18 +433,18 @@ static int __init neo1973_gta02_init(void)
435 return -ENODEV; 433 return -ENODEV;
436 } 434 }
437 435
438 /* register bluetooth DAI here */
439 ret = snd_soc_register_dai(&bt_dai);
440 if (ret)
441 return ret;
442
443 neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); 436 neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
444 if (!neo1973_gta02_snd_device) 437 if (!neo1973_gta02_snd_device)
445 return -ENOMEM; 438 return -ENOMEM;
446 439
447 platform_set_drvdata(neo1973_gta02_snd_device, 440 /* register bluetooth DAI here */
448 &neo1973_gta02_snd_devdata); 441 ret = snd_soc_register_dai(&neo1973_gta02_snd_device->dev, -1, &bt_dai);
449 neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; 442 if (ret) {
443 platform_device_put(neo1973_gta02_snd_device);
444 return ret;
445 }
446
447 platform_set_drvdata(neo1973_gta02_snd_device, &neo1973_gta02);
450 ret = platform_device_add(neo1973_gta02_snd_device); 448 ret = platform_device_add(neo1973_gta02_snd_device);
451 449
452 if (ret) { 450 if (ret) {
@@ -461,7 +459,7 @@ static int __init neo1973_gta02_init(void)
461 goto err_unregister_device; 459 goto err_unregister_device;
462 } 460 }
463 461
464 ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); 462 ret = gpio_direction_output(GTA02_GPIO_HP_IN, 1);
465 if (ret) { 463 if (ret) {
466 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); 464 pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN);
467 goto err_free_gpio_hp_in; 465 goto err_free_gpio_hp_in;
@@ -493,7 +491,7 @@ module_init(neo1973_gta02_init);
493 491
494static void __exit neo1973_gta02_exit(void) 492static void __exit neo1973_gta02_exit(void)
495{ 493{
496 snd_soc_unregister_dai(&bt_dai); 494 snd_soc_unregister_dai(&neo1973_gta02_snd_device->dev, -1);
497 platform_device_unregister(neo1973_gta02_snd_device); 495 platform_device_unregister(neo1973_gta02_snd_device);
498 gpio_free(GTA02_GPIO_HP_IN); 496 gpio_free(GTA02_GPIO_HP_IN);
499 gpio_free(GTA02_GPIO_AMP_SHUT); 497 gpio_free(GTA02_GPIO_AMP_SHUT);
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 4ac620988e7c..f4f2ee731f01 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -57,8 +57,8 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
57 struct snd_pcm_hw_params *params) 57 struct snd_pcm_hw_params *params)
58{ 58{
59 struct snd_soc_pcm_runtime *rtd = substream->private_data; 59 struct snd_soc_pcm_runtime *rtd = substream->private_data;
60 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 60 struct snd_soc_dai *codec_dai = rtd->codec_dai;
61 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 61 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
62 unsigned int pll_out = 0, bclk = 0; 62 unsigned int pll_out = 0, bclk = 0;
63 int ret = 0; 63 int ret = 0;
64 unsigned long iis_clkrate; 64 unsigned long iis_clkrate;
@@ -147,7 +147,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
147static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) 147static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
148{ 148{
149 struct snd_soc_pcm_runtime *rtd = substream->private_data; 149 struct snd_soc_pcm_runtime *rtd = substream->private_data;
150 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 150 struct snd_soc_dai *codec_dai = rtd->codec_dai;
151 151
152 pr_debug("Entered %s\n", __func__); 152 pr_debug("Entered %s\n", __func__);
153 153
@@ -167,7 +167,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
167 struct snd_pcm_hw_params *params) 167 struct snd_pcm_hw_params *params)
168{ 168{
169 struct snd_soc_pcm_runtime *rtd = substream->private_data; 169 struct snd_soc_pcm_runtime *rtd = substream->private_data;
170 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 170 struct snd_soc_dai *codec_dai = rtd->codec_dai;
171 unsigned int pcmdiv = 0; 171 unsigned int pcmdiv = 0;
172 int ret = 0; 172 int ret = 0;
173 unsigned long iis_clkrate; 173 unsigned long iis_clkrate;
@@ -213,7 +213,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
213static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) 213static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
214{ 214{
215 struct snd_soc_pcm_runtime *rtd = substream->private_data; 215 struct snd_soc_pcm_runtime *rtd = substream->private_data;
216 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 216 struct snd_soc_dai *codec_dai = rtd->codec_dai;
217 217
218 pr_debug("Entered %s\n", __func__); 218 pr_debug("Entered %s\n", __func__);
219 219
@@ -499,8 +499,9 @@ static const struct snd_kcontrol_new wm8753_neo1973_controls[] = {
499 * neo1973 II. It is missing logic to detect hp/mic insertions and logic 499 * neo1973 II. It is missing logic to detect hp/mic insertions and logic
500 * to re-route the audio in such an event. 500 * to re-route the audio in such an event.
501 */ 501 */
502static int neo1973_wm8753_init(struct snd_soc_codec *codec) 502static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
503{ 503{
504 struct snd_soc_codec *codec = rtd->codec;
504 int err; 505 int err;
505 506
506 pr_debug("Entered %s\n", __func__); 507 pr_debug("Entered %s\n", __func__);
@@ -538,8 +539,7 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
538 * BT Codec DAI 539 * BT Codec DAI
539 */ 540 */
540static struct snd_soc_dai bt_dai = { 541static struct snd_soc_dai bt_dai = {
541 .name = "Bluetooth", 542 .name = "bluetooth-dai",
542 .id = 0,
543 .playback = { 543 .playback = {
544 .channels_min = 1, 544 .channels_min = 1,
545 .channels_max = 1, 545 .channels_max = 1,
@@ -556,32 +556,30 @@ static struct snd_soc_dai_link neo1973_dai[] = {
556{ /* Hifi Playback - for similatious use with voice below */ 556{ /* Hifi Playback - for similatious use with voice below */
557 .name = "WM8753", 557 .name = "WM8753",
558 .stream_name = "WM8753 HiFi", 558 .stream_name = "WM8753 HiFi",
559 .cpu_dai = &s3c24xx_i2s_dai, 559 .platform_name = "s3c24xx-pcm-audio",
560 .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], 560 .cpu_dai_name = "s3c24xx-i2s",
561 .codec_dai_name = "wm8753-hifi",
562 .codec_name = "wm8753-codec.0-0x1a",
561 .init = neo1973_wm8753_init, 563 .init = neo1973_wm8753_init,
562 .ops = &neo1973_hifi_ops, 564 .ops = &neo1973_hifi_ops,
563}, 565},
564{ /* Voice via BT */ 566{ /* Voice via BT */
565 .name = "Bluetooth", 567 .name = "Bluetooth",
566 .stream_name = "Voice", 568 .stream_name = "Voice",
567 .cpu_dai = &bt_dai, 569 .platform_name = "s3c24xx-pcm-audio",
568 .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], 570 .cpu_dai_name = "bluetooth-dai",
571 .codec_dai_name = "wm8753-voice",
572 .codec_name = "wm8753-codec.0-0x1a",
569 .ops = &neo1973_voice_ops, 573 .ops = &neo1973_voice_ops,
570}, 574},
571}; 575};
572 576
573static struct snd_soc_card neo1973 = { 577static struct snd_soc_card neo1973 = {
574 .name = "neo1973", 578 .name = "neo1973",
575 .platform = &s3c24xx_soc_platform,
576 .dai_link = neo1973_dai, 579 .dai_link = neo1973_dai,
577 .num_links = ARRAY_SIZE(neo1973_dai), 580 .num_links = ARRAY_SIZE(neo1973_dai),
578}; 581};
579 582
580static struct snd_soc_device neo1973_snd_devdata = {
581 .card = &neo1973,
582 .codec_dev = &soc_codec_dev_wm8753,
583};
584
585static int lm4857_i2c_probe(struct i2c_client *client, 583static int lm4857_i2c_probe(struct i2c_client *client,
586 const struct i2c_device_id *id) 584 const struct i2c_device_id *id)
587{ 585{
@@ -673,8 +671,7 @@ static int __init neo1973_init(void)
673 if (!neo1973_snd_device) 671 if (!neo1973_snd_device)
674 return -ENOMEM; 672 return -ENOMEM;
675 673
676 platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata); 674 platform_set_drvdata(neo1973_snd_device, &neo1973);
677 neo1973_snd_devdata.dev = &neo1973_snd_device->dev;
678 ret = platform_device_add(neo1973_snd_device); 675 ret = platform_device_add(neo1973_snd_device);
679 676
680 if (ret) { 677 if (ret) {
diff --git a/sound/soc/s3c24xx/rx1950_uda1380.c b/sound/soc/s3c24xx/rx1950_uda1380.c
new file mode 100644
index 000000000000..ffd5cf2fb0a9
--- /dev/null
+++ b/sound/soc/s3c24xx/rx1950_uda1380.c
@@ -0,0 +1,333 @@
1/*
2 * rx1950.c -- ALSA Soc Audio Layer
3 *
4 * Copyright (c) 2010 Vasily Khoruzhick <anarsoul@gmail.com>
5 *
6 * Based on smdk2440.c and magician.c
7 *
8 * Authors: Graeme Gregory graeme.gregory@wolfsonmicro.com
9 * Philipp Zabel <philipp.zabel@gmail.com>
10 * Denis Grigoriev <dgreenday@gmail.com>
11 * Vasily Khoruzhick <anarsoul@gmail.com>
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/platform_device.h>
23#include <linux/i2c.h>
24#include <linux/gpio.h>
25#include <linux/clk.h>
26
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29#include <sound/uda1380.h>
30#include <sound/jack.h>
31
32#include <plat/regs-iis.h>
33
34#include <mach/regs-clock.h>
35
36#include <asm/mach-types.h>
37
38#include "s3c-dma.h"
39#include "s3c24xx-i2s.h"
40#include "../codecs/uda1380.h"
41
42static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd);
43static int rx1950_startup(struct snd_pcm_substream *substream);
44static int rx1950_hw_params(struct snd_pcm_substream *substream,
45 struct snd_pcm_hw_params *params);
46static int rx1950_spk_power(struct snd_soc_dapm_widget *w,
47 struct snd_kcontrol *kcontrol, int event);
48
49static unsigned int rates[] = {
50 16000,
51 44100,
52 48000,
53 88200,
54};
55
56static struct snd_pcm_hw_constraint_list hw_rates = {
57 .count = ARRAY_SIZE(rates),
58 .list = rates,
59 .mask = 0,
60};
61
62static struct snd_soc_jack hp_jack;
63
64static struct snd_soc_jack_pin hp_jack_pins[] = {
65 {
66 .pin = "Headphone Jack",
67 .mask = SND_JACK_HEADPHONE,
68 },
69 {
70 .pin = "Speaker",
71 .mask = SND_JACK_HEADPHONE,
72 .invert = 1,
73 },
74};
75
76static struct snd_soc_jack_gpio hp_jack_gpios[] = {
77 [0] = {
78 .gpio = S3C2410_GPG(12),
79 .name = "hp-gpio",
80 .report = SND_JACK_HEADPHONE,
81 .invert = 1,
82 .debounce_time = 200,
83 },
84};
85
86static struct snd_soc_ops rx1950_ops = {
87 .startup = rx1950_startup,
88 .hw_params = rx1950_hw_params,
89};
90
91/* s3c24xx digital audio interface glue - connects codec <--> CPU */
92static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
93 {
94 .name = "uda1380",
95 .stream_name = "UDA1380 Duplex",
96 .cpu_dai_name = "s3c24xx-iis",
97 .codec_dai_name = "uda1380-hifi",
98 .init = rx1950_uda1380_init,
99 .platform_name = "s3c24xx-pcm-audio",
100 .codec_name = "uda1380-codec.0-001a",
101 .ops = &rx1950_ops,
102 },
103};
104
105static struct snd_soc_card rx1950_asoc = {
106 .name = "rx1950",
107 .dai_link = rx1950_uda1380_dai,
108 .num_links = ARRAY_SIZE(rx1950_uda1380_dai),
109};
110
111/* rx1950 machine dapm widgets */
112static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
113 SND_SOC_DAPM_HP("Headphone Jack", NULL),
114 SND_SOC_DAPM_MIC("Mic Jack", NULL),
115 SND_SOC_DAPM_SPK("Speaker", rx1950_spk_power),
116};
117
118/* rx1950 machine audio_map */
119static const struct snd_soc_dapm_route audio_map[] = {
120 /* headphone connected to VOUTLHP, VOUTRHP */
121 {"Headphone Jack", NULL, "VOUTLHP"},
122 {"Headphone Jack", NULL, "VOUTRHP"},
123
124 /* ext speaker connected to VOUTL, VOUTR */
125 {"Speaker", NULL, "VOUTL"},
126 {"Speaker", NULL, "VOUTR"},
127
128 /* mic is connected to VINM */
129 {"VINM", NULL, "Mic Jack"},
130};
131
132static struct platform_device *s3c24xx_snd_device;
133static struct clk *xtal;
134
135static int rx1950_startup(struct snd_pcm_substream *substream)
136{
137 struct snd_pcm_runtime *runtime = substream->runtime;
138
139 runtime->hw.rate_min = hw_rates.list[0];
140 runtime->hw.rate_max = hw_rates.list[hw_rates.count - 1];
141 runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
142
143 return snd_pcm_hw_constraint_list(runtime, 0,
144 SNDRV_PCM_HW_PARAM_RATE,
145 &hw_rates);
146}
147
148static int rx1950_spk_power(struct snd_soc_dapm_widget *w,
149 struct snd_kcontrol *kcontrol, int event)
150{
151 if (SND_SOC_DAPM_EVENT_ON(event))
152 gpio_set_value(S3C2410_GPA(1), 1);
153 else
154 gpio_set_value(S3C2410_GPA(1), 0);
155
156 return 0;
157}
158
159static int rx1950_hw_params(struct snd_pcm_substream *substream,
160 struct snd_pcm_hw_params *params)
161{
162 struct snd_soc_pcm_runtime *rtd = substream->private_data;
163 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
164 struct snd_soc_dai *codec_dai = rtd->codec_dai;
165 int div;
166 int ret;
167 unsigned int rate = params_rate(params);
168 int clk_source, fs_mode;
169
170 switch (rate) {
171 case 16000:
172 case 48000:
173 clk_source = S3C24XX_CLKSRC_PCLK;
174 fs_mode = S3C2410_IISMOD_256FS;
175 div = s3c24xx_i2s_get_clockrate() / (256 * rate);
176 if (s3c24xx_i2s_get_clockrate() % (256 * rate) > (128 * rate))
177 div++;
178 break;
179 case 44100:
180 case 88200:
181 clk_source = S3C24XX_CLKSRC_MPLL;
182 fs_mode = S3C2410_IISMOD_256FS;
183 div = clk_get_rate(xtal) / (256 * rate);
184 if (clk_get_rate(xtal) % (256 * rate) > (128 * rate))
185 div++;
186 break;
187 default:
188 printk(KERN_ERR "%s: rate %d is not supported\n",
189 __func__, rate);
190 return -EINVAL;
191 }
192
193 /* set codec DAI configuration */
194 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
195 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
196 if (ret < 0)
197 return ret;
198
199 /* set cpu DAI configuration */
200 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
201 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
202 if (ret < 0)
203 return ret;
204
205 /* select clock source */
206 ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source, rate,
207 SND_SOC_CLOCK_OUT);
208 if (ret < 0)
209 return ret;
210
211 /* set MCLK division for sample rate */
212 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
213 S3C2410_IISMOD_384FS);
214 if (ret < 0)
215 return ret;
216
217 /* set BCLK division for sample rate */
218 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
219 S3C2410_IISMOD_32FS);
220 if (ret < 0)
221 return ret;
222
223 /* set prescaler division for sample rate */
224 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
225 S3C24XX_PRESCALE(div, div));
226 if (ret < 0)
227 return ret;
228
229 return 0;
230}
231
232static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
233{
234 struct snd_soc_codec *codec = rtd->codec;
235 int err;
236
237 /* Add rx1950 specific widgets */
238 err = snd_soc_dapm_new_controls(codec, uda1380_dapm_widgets,
239 ARRAY_SIZE(uda1380_dapm_widgets));
240
241 if (err)
242 return err;
243
244 /* Set up rx1950 specific audio path audio_mapnects */
245 err = snd_soc_dapm_add_routes(codec, audio_map,
246 ARRAY_SIZE(audio_map));
247
248 if (err)
249 return err;
250
251 snd_soc_dapm_enable_pin(codec, "Headphone Jack");
252 snd_soc_dapm_enable_pin(codec, "Speaker");
253
254 snd_soc_dapm_sync(codec);
255
256 snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
257 &hp_jack);
258
259 snd_soc_jack_add_pins(&hp_jack, ARRAY_SIZE(hp_jack_pins),
260 hp_jack_pins);
261
262 snd_soc_jack_add_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
263 hp_jack_gpios);
264
265 return 0;
266}
267
268static int __init rx1950_init(void)
269{
270 int ret;
271
272 if (!machine_is_rx1950())
273 return -ENODEV;
274
275 /* configure some gpios */
276 ret = gpio_request(S3C2410_GPA(1), "speaker-power");
277 if (ret)
278 goto err_gpio;
279
280 ret = gpio_direction_output(S3C2410_GPA(1), 0);
281 if (ret)
282 goto err_gpio_conf;
283
284 s3c24xx_snd_device = platform_device_alloc("soc-audio", -1);
285 if (!s3c24xx_snd_device) {
286 ret = -ENOMEM;
287 goto err_plat_alloc;
288 }
289
290 platform_set_drvdata(s3c24xx_snd_device, &rx1950_asoc);
291 ret = platform_device_add(s3c24xx_snd_device);
292
293 if (ret) {
294 platform_device_put(s3c24xx_snd_device);
295 goto err_plat_add;
296 }
297
298 xtal = clk_get(&s3c24xx_snd_device->dev, "xtal");
299
300 if (IS_ERR(xtal)) {
301 ret = PTR_ERR(xtal);
302 platform_device_unregister(s3c24xx_snd_device);
303 goto err_clk;
304 }
305
306 return 0;
307
308err_clk:
309err_plat_add:
310err_plat_alloc:
311err_gpio_conf:
312 gpio_free(S3C2410_GPA(1));
313
314err_gpio:
315 return ret;
316}
317
318static void __exit rx1950_exit(void)
319{
320 platform_device_unregister(s3c24xx_snd_device);
321 snd_soc_jack_free_gpios(&hp_jack, ARRAY_SIZE(hp_jack_gpios),
322 hp_jack_gpios);
323 clk_put(xtal);
324 gpio_free(S3C2410_GPA(1));
325}
326
327module_init(rx1950_init);
328module_exit(rx1950_exit);
329
330/* Module information */
331MODULE_AUTHOR("Vasily Khoruzhick");
332MODULE_DESCRIPTION("ALSA SoC RX1950");
333MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c-ac97.c b/sound/soc/s3c24xx/s3c-ac97.c
index 31f6d45b6384..f891eb79b575 100644
--- a/sound/soc/s3c24xx/s3c-ac97.c
+++ b/sound/soc/s3c24xx/s3c-ac97.c
@@ -89,7 +89,7 @@ static void s3c_ac97_activate(struct snd_ac97 *ac97)
89 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); 89 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
90 90
91 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) 91 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
92 printk(KERN_ERR "AC97: Unable to activate!"); 92 pr_err("AC97: Unable to activate!");
93} 93}
94 94
95static unsigned short s3c_ac97_read(struct snd_ac97 *ac97, 95static unsigned short s3c_ac97_read(struct snd_ac97 *ac97,
@@ -115,14 +115,15 @@ static unsigned short s3c_ac97_read(struct snd_ac97 *ac97,
115 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); 115 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
116 116
117 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) 117 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
118 printk(KERN_ERR "AC97: Unable to read!"); 118 pr_err("AC97: Unable to read!");
119 119
120 stat = readl(s3c_ac97.regs + S3C_AC97_STAT); 120 stat = readl(s3c_ac97.regs + S3C_AC97_STAT);
121 addr = (stat >> 16) & 0x7f; 121 addr = (stat >> 16) & 0x7f;
122 data = (stat & 0xffff); 122 data = (stat & 0xffff);
123 123
124 if (addr != reg) 124 if (addr != reg)
125 printk(KERN_ERR "s3c-ac97: req addr = %02x, rep addr = %02x\n", reg, addr); 125 pr_err("s3c-ac97: req addr = %02x, rep addr = %02x\n",
126 reg, addr);
126 127
127 mutex_unlock(&s3c_ac97.lock); 128 mutex_unlock(&s3c_ac97.lock);
128 129
@@ -151,7 +152,7 @@ static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
151 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL); 152 writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
152 153
153 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ)) 154 if (!wait_for_completion_timeout(&s3c_ac97.done, HZ))
154 printk(KERN_ERR "AC97: Unable to write!"); 155 pr_err("AC97: Unable to write!");
155 156
156 ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD); 157 ac_codec_cmd = readl(s3c_ac97.regs + S3C_AC97_CODEC_CMD);
157 ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; 158 ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ;
@@ -162,6 +163,7 @@ static void s3c_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
162 163
163static void s3c_ac97_cold_reset(struct snd_ac97 *ac97) 164static void s3c_ac97_cold_reset(struct snd_ac97 *ac97)
164{ 165{
166 pr_debug("AC97: Cold reset\n");
165 writel(S3C_AC97_GLBCTRL_COLDRESET, 167 writel(S3C_AC97_GLBCTRL_COLDRESET,
166 s3c_ac97.regs + S3C_AC97_GLBCTRL); 168 s3c_ac97.regs + S3C_AC97_GLBCTRL);
167 msleep(1); 169 msleep(1);
@@ -178,6 +180,8 @@ static void s3c_ac97_warm_reset(struct snd_ac97 *ac97)
178 if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE) 180 if (stat == S3C_AC97_GLBSTAT_MAINSTATE_ACTIVE)
179 return; /* Return if already active */ 181 return; /* Return if already active */
180 182
183 pr_debug("AC97: Warm reset\n");
184
181 writel(S3C_AC97_GLBCTRL_WARMRESET, s3c_ac97.regs + S3C_AC97_GLBCTRL); 185 writel(S3C_AC97_GLBCTRL_WARMRESET, s3c_ac97.regs + S3C_AC97_GLBCTRL);
182 msleep(1); 186 msleep(1);
183 187
@@ -222,7 +226,7 @@ static int s3c_ac97_hw_params(struct snd_pcm_substream *substream,
222 struct snd_soc_dai *dai) 226 struct snd_soc_dai *dai)
223{ 227{
224 struct snd_soc_pcm_runtime *rtd = substream->private_data; 228 struct snd_soc_pcm_runtime *rtd = substream->private_data;
225 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 229 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
226 struct s3c_dma_params *dma_data; 230 struct s3c_dma_params *dma_data;
227 231
228 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 232 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -241,7 +245,7 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
241 u32 ac_glbctrl; 245 u32 ac_glbctrl;
242 struct snd_soc_pcm_runtime *rtd = substream->private_data; 246 struct snd_soc_pcm_runtime *rtd = substream->private_data;
243 struct s3c_dma_params *dma_data = 247 struct s3c_dma_params *dma_data =
244 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 248 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
245 249
246 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); 250 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
247 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 251 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
@@ -277,7 +281,7 @@ static int s3c_ac97_hw_mic_params(struct snd_pcm_substream *substream,
277 struct snd_soc_dai *dai) 281 struct snd_soc_dai *dai)
278{ 282{
279 struct snd_soc_pcm_runtime *rtd = substream->private_data; 283 struct snd_soc_pcm_runtime *rtd = substream->private_data;
280 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 284 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
281 285
282 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 286 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
283 return -ENODEV; 287 return -ENODEV;
@@ -293,7 +297,7 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
293 u32 ac_glbctrl; 297 u32 ac_glbctrl;
294 struct snd_soc_pcm_runtime *rtd = substream->private_data; 298 struct snd_soc_pcm_runtime *rtd = substream->private_data;
295 struct s3c_dma_params *dma_data = 299 struct s3c_dma_params *dma_data =
296 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 300 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
297 301
298 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL); 302 ac_glbctrl = readl(s3c_ac97.regs + S3C_AC97_GLBCTRL);
299 ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK; 303 ac_glbctrl &= ~S3C_AC97_GLBCTRL_MICINTM_MASK;
@@ -328,10 +332,9 @@ static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
328 .trigger = s3c_ac97_mic_trigger, 332 .trigger = s3c_ac97_mic_trigger,
329}; 333};
330 334
331struct snd_soc_dai s3c_ac97_dai[] = { 335static struct snd_soc_dai_driver s3c_ac97_dai[] = {
332 [S3C_AC97_DAI_PCM] = { 336 [S3C_AC97_DAI_PCM] = {
333 .name = "s3c-ac97", 337 .name = "s3c-ac97",
334 .id = S3C_AC97_DAI_PCM,
335 .ac97_control = 1, 338 .ac97_control = 1,
336 .playback = { 339 .playback = {
337 .stream_name = "AC97 Playback", 340 .stream_name = "AC97 Playback",
@@ -349,7 +352,6 @@ struct snd_soc_dai s3c_ac97_dai[] = {
349 }, 352 },
350 [S3C_AC97_DAI_MIC] = { 353 [S3C_AC97_DAI_MIC] = {
351 .name = "s3c-ac97-mic", 354 .name = "s3c-ac97-mic",
352 .id = S3C_AC97_DAI_MIC,
353 .ac97_control = 1, 355 .ac97_control = 1,
354 .capture = { 356 .capture = {
355 .stream_name = "AC97 Mic Capture", 357 .stream_name = "AC97 Mic Capture",
@@ -360,7 +362,6 @@ struct snd_soc_dai s3c_ac97_dai[] = {
360 .ops = &s3c_ac97_mic_dai_ops, 362 .ops = &s3c_ac97_mic_dai_ops,
361 }, 363 },
362}; 364};
363EXPORT_SYMBOL_GPL(s3c_ac97_dai);
364 365
365static __devinit int s3c_ac97_probe(struct platform_device *pdev) 366static __devinit int s3c_ac97_probe(struct platform_device *pdev)
366{ 367{
@@ -445,14 +446,12 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
445 ret = request_irq(irq_res->start, s3c_ac97_irq, 446 ret = request_irq(irq_res->start, s3c_ac97_irq,
446 IRQF_DISABLED, "AC97", NULL); 447 IRQF_DISABLED, "AC97", NULL);
447 if (ret < 0) { 448 if (ret < 0) {
448 printk(KERN_ERR "s3c-ac97: interrupt request failed.\n"); 449 dev_err(&pdev->dev, "s3c-ac97: interrupt request failed.\n");
449 goto err4; 450 goto err4;
450 } 451 }
451 452
452 s3c_ac97_dai[S3C_AC97_DAI_PCM].dev = &pdev->dev; 453 ret = snd_soc_register_dais(&pdev->dev, s3c_ac97_dai,
453 s3c_ac97_dai[S3C_AC97_DAI_MIC].dev = &pdev->dev; 454 ARRAY_SIZE(s3c_ac97_dai));
454
455 ret = snd_soc_register_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai));
456 if (ret) 455 if (ret)
457 goto err5; 456 goto err5;
458 457
@@ -476,7 +475,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
476{ 475{
477 struct resource *mem_res, *irq_res; 476 struct resource *mem_res, *irq_res;
478 477
479 snd_soc_unregister_dais(s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); 478 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c_ac97_dai));
480 479
481 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 480 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
482 if (irq_res) 481 if (irq_res)
@@ -518,3 +517,4 @@ module_exit(s3c_ac97_exit);
518MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); 517MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
519MODULE_DESCRIPTION("AC97 driver for the Samsung SoC"); 518MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
520MODULE_LICENSE("GPL"); 519MODULE_LICENSE("GPL");
520MODULE_ALIAS("platform:s3c-ac97");
diff --git a/sound/soc/s3c24xx/s3c-ac97.h b/sound/soc/s3c24xx/s3c-ac97.h
index 278198379def..5dcedd07fdbb 100644
--- a/sound/soc/s3c24xx/s3c-ac97.h
+++ b/sound/soc/s3c24xx/s3c-ac97.h
@@ -18,6 +18,4 @@
18#define S3C_AC97_DAI_PCM 0 18#define S3C_AC97_DAI_PCM 0
19#define S3C_AC97_DAI_MIC 1 19#define S3C_AC97_DAI_MIC 1
20 20
21extern struct snd_soc_dai s3c_ac97_dai[];
22
23#endif /* __S3C_AC97_H_ */ 21#endif /* __S3C_AC97_H_ */
diff --git a/sound/soc/s3c24xx/s3c-dma.c b/sound/soc/s3c24xx/s3c-dma.c
index f1b1bc4bacfb..243f79bf43bb 100644
--- a/sound/soc/s3c24xx/s3c-dma.c
+++ b/sound/soc/s3c24xx/s3c-dma.c
@@ -146,7 +146,7 @@ static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
146 struct snd_soc_pcm_runtime *rtd = substream->private_data; 146 struct snd_soc_pcm_runtime *rtd = substream->private_data;
147 unsigned long totbytes = params_buffer_bytes(params); 147 unsigned long totbytes = params_buffer_bytes(params);
148 struct s3c_dma_params *dma = 148 struct s3c_dma_params *dma =
149 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 149 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
150 int ret = 0; 150 int ret = 0;
151 151
152 152
@@ -440,14 +440,14 @@ static int s3c_dma_new(struct snd_card *card,
440 if (!card->dev->coherent_dma_mask) 440 if (!card->dev->coherent_dma_mask)
441 card->dev->coherent_dma_mask = 0xffffffff; 441 card->dev->coherent_dma_mask = 0xffffffff;
442 442
443 if (dai->playback.channels_min) { 443 if (dai->driver->playback.channels_min) {
444 ret = s3c_preallocate_dma_buffer(pcm, 444 ret = s3c_preallocate_dma_buffer(pcm,
445 SNDRV_PCM_STREAM_PLAYBACK); 445 SNDRV_PCM_STREAM_PLAYBACK);
446 if (ret) 446 if (ret)
447 goto out; 447 goto out;
448 } 448 }
449 449
450 if (dai->capture.channels_min) { 450 if (dai->driver->capture.channels_min) {
451 ret = s3c_preallocate_dma_buffer(pcm, 451 ret = s3c_preallocate_dma_buffer(pcm,
452 SNDRV_PCM_STREAM_CAPTURE); 452 SNDRV_PCM_STREAM_CAPTURE);
453 if (ret) 453 if (ret)
@@ -457,26 +457,46 @@ static int s3c_dma_new(struct snd_card *card,
457 return ret; 457 return ret;
458} 458}
459 459
460struct snd_soc_platform s3c24xx_soc_platform = { 460static struct snd_soc_platform_driver s3c24xx_soc_platform = {
461 .name = "s3c24xx-audio", 461 .ops = &s3c_dma_ops,
462 .pcm_ops = &s3c_dma_ops,
463 .pcm_new = s3c_dma_new, 462 .pcm_new = s3c_dma_new,
464 .pcm_free = s3c_dma_free_dma_buffers, 463 .pcm_free = s3c_dma_free_dma_buffers,
465}; 464};
466EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
467 465
468static int __init s3c24xx_soc_platform_init(void) 466static int __devinit s3c24xx_soc_platform_probe(struct platform_device *pdev)
469{ 467{
470 return snd_soc_register_platform(&s3c24xx_soc_platform); 468 return snd_soc_register_platform(&pdev->dev, &s3c24xx_soc_platform);
471} 469}
472module_init(s3c24xx_soc_platform_init);
473 470
474static void __exit s3c24xx_soc_platform_exit(void) 471static int __devexit s3c24xx_soc_platform_remove(struct platform_device *pdev)
475{ 472{
476 snd_soc_unregister_platform(&s3c24xx_soc_platform); 473 snd_soc_unregister_platform(&pdev->dev);
474 return 0;
475}
476
477static struct platform_driver s3c24xx_pcm_driver = {
478 .driver = {
479 .name = "s3c24xx-pcm-audio",
480 .owner = THIS_MODULE,
481 },
482
483 .probe = s3c24xx_soc_platform_probe,
484 .remove = __devexit_p(s3c24xx_soc_platform_remove),
485};
486
487static int __init snd_s3c24xx_pcm_init(void)
488{
489 return platform_driver_register(&s3c24xx_pcm_driver);
490}
491module_init(snd_s3c24xx_pcm_init);
492
493static void __exit snd_s3c24xx_pcm_exit(void)
494{
495 platform_driver_unregister(&s3c24xx_pcm_driver);
477} 496}
478module_exit(s3c24xx_soc_platform_exit); 497module_exit(snd_s3c24xx_pcm_exit);
479 498
480MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 499MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
481MODULE_DESCRIPTION("Samsung S3C Audio DMA module"); 500MODULE_DESCRIPTION("Samsung S3C Audio DMA module");
482MODULE_LICENSE("GPL"); 501MODULE_LICENSE("GPL");
502MODULE_ALIAS("platform:s3c24xx-pcm-audio");
diff --git a/sound/soc/s3c24xx/s3c-dma.h b/sound/soc/s3c24xx/s3c-dma.h
index 69bb6bf6fc1c..748c07d7c075 100644
--- a/sound/soc/s3c24xx/s3c-dma.h
+++ b/sound/soc/s3c24xx/s3c-dma.h
@@ -25,7 +25,6 @@ struct s3c_dma_params {
25#define S3C24XX_DAI_I2S 0 25#define S3C24XX_DAI_I2S 0
26 26
27/* platform data */ 27/* platform data */
28extern struct snd_soc_platform s3c24xx_soc_platform;
29extern struct snd_ac97_bus_ops s3c24xx_ac97_ops; 28extern struct snd_ac97_bus_ops s3c24xx_ac97_ops;
30 29
31#endif 30#endif
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index 64376b2aac73..b3866d5b19e9 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -49,7 +49,7 @@
49 49
50static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) 50static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
51{ 51{
52 return cpu_dai->private_data; 52 return snd_soc_dai_get_drvdata(cpu_dai);
53} 53}
54 54
55#define bit_set(v, b) (((v) & (b)) ? 1 : 0) 55#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
@@ -307,11 +307,9 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
307 307
308static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream, 308static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
309 struct snd_pcm_hw_params *params, 309 struct snd_pcm_hw_params *params,
310 struct snd_soc_dai *socdai) 310 struct snd_soc_dai *dai)
311{ 311{
312 struct snd_soc_pcm_runtime *rtd = substream->private_data; 312 struct s3c_i2sv2_info *i2s = to_info(dai);
313 struct snd_soc_dai_link *dai = rtd->dai;
314 struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
315 struct s3c_dma_params *dma_data; 313 struct s3c_dma_params *dma_data;
316 u32 iismod; 314 u32 iismod;
317 315
@@ -322,7 +320,7 @@ static int s3c_i2sv2_hw_params(struct snd_pcm_substream *substream,
322 else 320 else
323 dma_data = i2s->dma_capture; 321 dma_data = i2s->dma_capture;
324 322
325 snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); 323 snd_soc_dai_set_dma_data(dai, substream, dma_data);
326 324
327 /* Working copies of register */ 325 /* Working copies of register */
328 iismod = readl(i2s->regs + S3C2412_IISMOD); 326 iismod = readl(i2s->regs + S3C2412_IISMOD);
@@ -396,12 +394,12 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
396 struct snd_soc_dai *dai) 394 struct snd_soc_dai *dai)
397{ 395{
398 struct snd_soc_pcm_runtime *rtd = substream->private_data; 396 struct snd_soc_pcm_runtime *rtd = substream->private_data;
399 struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai); 397 struct s3c_i2sv2_info *i2s = to_info(rtd->cpu_dai);
400 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); 398 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
401 unsigned long irqs; 399 unsigned long irqs;
402 int ret = 0; 400 int ret = 0;
403 struct s3c_dma_params *dma_data = 401 struct s3c_dma_params *dma_data =
404 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 402 snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
405 403
406 pr_debug("Entered %s\n", __func__); 404 pr_debug("Entered %s\n", __func__);
407 405
@@ -640,36 +638,17 @@ int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
640} 638}
641EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate); 639EXPORT_SYMBOL_GPL(s3c_i2sv2_iis_calc_rate);
642 640
643int s3c_i2sv2_probe(struct platform_device *pdev, 641int s3c_i2sv2_probe(struct snd_soc_dai *dai,
644 struct snd_soc_dai *dai,
645 struct s3c_i2sv2_info *i2s, 642 struct s3c_i2sv2_info *i2s,
646 unsigned long base) 643 unsigned long base)
647{ 644{
648 struct device *dev = &pdev->dev; 645 struct device *dev = dai->dev;
649 unsigned int iismod; 646 unsigned int iismod;
650 647
651 i2s->dev = dev; 648 i2s->dev = dev;
652 649
653 /* record our i2s structure for later use in the callbacks */ 650 /* record our i2s structure for later use in the callbacks */
654 dai->private_data = i2s; 651 snd_soc_dai_set_drvdata(dai, i2s);
655
656 if (!base) {
657 struct resource *res = platform_get_resource(pdev,
658 IORESOURCE_MEM,
659 0);
660 if (!res) {
661 dev_err(dev, "Unable to get register resource\n");
662 return -ENXIO;
663 }
664
665 if (!request_mem_region(res->start, resource_size(res),
666 "s3c64xx-i2s-v4")) {
667 dev_err(dev, "Unable to request register region\n");
668 return -EBUSY;
669 }
670
671 base = res->start;
672 }
673 652
674 i2s->regs = ioremap(base, 0x100); 653 i2s->regs = ioremap(base, 0x100);
675 if (i2s->regs == NULL) { 654 if (i2s->regs == NULL) {
@@ -752,9 +731,10 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
752#define s3c2412_i2s_resume NULL 731#define s3c2412_i2s_resume NULL
753#endif 732#endif
754 733
755int s3c_i2sv2_register_dai(struct snd_soc_dai *dai) 734int s3c_i2sv2_register_dai(struct device *dev, int id,
735 struct snd_soc_dai_driver *drv)
756{ 736{
757 struct snd_soc_dai_ops *ops = dai->ops; 737 struct snd_soc_dai_ops *ops = drv->ops;
758 738
759 ops->trigger = s3c2412_i2s_trigger; 739 ops->trigger = s3c2412_i2s_trigger;
760 if (!ops->hw_params) 740 if (!ops->hw_params)
@@ -767,10 +747,10 @@ int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
767 if (!ops->delay) 747 if (!ops->delay)
768 ops->delay = s3c2412_i2s_delay; 748 ops->delay = s3c2412_i2s_delay;
769 749
770 dai->suspend = s3c2412_i2s_suspend; 750 drv->suspend = s3c2412_i2s_suspend;
771 dai->resume = s3c2412_i2s_resume; 751 drv->resume = s3c2412_i2s_resume;
772 752
773 return snd_soc_register_dai(dai); 753 return snd_soc_register_dai(dev, drv);
774} 754}
775EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai); 755EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
776 756
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h
index 766f43a13d8b..d45830151484 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.h
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.h
@@ -66,6 +66,8 @@ struct s3c_i2sv2_info {
66 u32 suspend_iismod; 66 u32 suspend_iismod;
67 u32 suspend_iiscon; 67 u32 suspend_iiscon;
68 u32 suspend_iispsr; 68 u32 suspend_iispsr;
69
70 unsigned long base;
69}; 71};
70 72
71extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai); 73extern struct clk *s3c_i2sv2_get_clock(struct snd_soc_dai *cpu_dai);
@@ -81,23 +83,24 @@ extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
81 83
82/** 84/**
83 * s3c_i2sv2_probe - probe for i2s device helper 85 * s3c_i2sv2_probe - probe for i2s device helper
84 * @pdev: The platform device supplied to the original probe.
85 * @dai: The ASoC DAI structure supplied to the original probe. 86 * @dai: The ASoC DAI structure supplied to the original probe.
86 * @i2s: Our local i2s structure to fill in. 87 * @i2s: Our local i2s structure to fill in.
87 * @base: The base address for the registers. 88 * @base: The base address for the registers.
88 */ 89 */
89extern int s3c_i2sv2_probe(struct platform_device *pdev, 90extern int s3c_i2sv2_probe(struct snd_soc_dai *dai,
90 struct snd_soc_dai *dai,
91 struct s3c_i2sv2_info *i2s, 91 struct s3c_i2sv2_info *i2s,
92 unsigned long base); 92 unsigned long base);
93 93
94/** 94/**
95 * s3c_i2sv2_register_dai - register dai with soc core 95 * s3c_i2sv2_register_dai - register dai with soc core
96 * @dai: The snd_soc_dai structure to register 96 * @dev: DAI device
97 * @id: DAI ID
98 * @drv: The driver structure to register
97 * 99 *
98 * Fill in any missing fields and then register the given dai with the 100 * Fill in any missing fields and then register the given dai with the
99 * soc core. 101 * soc core.
100 */ 102 */
101extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai); 103extern int s3c_i2sv2_register_dai(struct device *dev, int id,
104 struct snd_soc_dai_driver *drv);
102 105
103#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */ 106#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */
diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c
index 326f0a9e7e30..2e020e1b4eab 100644
--- a/sound/soc/s3c24xx/s3c-pcm.c
+++ b/sound/soc/s3c24xx/s3c-pcm.c
@@ -64,11 +64,6 @@ static struct s3c_dma_params s3c_pcm_stereo_in[] = {
64 64
65static struct s3c_pcm_info s3c_pcm[2]; 65static struct s3c_pcm_info s3c_pcm[2];
66 66
67static inline struct s3c_pcm_info *to_info(struct snd_soc_dai *cpu_dai)
68{
69 return cpu_dai->private_data;
70}
71
72static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on) 67static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on)
73{ 68{
74 void __iomem *regs = pcm->regs; 69 void __iomem *regs = pcm->regs;
@@ -83,7 +78,7 @@ static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on)
83 ctl |= S3C_PCM_CTL_TXDMA_EN; 78 ctl |= S3C_PCM_CTL_TXDMA_EN;
84 ctl |= S3C_PCM_CTL_TXFIFO_EN; 79 ctl |= S3C_PCM_CTL_TXFIFO_EN;
85 ctl |= S3C_PCM_CTL_ENABLE; 80 ctl |= S3C_PCM_CTL_ENABLE;
86 ctl |= (0x20<<S3C_PCM_CTL_TXDIPSTICK_SHIFT); 81 ctl |= (0x4<<S3C_PCM_CTL_TXDIPSTICK_SHIFT);
87 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN; 82 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
88 } else { 83 } else {
89 ctl &= ~S3C_PCM_CTL_TXDMA_EN; 84 ctl &= ~S3C_PCM_CTL_TXDMA_EN;
@@ -107,11 +102,14 @@ static void s3c_pcm_snd_rxctrl(struct s3c_pcm_info *pcm, int on)
107 102
108 ctl = readl(regs + S3C_PCM_CTL); 103 ctl = readl(regs + S3C_PCM_CTL);
109 clkctl = readl(regs + S3C_PCM_CLKCTL); 104 clkctl = readl(regs + S3C_PCM_CLKCTL);
105 ctl &= ~(S3C_PCM_CTL_RXDIPSTICK_MASK
106 << S3C_PCM_CTL_RXDIPSTICK_SHIFT);
110 107
111 if (on) { 108 if (on) {
112 ctl |= S3C_PCM_CTL_RXDMA_EN; 109 ctl |= S3C_PCM_CTL_RXDMA_EN;
113 ctl |= S3C_PCM_CTL_RXFIFO_EN; 110 ctl |= S3C_PCM_CTL_RXFIFO_EN;
114 ctl |= S3C_PCM_CTL_ENABLE; 111 ctl |= S3C_PCM_CTL_ENABLE;
112 ctl |= (0x20<<S3C_PCM_CTL_RXDIPSTICK_SHIFT);
115 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN; 113 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
116 } else { 114 } else {
117 ctl &= ~S3C_PCM_CTL_RXDMA_EN; 115 ctl &= ~S3C_PCM_CTL_RXDMA_EN;
@@ -132,7 +130,7 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
132 struct snd_soc_dai *dai) 130 struct snd_soc_dai *dai)
133{ 131{
134 struct snd_soc_pcm_runtime *rtd = substream->private_data; 132 struct snd_soc_pcm_runtime *rtd = substream->private_data;
135 struct s3c_pcm_info *pcm = to_info(rtd->dai->cpu_dai); 133 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
136 unsigned long flags; 134 unsigned long flags;
137 135
138 dev_dbg(pcm->dev, "Entered %s\n", __func__); 136 dev_dbg(pcm->dev, "Entered %s\n", __func__);
@@ -176,8 +174,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
176 struct snd_soc_dai *socdai) 174 struct snd_soc_dai *socdai)
177{ 175{
178 struct snd_soc_pcm_runtime *rtd = substream->private_data; 176 struct snd_soc_pcm_runtime *rtd = substream->private_data;
179 struct snd_soc_dai_link *dai = rtd->dai; 177 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
180 struct s3c_pcm_info *pcm = to_info(dai->cpu_dai);
181 struct s3c_dma_params *dma_data; 178 struct s3c_dma_params *dma_data;
182 void __iomem *regs = pcm->regs; 179 void __iomem *regs = pcm->regs;
183 struct clk *clk; 180 struct clk *clk;
@@ -192,7 +189,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
192 else 189 else
193 dma_data = pcm->dma_capture; 190 dma_data = pcm->dma_capture;
194 191
195 snd_soc_dai_set_dma_data(dai->cpu_dai, substream, dma_data); 192 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
196 193
197 /* Strictly check for sample size */ 194 /* Strictly check for sample size */
198 switch (params_format(params)) { 195 switch (params_format(params)) {
@@ -242,7 +239,7 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
242static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai, 239static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
243 unsigned int fmt) 240 unsigned int fmt)
244{ 241{
245 struct s3c_pcm_info *pcm = to_info(cpu_dai); 242 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
246 void __iomem *regs = pcm->regs; 243 void __iomem *regs = pcm->regs;
247 unsigned long flags; 244 unsigned long flags;
248 int ret = 0; 245 int ret = 0;
@@ -313,7 +310,7 @@ exit:
313static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai, 310static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,
314 int div_id, int div) 311 int div_id, int div)
315{ 312{
316 struct s3c_pcm_info *pcm = to_info(cpu_dai); 313 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
317 314
318 switch (div_id) { 315 switch (div_id) {
319 case S3C_PCM_SCLK_PER_FS: 316 case S3C_PCM_SCLK_PER_FS:
@@ -330,7 +327,7 @@ static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,
330static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai, 327static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai,
331 int clk_id, unsigned int freq, int dir) 328 int clk_id, unsigned int freq, int dir)
332{ 329{
333 struct s3c_pcm_info *pcm = to_info(cpu_dai); 330 struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
334 void __iomem *regs = pcm->regs; 331 void __iomem *regs = pcm->regs;
335 u32 clkctl = readl(regs + S3C_PCM_CLKCTL); 332 u32 clkctl = readl(regs + S3C_PCM_CLKCTL);
336 333
@@ -366,10 +363,7 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
366 363
367#define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000 364#define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000
368 365
369#define S3C_PCM_DECLARE(n) \ 366#define S3C_PCM_DAI_DECLARE \
370{ \
371 .name = "samsung-pcm", \
372 .id = (n), \
373 .symmetric_rates = 1, \ 367 .symmetric_rates = 1, \
374 .ops = &s3c_pcm_dai_ops, \ 368 .ops = &s3c_pcm_dai_ops, \
375 .playback = { \ 369 .playback = { \
@@ -383,19 +377,23 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
383 .channels_max = 2, \ 377 .channels_max = 2, \
384 .rates = S3C_PCM_RATES, \ 378 .rates = S3C_PCM_RATES, \
385 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 379 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
386 }, \ 380 }
387}
388 381
389struct snd_soc_dai s3c_pcm_dai[] = { 382struct snd_soc_dai_driver s3c_pcm_dai[] = {
390 S3C_PCM_DECLARE(0), 383 [0] = {
391 S3C_PCM_DECLARE(1), 384 .name = "samsung-pcm.0",
385 S3C_PCM_DAI_DECLARE,
386 },
387 [1] = {
388 .name = "samsung-pcm.1",
389 S3C_PCM_DAI_DECLARE,
390 },
392}; 391};
393EXPORT_SYMBOL_GPL(s3c_pcm_dai); 392EXPORT_SYMBOL_GPL(s3c_pcm_dai);
394 393
395static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev) 394static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
396{ 395{
397 struct s3c_pcm_info *pcm; 396 struct s3c_pcm_info *pcm;
398 struct snd_soc_dai *dai;
399 struct resource *mem_res, *dmatx_res, *dmarx_res; 397 struct resource *mem_res, *dmatx_res, *dmarx_res;
400 struct s3c_audio_pdata *pcm_pdata; 398 struct s3c_audio_pdata *pcm_pdata;
401 int ret; 399 int ret;
@@ -437,9 +435,6 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
437 435
438 spin_lock_init(&pcm->lock); 436 spin_lock_init(&pcm->lock);
439 437
440 dai = &s3c_pcm_dai[pdev->id];
441 dai->dev = &pdev->dev;
442
443 /* Default is 128fs */ 438 /* Default is 128fs */
444 pcm->sclk_per_fs = 128; 439 pcm->sclk_per_fs = 128;
445 440
@@ -452,7 +447,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
452 clk_enable(pcm->cclk); 447 clk_enable(pcm->cclk);
453 448
454 /* record our pcm structure for later use in the callbacks */ 449 /* record our pcm structure for later use in the callbacks */
455 dai->private_data = pcm; 450 dev_set_drvdata(&pdev->dev, pcm);
456 451
457 if (!request_mem_region(mem_res->start, 452 if (!request_mem_region(mem_res->start,
458 resource_size(mem_res), "samsung-pcm")) { 453 resource_size(mem_res), "samsung-pcm")) {
@@ -476,7 +471,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
476 } 471 }
477 clk_enable(pcm->pclk); 472 clk_enable(pcm->pclk);
478 473
479 ret = snd_soc_register_dai(dai); 474 ret = snd_soc_register_dai(&pdev->dev, &s3c_pcm_dai[pdev->id]);
480 if (ret != 0) { 475 if (ret != 0) {
481 dev_err(&pdev->dev, "failed to get pcm_clock\n"); 476 dev_err(&pdev->dev, "failed to get pcm_clock\n");
482 goto err5; 477 goto err5;
@@ -514,6 +509,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
514 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; 509 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
515 struct resource *mem_res; 510 struct resource *mem_res;
516 511
512 snd_soc_unregister_dai(&pdev->dev);
513
517 iounmap(pcm->regs); 514 iounmap(pcm->regs);
518 515
519 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 516 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -552,3 +549,4 @@ module_exit(s3c_pcm_exit);
552MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); 549MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
553MODULE_DESCRIPTION("S3C PCM Controller Driver"); 550MODULE_DESCRIPTION("S3C PCM Controller Driver");
554MODULE_LICENSE("GPL"); 551MODULE_LICENSE("GPL");
552MODULE_ALIAS("platform:samsung-pcm");
diff --git a/sound/soc/s3c24xx/s3c-pcm.h b/sound/soc/s3c24xx/s3c-pcm.h
index 69ff9971692f..f60baa19387d 100644
--- a/sound/soc/s3c24xx/s3c-pcm.h
+++ b/sound/soc/s3c24xx/s3c-pcm.h
@@ -22,7 +22,8 @@
22/* PCM_CTL Bit-Fields */ 22/* PCM_CTL Bit-Fields */
23#define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f) 23#define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f)
24#define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13) 24#define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13)
25#define S3C_PCM_CTL_RXDIPSTICK_MSK (0x3f<<7) 25#define S3C_PCM_CTL_RXDIPSTICK_MASK (0x3f)
26#define S3C_PCM_CTL_RXDIPSTICK_SHIFT (7)
26#define S3C_PCM_CTL_TXDMA_EN (0x1<<6) 27#define S3C_PCM_CTL_TXDMA_EN (0x1<<6)
27#define S3C_PCM_CTL_RXDMA_EN (0x1<<5) 28#define S3C_PCM_CTL_RXDMA_EN (0x1<<5)
28#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4) 29#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4)
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index 709adef9d043..4a861cfa52c5 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -65,26 +65,20 @@ static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
65 65
66static struct s3c_i2sv2_info s3c2412_i2s; 66static struct s3c_i2sv2_info s3c2412_i2s;
67 67
68static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai) 68static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
69{
70 return cpu_dai->private_data;
71}
72
73static int s3c2412_i2s_probe(struct platform_device *pdev,
74 struct snd_soc_dai *dai)
75{ 69{
76 int ret; 70 int ret;
77 71
78 pr_debug("Entered %s\n", __func__); 72 pr_debug("Entered %s\n", __func__);
79 73
80 ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS); 74 ret = s3c_i2sv2_probe(dai, &s3c2412_i2s, S3C2410_PA_IIS);
81 if (ret) 75 if (ret)
82 return ret; 76 return ret;
83 77
84 s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in; 78 s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in;
85 s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out; 79 s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
86 80
87 s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk"); 81 s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk");
88 if (s3c2412_i2s.iis_cclk == NULL) { 82 if (s3c2412_i2s.iis_cclk == NULL) {
89 pr_err("failed to get i2sclk clock\n"); 83 pr_err("failed to get i2sclk clock\n");
90 iounmap(s3c2412_i2s.regs); 84 iounmap(s3c2412_i2s.regs);
@@ -108,11 +102,20 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
108 return 0; 102 return 0;
109} 103}
110 104
105static int s3c2412_i2s_remove(struct snd_soc_dai *dai)
106{
107 clk_disable(s3c2412_i2s.iis_cclk);
108 clk_put(s3c2412_i2s.iis_cclk);
109 iounmap(s3c2412_i2s.regs);
110
111 return 0;
112}
113
111static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, 114static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
112 struct snd_pcm_hw_params *params, 115 struct snd_pcm_hw_params *params,
113 struct snd_soc_dai *cpu_dai) 116 struct snd_soc_dai *cpu_dai)
114{ 117{
115 struct s3c_i2sv2_info *i2s = to_info(cpu_dai); 118 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
116 struct s3c_dma_params *dma_data; 119 struct s3c_dma_params *dma_data;
117 u32 iismod; 120 u32 iismod;
118 121
@@ -152,10 +155,9 @@ static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
152 .hw_params = s3c2412_i2s_hw_params, 155 .hw_params = s3c2412_i2s_hw_params,
153}; 156};
154 157
155struct snd_soc_dai s3c2412_i2s_dai = { 158static struct snd_soc_dai_driver s3c2412_i2s_dai = {
156 .name = "s3c2412-i2s",
157 .id = 0,
158 .probe = s3c2412_i2s_probe, 159 .probe = s3c2412_i2s_probe,
160 .remove = s3c2412_i2s_remove,
159 .playback = { 161 .playback = {
160 .channels_min = 2, 162 .channels_min = 2,
161 .channels_max = 2, 163 .channels_max = 2,
@@ -170,17 +172,36 @@ struct snd_soc_dai s3c2412_i2s_dai = {
170 }, 172 },
171 .ops = &s3c2412_i2s_dai_ops, 173 .ops = &s3c2412_i2s_dai_ops,
172}; 174};
173EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); 175
176static __devinit int s3c2412_iis_dev_probe(struct platform_device *pdev)
177{
178 return snd_soc_register_dai(&pdev->dev, &s3c2412_i2s_dai);
179}
180
181static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
182{
183 snd_soc_unregister_dai(&pdev->dev);
184 return 0;
185}
186
187static struct platform_driver s3c2412_iis_driver = {
188 .probe = s3c2412_iis_dev_probe,
189 .remove = s3c2412_iis_dev_remove,
190 .driver = {
191 .name = "s3c2412-iis",
192 .owner = THIS_MODULE,
193 },
194};
174 195
175static int __init s3c2412_i2s_init(void) 196static int __init s3c2412_i2s_init(void)
176{ 197{
177 return s3c_i2sv2_register_dai(&s3c2412_i2s_dai); 198 return platform_driver_register(&s3c2412_iis_driver);
178} 199}
179module_init(s3c2412_i2s_init); 200module_init(s3c2412_i2s_init);
180 201
181static void __exit s3c2412_i2s_exit(void) 202static void __exit s3c2412_i2s_exit(void)
182{ 203{
183 snd_soc_unregister_dai(&s3c2412_i2s_dai); 204 platform_driver_unregister(&s3c2412_iis_driver);
184} 205}
185module_exit(s3c2412_i2s_exit); 206module_exit(s3c2412_i2s_exit);
186 207
@@ -188,3 +209,4 @@ module_exit(s3c2412_i2s_exit);
188MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 209MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
189MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); 210MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
190MODULE_LICENSE("GPL"); 211MODULE_LICENSE("GPL");
212MODULE_ALIAS("platform:s3c2412-iis");
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.h b/sound/soc/s3c24xx/s3c2412-i2s.h
index 0b5686b4d5c3..01a0471ac65c 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.h
+++ b/sound/soc/s3c24xx/s3c2412-i2s.h
@@ -24,6 +24,4 @@
24#define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK 24#define S3C2412_CLKSRC_PCLK S3C_I2SV2_CLKSRC_PCLK
25#define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS 25#define S3C2412_CLKSRC_I2SCLK S3C_I2SV2_CLKSRC_AUDIOBUS
26 26
27extern struct snd_soc_dai s3c2412_i2s_dai;
28
29#endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */ 27#endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index c3ac890a3986..e060daaa458f 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -252,7 +252,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
252 else 252 else
253 dma_data = &s3c24xx_i2s_pcm_stereo_in; 253 dma_data = &s3c24xx_i2s_pcm_stereo_in;
254 254
255 snd_soc_dai_set_dma_data(rtd->dai->cpu_dai, substream, dma_data); 255 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
256 256
257 /* Working copies of register */ 257 /* Working copies of register */
258 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD); 258 iismod = readl(s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -280,9 +280,8 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
280 struct snd_soc_dai *dai) 280 struct snd_soc_dai *dai)
281{ 281{
282 int ret = 0; 282 int ret = 0;
283 struct snd_soc_pcm_runtime *rtd = substream->private_data;
284 struct s3c_dma_params *dma_data = 283 struct s3c_dma_params *dma_data =
285 snd_soc_dai_get_dma_data(rtd->dai->cpu_dai, substream); 284 snd_soc_dai_get_dma_data(dai, substream);
286 285
287 pr_debug("Entered %s\n", __func__); 286 pr_debug("Entered %s\n", __func__);
288 287
@@ -387,8 +386,7 @@ u32 s3c24xx_i2s_get_clockrate(void)
387} 386}
388EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate); 387EXPORT_SYMBOL_GPL(s3c24xx_i2s_get_clockrate);
389 388
390static int s3c24xx_i2s_probe(struct platform_device *pdev, 389static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
391 struct snd_soc_dai *dai)
392{ 390{
393 pr_debug("Entered %s\n", __func__); 391 pr_debug("Entered %s\n", __func__);
394 392
@@ -396,7 +394,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev,
396 if (s3c24xx_i2s.regs == NULL) 394 if (s3c24xx_i2s.regs == NULL)
397 return -ENXIO; 395 return -ENXIO;
398 396
399 s3c24xx_i2s.iis_clk = clk_get(&pdev->dev, "iis"); 397 s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis");
400 if (s3c24xx_i2s.iis_clk == NULL) { 398 if (s3c24xx_i2s.iis_clk == NULL) {
401 pr_err("failed to get iis_clock\n"); 399 pr_err("failed to get iis_clock\n");
402 iounmap(s3c24xx_i2s.regs); 400 iounmap(s3c24xx_i2s.regs);
@@ -465,9 +463,7 @@ static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
465 .set_sysclk = s3c24xx_i2s_set_sysclk, 463 .set_sysclk = s3c24xx_i2s_set_sysclk,
466}; 464};
467 465
468struct snd_soc_dai s3c24xx_i2s_dai = { 466static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
469 .name = "s3c24xx-i2s",
470 .id = 0,
471 .probe = s3c24xx_i2s_probe, 467 .probe = s3c24xx_i2s_probe,
472 .suspend = s3c24xx_i2s_suspend, 468 .suspend = s3c24xx_i2s_suspend,
473 .resume = s3c24xx_i2s_resume, 469 .resume = s3c24xx_i2s_resume,
@@ -483,17 +479,36 @@ struct snd_soc_dai s3c24xx_i2s_dai = {
483 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, 479 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
484 .ops = &s3c24xx_i2s_dai_ops, 480 .ops = &s3c24xx_i2s_dai_ops,
485}; 481};
486EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); 482
483static __devinit int s3c24xx_iis_dev_probe(struct platform_device *pdev)
484{
485 return snd_soc_register_dai(&pdev->dev, &s3c24xx_i2s_dai);
486}
487
488static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
489{
490 snd_soc_unregister_dai(&pdev->dev);
491 return 0;
492}
493
494static struct platform_driver s3c24xx_iis_driver = {
495 .probe = s3c24xx_iis_dev_probe,
496 .remove = s3c24xx_iis_dev_remove,
497 .driver = {
498 .name = "s3c24xx-iis",
499 .owner = THIS_MODULE,
500 },
501};
487 502
488static int __init s3c24xx_i2s_init(void) 503static int __init s3c24xx_i2s_init(void)
489{ 504{
490 return snd_soc_register_dai(&s3c24xx_i2s_dai); 505 return platform_driver_register(&s3c24xx_iis_driver);
491} 506}
492module_init(s3c24xx_i2s_init); 507module_init(s3c24xx_i2s_init);
493 508
494static void __exit s3c24xx_i2s_exit(void) 509static void __exit s3c24xx_i2s_exit(void)
495{ 510{
496 snd_soc_unregister_dai(&s3c24xx_i2s_dai); 511 platform_driver_unregister(&s3c24xx_iis_driver);
497} 512}
498module_exit(s3c24xx_i2s_exit); 513module_exit(s3c24xx_i2s_exit);
499 514
@@ -501,3 +516,4 @@ module_exit(s3c24xx_i2s_exit);
501MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 516MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
502MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); 517MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
503MODULE_LICENSE("GPL"); 518MODULE_LICENSE("GPL");
519MODULE_ALIAS("platform:s3c24xx-iis");
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.h b/sound/soc/s3c24xx/s3c24xx-i2s.h
index 726d91cf4e1c..f9ca04edacb7 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.h
@@ -32,6 +32,4 @@
32 32
33u32 s3c24xx_i2s_get_clockrate(void); 33u32 s3c24xx_i2s_get_clockrate(void);
34 34
35extern struct snd_soc_dai s3c24xx_i2s_dai;
36
37#endif /*S3C24XXI2S_H_*/ 35#endif /*S3C24XXI2S_H_*/
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c
index 4984754f3298..c4c111442010 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec.c
@@ -139,8 +139,10 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = {
139 speaker_unmute_get, speaker_unmute_put), 139 speaker_unmute_get, speaker_unmute_put),
140}; 140};
141 141
142void simtec_audio_init(struct snd_soc_codec *codec) 142void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)
143{ 143{
144 struct snd_soc_codec *codec = rtd->codec;
145
144 if (pdata->amp_gpio > 0) { 146 if (pdata->amp_gpio > 0) {
145 pr_debug("%s: adding amp routes\n", __func__); 147 pr_debug("%s: adding amp routes\n", __func__);
146 148
@@ -170,8 +172,8 @@ static int simtec_hw_params(struct snd_pcm_substream *substream,
170 struct snd_pcm_hw_params *params) 172 struct snd_pcm_hw_params *params)
171{ 173{
172 struct snd_soc_pcm_runtime *rtd = substream->private_data; 174 struct snd_soc_pcm_runtime *rtd = substream->private_data;
173 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 175 struct snd_soc_dai *codec_dai = rtd->codec_dai;
174 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 176 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
175 int ret; 177 int ret;
176 178
177 /* Set the CODEC as the bus clock master, I2S */ 179 /* Set the CODEC as the bus clock master, I2S */
@@ -319,12 +321,12 @@ EXPORT_SYMBOL_GPL(simtec_audio_pmops);
319#endif 321#endif
320 322
321int __devinit simtec_audio_core_probe(struct platform_device *pdev, 323int __devinit simtec_audio_core_probe(struct platform_device *pdev,
322 struct snd_soc_device *socdev) 324 struct snd_soc_card *card)
323{ 325{
324 struct platform_device *snd_dev; 326 struct platform_device *snd_dev;
325 int ret; 327 int ret;
326 328
327 socdev->card->dai_link->ops = &simtec_snd_ops; 329 card->dai_link->ops = &simtec_snd_ops;
328 330
329 pdata = pdev->dev.platform_data; 331 pdata = pdev->dev.platform_data;
330 if (!pdata) { 332 if (!pdata) {
@@ -353,8 +355,7 @@ int __devinit simtec_audio_core_probe(struct platform_device *pdev,
353 goto err_gpio; 355 goto err_gpio;
354 } 356 }
355 357
356 platform_set_drvdata(snd_dev, socdev); 358 platform_set_drvdata(snd_dev, card);
357 socdev->dev = &snd_dev->dev;
358 359
359 ret = platform_device_add(snd_dev); 360 ret = platform_device_add(snd_dev);
360 if (ret) { 361 if (ret) {
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.h b/sound/soc/s3c24xx/s3c24xx_simtec.h
index e18faee30cce..e63d5ff9c41f 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec.h
+++ b/sound/soc/s3c24xx/s3c24xx_simtec.h
@@ -7,10 +7,10 @@
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8*/ 8*/
9 9
10extern void simtec_audio_init(struct snd_soc_codec *codec); 10extern void simtec_audio_init(struct snd_soc_pcm_runtime *rtd);
11 11
12extern int simtec_audio_core_probe(struct platform_device *pdev, 12extern int simtec_audio_core_probe(struct platform_device *pdev,
13 struct snd_soc_device *socdev); 13 struct snd_soc_card *card);
14 14
15extern int simtec_audio_remove(struct platform_device *pdev); 15extern int simtec_audio_remove(struct platform_device *pdev);
16 16
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
index bdf8951af8e3..f88453735ae2 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
@@ -73,8 +73,10 @@ static const struct snd_soc_dapm_route base_map[] = {
73 * Attach our controls and configure the necessary codec 73 * Attach our controls and configure the necessary codec
74 * mappings for our sound card instance. 74 * mappings for our sound card instance.
75*/ 75*/
76static int simtec_hermes_init(struct snd_soc_codec *codec) 76static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd)
77{ 77{
78 struct snd_soc_codec *codec = rtd->codec;
79
78 snd_soc_dapm_new_controls(codec, dapm_widgets, 80 snd_soc_dapm_new_controls(codec, dapm_widgets,
79 ARRAY_SIZE(dapm_widgets)); 81 ARRAY_SIZE(dapm_widgets));
80 82
@@ -85,42 +87,33 @@ static int simtec_hermes_init(struct snd_soc_codec *codec)
85 snd_soc_dapm_enable_pin(codec, "Line Out"); 87 snd_soc_dapm_enable_pin(codec, "Line Out");
86 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 88 snd_soc_dapm_enable_pin(codec, "Mic Jack");
87 89
88 simtec_audio_init(codec); 90 simtec_audio_init(rtd);
89 snd_soc_dapm_sync(codec); 91 snd_soc_dapm_sync(codec);
90 92
91 return 0; 93 return 0;
92} 94}
93 95
94static struct aic3x_setup_data codec_setup = {
95};
96
97static struct snd_soc_dai_link simtec_dai_aic33 = { 96static struct snd_soc_dai_link simtec_dai_aic33 = {
98 .name = "tlv320aic33", 97 .name = "tlv320aic33",
99 .stream_name = "TLV320AIC33", 98 .stream_name = "TLV320AIC33",
100 .cpu_dai = &s3c24xx_i2s_dai, 99 .codec_name = "tlv320aic3x-codec.0-0x1a",
101 .codec_dai = &aic3x_dai, 100 .cpu_dai_name = "s3c24xx-i2s",
101 .codec_dai_name = "tlv320aic3x-hifi",
102 .platform_name = "s3c24xx-pcm-audio",
102 .init = simtec_hermes_init, 103 .init = simtec_hermes_init,
103}; 104};
104 105
105/* simtec audio machine driver */ 106/* simtec audio machine driver */
106static struct snd_soc_card snd_soc_machine_simtec_aic33 = { 107static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
107 .name = "Simtec-Hermes", 108 .name = "Simtec-Hermes",
108 .platform = &s3c24xx_soc_platform,
109 .dai_link = &simtec_dai_aic33, 109 .dai_link = &simtec_dai_aic33,
110 .num_links = 1, 110 .num_links = 1,
111}; 111};
112 112
113/* simtec audio subsystem */
114static struct snd_soc_device simtec_snd_devdata_aic33 = {
115 .card = &snd_soc_machine_simtec_aic33,
116 .codec_dev = &soc_codec_dev_aic3x,
117 .codec_data = &codec_setup,
118};
119
120static int __devinit simtec_audio_hermes_probe(struct platform_device *pd) 113static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
121{ 114{
122 dev_info(&pd->dev, "probing....\n"); 115 dev_info(&pd->dev, "probing....\n");
123 return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic33); 116 return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic33);
124} 117}
125 118
126static struct platform_driver simtec_audio_hermes_platdrv = { 119static struct platform_driver simtec_audio_hermes_platdrv = {
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
index 185c0acb5ce6..c0967593510d 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
@@ -62,8 +62,10 @@ static const struct snd_soc_dapm_route base_map[] = {
62 * Attach our controls and configure the necessary codec 62 * Attach our controls and configure the necessary codec
63 * mappings for our sound card instance. 63 * mappings for our sound card instance.
64*/ 64*/
65static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) 65static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
66{ 66{
67 struct snd_soc_codec *codec = rtd->codec;
68
67 snd_soc_dapm_new_controls(codec, dapm_widgets, 69 snd_soc_dapm_new_controls(codec, dapm_widgets,
68 ARRAY_SIZE(dapm_widgets)); 70 ARRAY_SIZE(dapm_widgets));
69 71
@@ -74,7 +76,7 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)
74 snd_soc_dapm_enable_pin(codec, "Line Out"); 76 snd_soc_dapm_enable_pin(codec, "Line Out");
75 snd_soc_dapm_enable_pin(codec, "Mic Jack"); 77 snd_soc_dapm_enable_pin(codec, "Mic Jack");
76 78
77 simtec_audio_init(codec); 79 simtec_audio_init(rtd);
78 snd_soc_dapm_sync(codec); 80 snd_soc_dapm_sync(codec);
79 81
80 return 0; 82 return 0;
@@ -83,28 +85,23 @@ static int simtec_tlv320aic23_init(struct snd_soc_codec *codec)
83static struct snd_soc_dai_link simtec_dai_aic23 = { 85static struct snd_soc_dai_link simtec_dai_aic23 = {
84 .name = "tlv320aic23", 86 .name = "tlv320aic23",
85 .stream_name = "TLV320AIC23", 87 .stream_name = "TLV320AIC23",
86 .cpu_dai = &s3c24xx_i2s_dai, 88 .codec_name = "tlv320aic3x-codec.0-0x1a",
87 .codec_dai = &tlv320aic23_dai, 89 .cpu_dai_name = "s3c24xx-i2s",
90 .codec_dai_name = "tlv320aic3x-hifi",
91 .platform_name = "s3c24xx-pcm-audio",
88 .init = simtec_tlv320aic23_init, 92 .init = simtec_tlv320aic23_init,
89}; 93};
90 94
91/* simtec audio machine driver */ 95/* simtec audio machine driver */
92static struct snd_soc_card snd_soc_machine_simtec_aic23 = { 96static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
93 .name = "Simtec", 97 .name = "Simtec",
94 .platform = &s3c24xx_soc_platform,
95 .dai_link = &simtec_dai_aic23, 98 .dai_link = &simtec_dai_aic23,
96 .num_links = 1, 99 .num_links = 1,
97}; 100};
98 101
99/* simtec audio subsystem */
100static struct snd_soc_device simtec_snd_devdata_aic23 = {
101 .card = &snd_soc_machine_simtec_aic23,
102 .codec_dev = &soc_codec_dev_tlv320aic23,
103};
104
105static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd) 102static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
106{ 103{
107 return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic23); 104 return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
108} 105}
109 106
110static struct platform_driver simtec_audio_tlv320aic23_platdrv = { 107static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c
index 052d59659c29..bd48ffbde880 100644
--- a/sound/soc/s3c24xx/s3c24xx_uda134x.c
+++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c
@@ -133,8 +133,8 @@ static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
133 struct snd_pcm_hw_params *params) 133 struct snd_pcm_hw_params *params)
134{ 134{
135 struct snd_soc_pcm_runtime *rtd = substream->private_data; 135 struct snd_soc_pcm_runtime *rtd = substream->private_data;
136 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 136 struct snd_soc_dai *codec_dai = rtd->codec_dai;
137 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 137 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
138 unsigned int clk = 0; 138 unsigned int clk = 0;
139 int ret = 0; 139 int ret = 0;
140 int clk_source, fs_mode; 140 int clk_source, fs_mode;
@@ -227,14 +227,15 @@ static struct snd_soc_ops s3c24xx_uda134x_ops = {
227static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { 227static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
228 .name = "UDA134X", 228 .name = "UDA134X",
229 .stream_name = "UDA134X", 229 .stream_name = "UDA134X",
230 .codec_dai = &uda134x_dai, 230 .codec_name = "uda134x-hifi",
231 .cpu_dai = &s3c24xx_i2s_dai, 231 .codec_dai_name = "uda134x-hifi",
232 .cpu_dai_name = "s3c24xx-i2s",
232 .ops = &s3c24xx_uda134x_ops, 233 .ops = &s3c24xx_uda134x_ops,
234 .platform_name = "s3c24xx-pcm-audio",
233}; 235};
234 236
235static struct snd_soc_card snd_soc_s3c24xx_uda134x = { 237static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
236 .name = "S3C24XX_UDA134X", 238 .name = "S3C24XX_UDA134X",
237 .platform = &s3c24xx_soc_platform,
238 .dai_link = &s3c24xx_uda134x_dai_link, 239 .dai_link = &s3c24xx_uda134x_dai_link,
239 .num_links = 1, 240 .num_links = 1,
240}; 241};
@@ -256,6 +257,7 @@ static void setmode(int v)
256 gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0); 257 gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
257} 258}
258 259
260/* FIXME - This must be codec platform data but in which board file ?? */
259static struct uda134x_platform_data s3c24xx_uda134x = { 261static struct uda134x_platform_data s3c24xx_uda134x = {
260 .l3 = { 262 .l3 = {
261 .setdat = setdat, 263 .setdat = setdat,
@@ -270,12 +272,6 @@ static struct uda134x_platform_data s3c24xx_uda134x = {
270 }, 272 },
271}; 273};
272 274
273static struct snd_soc_device s3c24xx_uda134x_snd_devdata = {
274 .card = &snd_soc_s3c24xx_uda134x,
275 .codec_dev = &soc_codec_dev_uda134x,
276 .codec_data = &s3c24xx_uda134x,
277};
278
279static int s3c24xx_uda134x_setup_pin(int pin, char *fun) 275static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
280{ 276{
281 if (gpio_request(pin, "s3c24xx_uda134x") < 0) { 277 if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
@@ -325,8 +321,7 @@ static int s3c24xx_uda134x_probe(struct platform_device *pdev)
325 } 321 }
326 322
327 platform_set_drvdata(s3c24xx_uda134x_snd_device, 323 platform_set_drvdata(s3c24xx_uda134x_snd_device,
328 &s3c24xx_uda134x_snd_devdata); 324 &snd_soc_s3c24xx_uda134x);
329 s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev;
330 ret = platform_device_add(s3c24xx_uda134x_snd_device); 325 ret = platform_device_add(s3c24xx_uda134x_snd_device);
331 if (ret) { 326 if (ret) {
332 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); 327 printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
index 06db130030a1..a9628472ebfe 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s-v4.c
@@ -16,9 +16,7 @@
16#include <sound/soc.h> 16#include <sound/soc.h>
17#include <sound/pcm_params.h> 17#include <sound/pcm_params.h>
18 18
19#include <mach/gpio-bank-c.h> 19#include <plat/audio.h>
20#include <mach/gpio-bank-h.h>
21#include <plat/gpio-cfg.h>
22 20
23#include <mach/map.h> 21#include <mach/map.h>
24#include <mach/dma.h> 22#include <mach/dma.h>
@@ -39,34 +37,23 @@ static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_out;
39static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in; 37static struct s3c_dma_params s3c64xx_i2sv4_pcm_stereo_in;
40static struct s3c_i2sv2_info s3c64xx_i2sv4; 38static struct s3c_i2sv2_info s3c64xx_i2sv4;
41 39
42struct snd_soc_dai s3c64xx_i2s_v4_dai; 40static int s3c64xx_i2sv4_probe(struct snd_soc_dai *dai)
43EXPORT_SYMBOL_GPL(s3c64xx_i2s_v4_dai);
44
45static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
46{ 41{
47 return cpu_dai->private_data; 42 struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4;
48} 43 int ret = 0;
49 44
50static int s3c64xx_i2sv4_probe(struct platform_device *pdev, 45 snd_soc_dai_set_drvdata(dai, i2s);
51 struct snd_soc_dai *dai)
52{
53 /* configure GPIO for i2s port */
54 s3c_gpio_cfgpin(S3C64XX_GPC(4), S3C64XX_GPC4_I2S_V40_DO0);
55 s3c_gpio_cfgpin(S3C64XX_GPC(5), S3C64XX_GPC5_I2S_V40_DO1);
56 s3c_gpio_cfgpin(S3C64XX_GPC(7), S3C64XX_GPC7_I2S_V40_DO2);
57 s3c_gpio_cfgpin(S3C64XX_GPH(6), S3C64XX_GPH6_I2S_V40_BCLK);
58 s3c_gpio_cfgpin(S3C64XX_GPH(7), S3C64XX_GPH7_I2S_V40_CDCLK);
59 s3c_gpio_cfgpin(S3C64XX_GPH(8), S3C64XX_GPH8_I2S_V40_LRCLK);
60 s3c_gpio_cfgpin(S3C64XX_GPH(9), S3C64XX_GPH9_I2S_V40_DI);
61 46
62 return 0; 47 ret = s3c_i2sv2_probe(dai, i2s, i2s->base);
48
49 return ret;
63} 50}
64 51
65static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream, 52static int s3c_i2sv4_hw_params(struct snd_pcm_substream *substream,
66 struct snd_pcm_hw_params *params, 53 struct snd_pcm_hw_params *params,
67 struct snd_soc_dai *cpu_dai) 54 struct snd_soc_dai *cpu_dai)
68{ 55{
69 struct s3c_i2sv2_info *i2s = to_info(cpu_dai); 56 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(cpu_dai);
70 struct s3c_dma_params *dma_data; 57 struct s3c_dma_params *dma_data;
71 u32 iismod; 58 u32 iismod;
72 59
@@ -104,51 +91,79 @@ static struct snd_soc_dai_ops s3c64xx_i2sv4_dai_ops = {
104 .hw_params = s3c_i2sv4_hw_params, 91 .hw_params = s3c_i2sv4_hw_params,
105}; 92};
106 93
94static struct snd_soc_dai_driver s3c64xx_i2s_v4_dai = {
95 .symmetric_rates = 1,
96 .playback = {
97 .channels_min = 2,
98 .channels_max = 2,
99 .rates = S3C64XX_I2S_RATES,
100 .formats = S3C64XX_I2S_FMTS,
101 },
102 .capture = {
103 .channels_min = 2,
104 .channels_max = 2,
105 .rates = S3C64XX_I2S_RATES,
106 .formats = S3C64XX_I2S_FMTS,
107 },
108 .probe = s3c64xx_i2sv4_probe,
109 .ops = &s3c64xx_i2sv4_dai_ops,
110};
111
107static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev) 112static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)
108{ 113{
114 struct s3c_audio_pdata *i2s_pdata;
109 struct s3c_i2sv2_info *i2s; 115 struct s3c_i2sv2_info *i2s;
110 struct snd_soc_dai *dai; 116 struct resource *res;
111 int ret; 117 int ret;
112 118
113 i2s = &s3c64xx_i2sv4; 119 i2s = &s3c64xx_i2sv4;
114 dai = &s3c64xx_i2s_v4_dai;
115
116 if (dai->dev) {
117 dev_dbg(dai->dev, "%s: \
118 I2Sv4 instance already registered!\n", __func__);
119 return -EBUSY;
120 }
121
122 dai->dev = &pdev->dev;
123 dai->name = "s3c64xx-i2s-v4";
124 dai->id = 0;
125 dai->symmetric_rates = 1;
126 dai->playback.channels_min = 2;
127 dai->playback.channels_max = 2;
128 dai->playback.rates = S3C64XX_I2S_RATES;
129 dai->playback.formats = S3C64XX_I2S_FMTS;
130 dai->capture.channels_min = 2;
131 dai->capture.channels_max = 2;
132 dai->capture.rates = S3C64XX_I2S_RATES;
133 dai->capture.formats = S3C64XX_I2S_FMTS;
134 dai->probe = s3c64xx_i2sv4_probe;
135 dai->ops = &s3c64xx_i2sv4_dai_ops;
136 120
137 i2s->feature |= S3C_FEATURE_CDCLKCON; 121 i2s->feature |= S3C_FEATURE_CDCLKCON;
138 122
139 i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in; 123 i2s->dma_capture = &s3c64xx_i2sv4_pcm_stereo_in;
140 i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out; 124 i2s->dma_playback = &s3c64xx_i2sv4_pcm_stereo_out;
141 125
142 i2s->dma_capture->channel = DMACH_HSI_I2SV40_RX; 126 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
143 i2s->dma_capture->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISRXD; 127 if (!res) {
144 i2s->dma_playback->channel = DMACH_HSI_I2SV40_TX; 128 dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
145 i2s->dma_playback->dma_addr = S3C64XX_PA_IISV4 + S3C2412_IISTXD; 129 return -ENXIO;
130 }
131 i2s->dma_playback->channel = res->start;
132
133 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
134 if (!res) {
135 dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n");
136 return -ENXIO;
137 }
138 i2s->dma_capture->channel = res->start;
139
140 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
141 if (!res) {
142 dev_err(&pdev->dev, "Unable to get I2S SFR address\n");
143 return -ENXIO;
144 }
145
146 if (!request_mem_region(res->start, resource_size(res),
147 "s3c64xx-i2s-v4")) {
148 dev_err(&pdev->dev, "Unable to request SFR region\n");
149 return -EBUSY;
150 }
151 i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD;
152 i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD;
146 153
147 i2s->dma_capture->client = &s3c64xx_dma_client_in; 154 i2s->dma_capture->client = &s3c64xx_dma_client_in;
148 i2s->dma_capture->dma_size = 4; 155 i2s->dma_capture->dma_size = 4;
149 i2s->dma_playback->client = &s3c64xx_dma_client_out; 156 i2s->dma_playback->client = &s3c64xx_dma_client_out;
150 i2s->dma_playback->dma_size = 4; 157 i2s->dma_playback->dma_size = 4;
151 158
159 i2s->base = res->start;
160
161 i2s_pdata = pdev->dev.platform_data;
162 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
163 dev_err(&pdev->dev, "Unable to configure gpio\n");
164 return -EINVAL;
165 }
166
152 i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); 167 i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus");
153 if (IS_ERR(i2s->iis_cclk)) { 168 if (IS_ERR(i2s->iis_cclk)) {
154 dev_err(&pdev->dev, "failed to get audio-bus\n"); 169 dev_err(&pdev->dev, "failed to get audio-bus\n");
@@ -158,19 +173,13 @@ static __devinit int s3c64xx_i2sv4_dev_probe(struct platform_device *pdev)
158 173
159 clk_enable(i2s->iis_cclk); 174 clk_enable(i2s->iis_cclk);
160 175
161 ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); 176 ret = s3c_i2sv2_register_dai(&pdev->dev, pdev->id, &s3c64xx_i2s_v4_dai);
162 if (ret)
163 goto err_clk;
164
165 ret = s3c_i2sv2_register_dai(dai);
166 if (ret != 0) 177 if (ret != 0)
167 goto err_i2sv2; 178 goto err_i2sv2;
168 179
169 return 0; 180 return 0;
170 181
171err_i2sv2: 182err_i2sv2:
172 /* Not implemented for I2Sv2 core yet */
173err_clk:
174 clk_put(i2s->iis_cclk); 183 clk_put(i2s->iis_cclk);
175err: 184err:
176 return ret; 185 return ret;
@@ -178,7 +187,18 @@ err:
178 187
179static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev) 188static __devexit int s3c64xx_i2sv4_dev_remove(struct platform_device *pdev)
180{ 189{
181 dev_err(&pdev->dev, "Device removal not yet supported\n"); 190 struct s3c_i2sv2_info *i2s = &s3c64xx_i2sv4;
191 struct resource *res;
192
193 snd_soc_unregister_dai(&pdev->dev);
194 clk_put(i2s->iis_cclk);
195
196 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
197 if (res)
198 release_mem_region(res->start, resource_size(res));
199 else
200 dev_warn(&pdev->dev, "Unable to get I2S SFR address\n");
201
182 return 0; 202 return 0;
183} 203}
184 204
@@ -207,3 +227,4 @@ module_exit(s3c64xx_i2sv4_exit);
207MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>"); 227MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
208MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface"); 228MODULE_DESCRIPTION("S3C64XX I2Sv4 SoC Interface");
209MODULE_LICENSE("GPL"); 229MODULE_LICENSE("GPL");
230MODULE_ALIAS("platform:s3c64xx-iis-v4");
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index 1d85cb85a7d2..ae7acb6c4f1d 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -12,15 +12,15 @@
12 * published by the Free Software Foundation. 12 * published by the Free Software Foundation.
13 */ 13 */
14 14
15#include <linux/module.h>
15#include <linux/clk.h> 16#include <linux/clk.h>
16#include <linux/gpio.h> 17#include <linux/gpio.h>
17#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/slab.h>
18 20
19#include <sound/soc.h> 21#include <sound/soc.h>
20 22
21#include <mach/gpio-bank-d.h> 23#include <plat/audio.h>
22#include <mach/gpio-bank-e.h>
23#include <plat/gpio-cfg.h>
24 24
25#include <mach/map.h> 25#include <mach/map.h>
26#include <mach/dma.h> 26#include <mach/dma.h>
@@ -46,45 +46,107 @@ static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[MAX_I2SV3];
46static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3]; 46static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[MAX_I2SV3];
47static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3]; 47static struct s3c_i2sv2_info s3c64xx_i2s[MAX_I2SV3];
48 48
49struct snd_soc_dai s3c64xx_i2s_dai[MAX_I2SV3]; 49struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
50EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
51
52static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
53{ 50{
54 return cpu_dai->private_data; 51 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai);
52 u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
53
54 if (iismod & S3C2412_IISMOD_IMS_SYSMUX)
55 return i2s->iis_cclk;
56 else
57 return i2s->iis_pclk;
55} 58}
59EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
56 60
57static int s3c64xx_i2s_probe(struct platform_device *pdev, 61static int s3c64xx_i2s_probe(struct snd_soc_dai *dai)
58 struct snd_soc_dai *dai)
59{ 62{
60 /* configure GPIO for i2s port */ 63 struct s3c_i2sv2_info *i2s;
61 switch (dai->id) { 64 int ret;
62 case 0: 65
63 s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK); 66 if (dai->id >= MAX_I2SV3) {
64 s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK); 67 dev_err(dai->dev, "id %d out of range\n", dai->id);
65 s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK); 68 return -EINVAL;
66 s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI); 69 }
67 s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0); 70
68 break; 71 i2s = &s3c64xx_i2s[dai->id];
69 case 1: 72 snd_soc_dai_set_drvdata(dai, i2s);
70 s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK); 73
71 s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK); 74 i2s->iis_cclk = clk_get(dai->dev, "audio-bus");
72 s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK); 75 if (IS_ERR(i2s->iis_cclk)) {
73 s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI); 76 dev_err(dai->dev, "failed to get audio-bus\n");
74 s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0); 77 ret = PTR_ERR(i2s->iis_cclk);
78 goto err;
75 } 79 }
76 80
81 clk_enable(i2s->iis_cclk);
82
83 ret = s3c_i2sv2_probe(dai, i2s, i2s->base);
84 if (ret)
85 goto err_clk;
86
77 return 0; 87 return 0;
88
89err_clk:
90 clk_disable(i2s->iis_cclk);
91 clk_put(i2s->iis_cclk);
92err:
93 kfree(i2s);
94 return ret;
78} 95}
79 96
97static int s3c64xx_i2s_remove(struct snd_soc_dai *dai)
98{
99 struct s3c_i2sv2_info *i2s = snd_soc_dai_get_drvdata(dai);
100
101 clk_disable(i2s->iis_cclk);
102 clk_put(i2s->iis_cclk);
103 kfree(i2s);
104 return 0;
105}
80 106
81static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops; 107static struct snd_soc_dai_ops s3c64xx_i2s_dai_ops;
82 108
109static struct snd_soc_dai_driver s3c64xx_i2s_dai[MAX_I2SV3] = {
110{
111 .name = "s3c64xx-i2s-0",
112 .probe = s3c64xx_i2s_probe,
113 .remove = s3c64xx_i2s_remove,
114 .playback = {
115 .channels_min = 2,
116 .channels_max = 2,
117 .rates = S3C64XX_I2S_RATES,
118 .formats = S3C64XX_I2S_FMTS,},
119 .capture = {
120 .channels_min = 2,
121 .channels_max = 2,
122 .rates = S3C64XX_I2S_RATES,
123 .formats = S3C64XX_I2S_FMTS,},
124 .ops = &s3c64xx_i2s_dai_ops,
125 .symmetric_rates = 1,
126}, {
127 .name = "s3c64xx-i2s-1",
128 .probe = s3c64xx_i2s_probe,
129 .remove = s3c64xx_i2s_remove,
130 .playback = {
131 .channels_min = 2,
132 .channels_max = 2,
133 .rates = S3C64XX_I2S_RATES,
134 .formats = S3C64XX_I2S_FMTS,},
135 .capture = {
136 .channels_min = 2,
137 .channels_max = 2,
138 .rates = S3C64XX_I2S_RATES,
139 .formats = S3C64XX_I2S_FMTS,},
140 .ops = &s3c64xx_i2s_dai_ops,
141 .symmetric_rates = 1,
142},};
143
83static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev) 144static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
84{ 145{
146 struct s3c_audio_pdata *i2s_pdata;
85 struct s3c_i2sv2_info *i2s; 147 struct s3c_i2sv2_info *i2s;
86 struct snd_soc_dai *dai; 148 struct resource *res;
87 int ret; 149 int i, ret;
88 150
89 if (pdev->id >= MAX_I2SV3) { 151 if (pdev->id >= MAX_I2SV3) {
90 dev_err(&pdev->dev, "id %d out of range\n", pdev->id); 152 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
@@ -92,74 +154,63 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
92 } 154 }
93 155
94 i2s = &s3c64xx_i2s[pdev->id]; 156 i2s = &s3c64xx_i2s[pdev->id];
95 dai = &s3c64xx_i2s_dai[pdev->id];
96 dai->dev = &pdev->dev;
97 dai->name = "s3c64xx-i2s";
98 dai->id = pdev->id;
99 dai->symmetric_rates = 1;
100 dai->playback.channels_min = 2;
101 dai->playback.channels_max = 2;
102 dai->playback.rates = S3C64XX_I2S_RATES;
103 dai->playback.formats = S3C64XX_I2S_FMTS;
104 dai->capture.channels_min = 2;
105 dai->capture.channels_max = 2;
106 dai->capture.rates = S3C64XX_I2S_RATES;
107 dai->capture.formats = S3C64XX_I2S_FMTS;
108 dai->probe = s3c64xx_i2s_probe;
109 dai->ops = &s3c64xx_i2s_dai_ops;
110
111 i2s->feature |= S3C_FEATURE_CDCLKCON;
112 157
113 i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id]; 158 i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
114 i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id]; 159 i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
115 160
116 if (pdev->id == 0) { 161 res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
117 i2s->dma_capture->channel = DMACH_I2S0_IN; 162 if (!res) {
118 i2s->dma_capture->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD; 163 dev_err(&pdev->dev, "Unable to get I2S-TX dma resource\n");
119 i2s->dma_playback->channel = DMACH_I2S0_OUT; 164 return -ENXIO;
120 i2s->dma_playback->dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD; 165 }
121 } else { 166 i2s->dma_playback->channel = res->start;
122 i2s->dma_capture->channel = DMACH_I2S1_IN; 167
123 i2s->dma_capture->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD; 168 res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
124 i2s->dma_playback->channel = DMACH_I2S1_OUT; 169 if (!res) {
125 i2s->dma_playback->dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD; 170 dev_err(&pdev->dev, "Unable to get I2S-RX dma resource\n");
171 return -ENXIO;
172 }
173 i2s->dma_capture->channel = res->start;
174
175 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
176 if (!res) {
177 dev_err(&pdev->dev, "Unable to get I2S SFR address\n");
178 return -ENXIO;
126 } 179 }
127 180
181 if (!request_mem_region(res->start, resource_size(res),
182 "s3c64xx-i2s")) {
183 dev_err(&pdev->dev, "Unable to request SFR region\n");
184 return -EBUSY;
185 }
186 i2s->base = res->start;
187
188 i2s_pdata = pdev->dev.platform_data;
189 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
190 dev_err(&pdev->dev, "Unable to configure gpio\n");
191 return -EINVAL;
192 }
193 i2s->dma_capture->dma_addr = res->start + S3C2412_IISRXD;
194 i2s->dma_playback->dma_addr = res->start + S3C2412_IISTXD;
195
128 i2s->dma_capture->client = &s3c64xx_dma_client_in; 196 i2s->dma_capture->client = &s3c64xx_dma_client_in;
129 i2s->dma_capture->dma_size = 4; 197 i2s->dma_capture->dma_size = 4;
130 i2s->dma_playback->client = &s3c64xx_dma_client_out; 198 i2s->dma_playback->client = &s3c64xx_dma_client_out;
131 i2s->dma_playback->dma_size = 4; 199 i2s->dma_playback->dma_size = 4;
132 200
133 i2s->iis_cclk = clk_get(&pdev->dev, "audio-bus"); 201 for (i = 0; i < ARRAY_SIZE(s3c64xx_i2s_dai); i++) {
134 if (IS_ERR(i2s->iis_cclk)) { 202 ret = s3c_i2sv2_register_dai(&pdev->dev, i,
135 dev_err(&pdev->dev, "failed to get audio-bus\n"); 203 &s3c64xx_i2s_dai[i]);
136 ret = PTR_ERR(i2s->iis_cclk); 204 if (ret != 0)
137 goto err; 205 return ret;
138 } 206 }
139 207
140 clk_enable(i2s->iis_cclk);
141
142 ret = s3c_i2sv2_probe(pdev, dai, i2s, 0);
143 if (ret)
144 goto err_clk;
145
146 ret = s3c_i2sv2_register_dai(dai);
147 if (ret != 0)
148 goto err_i2sv2;
149
150 return 0; 208 return 0;
151
152err_i2sv2:
153 /* Not implemented for I2Sv2 core yet */
154err_clk:
155 clk_put(i2s->iis_cclk);
156err:
157 return ret;
158} 209}
159 210
160static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev) 211static __devexit int s3c64xx_iis_dev_remove(struct platform_device *pdev)
161{ 212{
162 dev_err(&pdev->dev, "Device removal not yet supported\n"); 213 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(s3c64xx_i2s_dai));
163 return 0; 214 return 0;
164} 215}
165 216
@@ -188,3 +239,4 @@ module_exit(s3c64xx_i2s_exit);
188MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 239MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
189MODULE_DESCRIPTION("S3C64XX I2S SoC Interface"); 240MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");
190MODULE_LICENSE("GPL"); 241MODULE_LICENSE("GPL");
242MODULE_ALIAS("platform:s3c64xx-iis");
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
index 7a40f43d1d51..de4075d26f0c 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -36,7 +36,6 @@ struct clk;
36 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ 36 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
37 SNDRV_PCM_FMTBIT_S24_LE) 37 SNDRV_PCM_FMTBIT_S24_LE)
38 38
39extern struct snd_soc_dai s3c64xx_i2s_dai[]; 39struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai);
40extern struct snd_soc_dai s3c64xx_i2s_v4_dai;
41 40
42#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */ 41#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */
diff --git a/sound/soc/s3c24xx/smartq_wm8987.c b/sound/soc/s3c24xx/smartq_wm8987.c
index b480348140b0..dd20ca7f4681 100644
--- a/sound/soc/s3c24xx/smartq_wm8987.c
+++ b/sound/soc/s3c24xx/smartq_wm8987.c
@@ -211,8 +211,10 @@ static struct snd_soc_dai_link smartq_dai[] = {
211 { 211 {
212 .name = "wm8987", 212 .name = "wm8987",
213 .stream_name = "SmartQ Hi-Fi", 213 .stream_name = "SmartQ Hi-Fi",
214 .cpu_dai = &s3c64xx_i2s_dai[0], 214 .cpu_dai_name = "s3c64xx-i2s.0",
215 .codec_dai = &wm8750_dai, 215 .codec_dai_name = "wm8750-hifi",
216 .platform_name = "s3c24xx-pcm-audio",
217 .codec_name = "wm8750-codec.0-0x1a",
216 .init = smartq_wm8987_init, 218 .init = smartq_wm8987_init,
217 .ops = &smartq_hifi_ops, 219 .ops = &smartq_hifi_ops,
218 }, 220 },
@@ -220,16 +222,10 @@ static struct snd_soc_dai_link smartq_dai[] = {
220 222
221static struct snd_soc_card snd_soc_smartq = { 223static struct snd_soc_card snd_soc_smartq = {
222 .name = "SmartQ", 224 .name = "SmartQ",
223 .platform = &s3c24xx_soc_platform,
224 .dai_link = smartq_dai, 225 .dai_link = smartq_dai,
225 .num_links = ARRAY_SIZE(smartq_dai), 226 .num_links = ARRAY_SIZE(smartq_dai),
226}; 227};
227 228
228static struct snd_soc_device smartq_snd_devdata = {
229 .card = &snd_soc_smartq,
230 .codec_dev = &soc_codec_dev_wm8750,
231};
232
233static struct platform_device *smartq_snd_device; 229static struct platform_device *smartq_snd_device;
234 230
235static int __init smartq_init(void) 231static int __init smartq_init(void)
@@ -245,8 +241,7 @@ static int __init smartq_init(void)
245 if (!smartq_snd_device) 241 if (!smartq_snd_device)
246 return -ENOMEM; 242 return -ENOMEM;
247 243
248 platform_set_drvdata(smartq_snd_device, &smartq_snd_devdata); 244 platform_set_drvdata(smartq_snd_device, &snd_soc_smartq);
249 smartq_snd_devdata.dev = &smartq_snd_device->dev;
250 245
251 ret = platform_device_add(smartq_snd_device); 246 ret = platform_device_add(smartq_snd_device);
252 if (ret) { 247 if (ret) {
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c
index 362258835e8d..4613288c2772 100644
--- a/sound/soc/s3c24xx/smdk2443_wm9710.c
+++ b/sound/soc/s3c24xx/smdk2443_wm9710.c
@@ -19,7 +19,6 @@
19#include <sound/soc.h> 19#include <sound/soc.h>
20#include <sound/soc-dapm.h> 20#include <sound/soc-dapm.h>
21 21
22#include "../codecs/ac97.h"
23#include "s3c-dma.h" 22#include "s3c-dma.h"
24#include "s3c-ac97.h" 23#include "s3c-ac97.h"
25 24
@@ -29,23 +28,19 @@ static struct snd_soc_dai_link smdk2443_dai[] = {
29{ 28{
30 .name = "AC97", 29 .name = "AC97",
31 .stream_name = "AC97 HiFi", 30 .stream_name = "AC97 HiFi",
32 .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], 31 .cpu_dai_name = "s3c-ac97",
33 .codec_dai = &ac97_dai, 32 .codec_dai_name = "ac97-hifi",
33 .codec_name = "ac97-codec",
34 .platform_name = "s3c24xx-pcm-audio",
34}, 35},
35}; 36};
36 37
37static struct snd_soc_card smdk2443 = { 38static struct snd_soc_card smdk2443 = {
38 .name = "SMDK2443", 39 .name = "SMDK2443",
39 .platform = &s3c24xx_soc_platform,
40 .dai_link = smdk2443_dai, 40 .dai_link = smdk2443_dai,
41 .num_links = ARRAY_SIZE(smdk2443_dai), 41 .num_links = ARRAY_SIZE(smdk2443_dai),
42}; 42};
43 43
44static struct snd_soc_device smdk2443_snd_ac97_devdata = {
45 .card = &smdk2443,
46 .codec_dev = &soc_codec_dev_ac97,
47};
48
49static struct platform_device *smdk2443_snd_ac97_device; 44static struct platform_device *smdk2443_snd_ac97_device;
50 45
51static int __init smdk2443_init(void) 46static int __init smdk2443_init(void)
@@ -56,9 +51,7 @@ static int __init smdk2443_init(void)
56 if (!smdk2443_snd_ac97_device) 51 if (!smdk2443_snd_ac97_device)
57 return -ENOMEM; 52 return -ENOMEM;
58 53
59 platform_set_drvdata(smdk2443_snd_ac97_device, 54 platform_set_drvdata(smdk2443_snd_ac97_device, &smdk2443);
60 &smdk2443_snd_ac97_devdata);
61 smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev;
62 ret = platform_device_add(smdk2443_snd_ac97_device); 55 ret = platform_device_add(smdk2443_snd_ac97_device);
63 56
64 if (ret) 57 if (ret)
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c
index 07e8e51d10d6..052e499b68d1 100644
--- a/sound/soc/s3c24xx/smdk64xx_wm8580.c
+++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c
@@ -22,6 +22,12 @@
22#include "s3c-dma.h" 22#include "s3c-dma.h"
23#include "s3c64xx-i2s.h" 23#include "s3c64xx-i2s.h"
24 24
25/*
26 * Default CFG switch settings to use this driver:
27 *
28 * SMDK6410: Set CFG1 1-3 Off, CFG2 1-4 On
29 */
30
25/* SMDK64XX has a 12MHZ crystal attached to WM8580 */ 31/* SMDK64XX has a 12MHZ crystal attached to WM8580 */
26#define SMDK64XX_WM8580_FREQ 12000000 32#define SMDK64XX_WM8580_FREQ 12000000
27 33
@@ -29,8 +35,8 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
29 struct snd_pcm_hw_params *params) 35 struct snd_pcm_hw_params *params)
30{ 36{
31 struct snd_soc_pcm_runtime *rtd = substream->private_data; 37 struct snd_soc_pcm_runtime *rtd = substream->private_data;
32 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 38 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
33 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 39 struct snd_soc_dai *codec_dai = rtd->codec_dai;
34 unsigned int pll_out; 40 unsigned int pll_out;
35 int bfs, rfs, ret; 41 int bfs, rfs, ret;
36 42
@@ -107,14 +113,13 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
107 if (ret < 0) 113 if (ret < 0)
108 return ret; 114 return ret;
109 115
110 /* Explicitly set WM8580-DAC to source from MCLK */ 116 ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
111 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_DAC_CLKSEL, 117 SMDK64XX_WM8580_FREQ, pll_out);
112 WM8580_CLKSRC_MCLK);
113 if (ret < 0) 118 if (ret < 0)
114 return ret; 119 return ret;
115 120
116 ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0, 121 ret = snd_soc_dai_set_sysclk(codec_dai, WM8580_CLKSRC_PLLA,
117 SMDK64XX_WM8580_FREQ, pll_out); 122 pll_out, SND_SOC_CLOCK_IN);
118 if (ret < 0) 123 if (ret < 0)
119 return ret; 124 return ret;
120 125
@@ -138,9 +143,9 @@ static struct snd_soc_ops smdk64xx_ops = {
138 143
139/* SMDK64xx Playback widgets */ 144/* SMDK64xx Playback widgets */
140static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = { 145static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
141 SND_SOC_DAPM_HP("Front-L/R", NULL), 146 SND_SOC_DAPM_HP("Front", NULL),
142 SND_SOC_DAPM_HP("Center/Sub", NULL), 147 SND_SOC_DAPM_HP("Center+Sub", NULL),
143 SND_SOC_DAPM_HP("Rear-L/R", NULL), 148 SND_SOC_DAPM_HP("Rear", NULL),
144}; 149};
145 150
146/* SMDK64xx Capture widgets */ 151/* SMDK64xx Capture widgets */
@@ -162,20 +167,22 @@ static const struct snd_soc_dapm_route audio_map_tx[] = {
162/* SMDK-PAIFRX connections */ 167/* SMDK-PAIFRX connections */
163static const struct snd_soc_dapm_route audio_map_rx[] = { 168static const struct snd_soc_dapm_route audio_map_rx[] = {
164 /* Front Left/Right are fed VOUT1L/R */ 169 /* Front Left/Right are fed VOUT1L/R */
165 {"Front-L/R", NULL, "VOUT1L"}, 170 {"Front", NULL, "VOUT1L"},
166 {"Front-L/R", NULL, "VOUT1R"}, 171 {"Front", NULL, "VOUT1R"},
167 172
168 /* Center/Sub are fed VOUT2L/R */ 173 /* Center/Sub are fed VOUT2L/R */
169 {"Center/Sub", NULL, "VOUT2L"}, 174 {"Center+Sub", NULL, "VOUT2L"},
170 {"Center/Sub", NULL, "VOUT2R"}, 175 {"Center+Sub", NULL, "VOUT2R"},
171 176
172 /* Rear Left/Right are fed VOUT3L/R */ 177 /* Rear Left/Right are fed VOUT3L/R */
173 {"Rear-L/R", NULL, "VOUT3L"}, 178 {"Rear", NULL, "VOUT3L"},
174 {"Rear-L/R", NULL, "VOUT3R"}, 179 {"Rear", NULL, "VOUT3R"},
175}; 180};
176 181
177static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec) 182static int smdk64xx_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
178{ 183{
184 struct snd_soc_codec *codec = rtd->codec;
185
179 /* Add smdk64xx specific Capture widgets */ 186 /* Add smdk64xx specific Capture widgets */
180 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt, 187 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt,
181 ARRAY_SIZE(wm8580_dapm_widgets_cpt)); 188 ARRAY_SIZE(wm8580_dapm_widgets_cpt));
@@ -194,8 +201,10 @@ static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec)
194 return 0; 201 return 0;
195} 202}
196 203
197static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec) 204static int smdk64xx_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd)
198{ 205{
206 struct snd_soc_codec *codec = rtd->codec;
207
199 /* Add smdk64xx specific Playback widgets */ 208 /* Add smdk64xx specific Playback widgets */
200 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk, 209 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk,
201 ARRAY_SIZE(wm8580_dapm_widgets_pbk)); 210 ARRAY_SIZE(wm8580_dapm_widgets_pbk));
@@ -213,33 +222,31 @@ static struct snd_soc_dai_link smdk64xx_dai[] = {
213{ /* Primary Playback i/f */ 222{ /* Primary Playback i/f */
214 .name = "WM8580 PAIF RX", 223 .name = "WM8580 PAIF RX",
215 .stream_name = "Playback", 224 .stream_name = "Playback",
216 .cpu_dai = &s3c64xx_i2s_v4_dai, 225 .cpu_dai_name = "s3c64xx-iis-v4",
217 .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX], 226 .codec_dai_name = "wm8580-hifi-playback",
227 .platform_name = "s3c24xx-pcm-audio",
228 .codec_name = "wm8580-codec.0-001b",
218 .init = smdk64xx_wm8580_init_paifrx, 229 .init = smdk64xx_wm8580_init_paifrx,
219 .ops = &smdk64xx_ops, 230 .ops = &smdk64xx_ops,
220}, 231},
221{ /* Primary Capture i/f */ 232{ /* Primary Capture i/f */
222 .name = "WM8580 PAIF TX", 233 .name = "WM8580 PAIF TX",
223 .stream_name = "Capture", 234 .stream_name = "Capture",
224 .cpu_dai = &s3c64xx_i2s_v4_dai, 235 .cpu_dai_name = "s3c64xx-iis-v4",
225 .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX], 236 .codec_dai_name = "wm8580-hifi-capture",
237 .platform_name = "s3c24xx-pcm-audio",
238 .codec_name = "wm8580-codec.0-001b",
226 .init = smdk64xx_wm8580_init_paiftx, 239 .init = smdk64xx_wm8580_init_paiftx,
227 .ops = &smdk64xx_ops, 240 .ops = &smdk64xx_ops,
228}, 241},
229}; 242};
230 243
231static struct snd_soc_card smdk64xx = { 244static struct snd_soc_card smdk64xx = {
232 .name = "smdk64xx", 245 .name = "SMDK64xx 5.1",
233 .platform = &s3c24xx_soc_platform,
234 .dai_link = smdk64xx_dai, 246 .dai_link = smdk64xx_dai,
235 .num_links = ARRAY_SIZE(smdk64xx_dai), 247 .num_links = ARRAY_SIZE(smdk64xx_dai),
236}; 248};
237 249
238static struct snd_soc_device smdk64xx_snd_devdata = {
239 .card = &smdk64xx,
240 .codec_dev = &soc_codec_dev_wm8580,
241};
242
243static struct platform_device *smdk64xx_snd_device; 250static struct platform_device *smdk64xx_snd_device;
244 251
245static int __init smdk64xx_audio_init(void) 252static int __init smdk64xx_audio_init(void)
@@ -250,8 +257,7 @@ static int __init smdk64xx_audio_init(void)
250 if (!smdk64xx_snd_device) 257 if (!smdk64xx_snd_device)
251 return -ENOMEM; 258 return -ENOMEM;
252 259
253 platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata); 260 platform_set_drvdata(smdk64xx_snd_device, &smdk64xx);
254 smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev;
255 ret = platform_device_add(smdk64xx_snd_device); 261 ret = platform_device_add(smdk64xx_snd_device);
256 262
257 if (ret) 263 if (ret)
diff --git a/sound/soc/s3c24xx/smdk_spdif.c b/sound/soc/s3c24xx/smdk_spdif.c
new file mode 100644
index 000000000000..f31d22ad7c88
--- /dev/null
+++ b/sound/soc/s3c24xx/smdk_spdif.c
@@ -0,0 +1,223 @@
1/*
2 * smdk_spdif.c -- S/PDIF audio for SMDK
3 *
4 * Copyright 2010 Samsung Electronics Co. Ltd.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 */
12
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/clk.h>
16
17#include <plat/devs.h>
18
19#include <sound/soc.h>
20
21#include "s3c-dma.h"
22#include "spdif.h"
23
24/* Audio clock settings are belonged to board specific part. Every
25 * board can set audio source clock setting which is matched with H/W
26 * like this function-'set_audio_clock_heirachy'.
27 */
28static int set_audio_clock_heirachy(struct platform_device *pdev)
29{
30 struct clk *fout_epll, *mout_epll, *sclk_audio0, *sclk_spdif;
31 int ret;
32
33 fout_epll = clk_get(NULL, "fout_epll");
34 if (IS_ERR(fout_epll)) {
35 printk(KERN_WARNING "%s: Cannot find fout_epll.\n",
36 __func__);
37 return -EINVAL;
38 }
39
40 mout_epll = clk_get(NULL, "mout_epll");
41 if (IS_ERR(fout_epll)) {
42 printk(KERN_WARNING "%s: Cannot find mout_epll.\n",
43 __func__);
44 ret = -EINVAL;
45 goto out1;
46 }
47
48 sclk_audio0 = clk_get(&pdev->dev, "sclk_audio");
49 if (IS_ERR(sclk_audio0)) {
50 printk(KERN_WARNING "%s: Cannot find sclk_audio.\n",
51 __func__);
52 ret = -EINVAL;
53 goto out2;
54 }
55
56 sclk_spdif = clk_get(NULL, "sclk_spdif");
57 if (IS_ERR(fout_epll)) {
58 printk(KERN_WARNING "%s: Cannot find sclk_spdif.\n",
59 __func__);
60 ret = -EINVAL;
61 goto out3;
62 }
63
64 /* Set audio clock heirachy for S/PDIF */
65 clk_set_parent(mout_epll, fout_epll);
66 clk_set_parent(sclk_audio0, mout_epll);
67 clk_set_parent(sclk_spdif, sclk_audio0);
68
69 clk_put(sclk_spdif);
70out3:
71 clk_put(sclk_audio0);
72out2:
73 clk_put(mout_epll);
74out1:
75 clk_put(fout_epll);
76
77 return ret;
78}
79
80/* We should haved to set clock directly on this part because of clock
81 * scheme of Samsudng SoCs did not support to set rates from abstrct
82 * clock of it's heirachy.
83 */
84static int set_audio_clock_rate(unsigned long epll_rate,
85 unsigned long audio_rate)
86{
87 struct clk *fout_epll, *sclk_spdif;
88
89 fout_epll = clk_get(NULL, "fout_epll");
90 if (IS_ERR(fout_epll)) {
91 printk(KERN_ERR "%s: failed to get fout_epll\n", __func__);
92 return -ENOENT;
93 }
94
95 clk_set_rate(fout_epll, epll_rate);
96 clk_put(fout_epll);
97
98 sclk_spdif = clk_get(NULL, "sclk_spdif");
99 if (IS_ERR(sclk_spdif)) {
100 printk(KERN_ERR "%s: failed to get sclk_spdif\n", __func__);
101 return -ENOENT;
102 }
103
104 clk_set_rate(sclk_spdif, audio_rate);
105 clk_put(sclk_spdif);
106
107 return 0;
108}
109
110static int smdk_hw_params(struct snd_pcm_substream *substream,
111 struct snd_pcm_hw_params *params)
112{
113 struct snd_soc_pcm_runtime *rtd = substream->private_data;
114 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
115 unsigned long pll_out, rclk_rate;
116 int ret, ratio;
117
118 switch (params_rate(params)) {
119 case 44100:
120 pll_out = 45158400;
121 break;
122 case 32000:
123 case 48000:
124 case 96000:
125 pll_out = 49152000;
126 break;
127 default:
128 return -EINVAL;
129 }
130
131 /* Setting ratio to 512fs helps to use S/PDIF with HDMI without
132 * modify S/PDIF ASoC machine driver.
133 */
134 ratio = 512;
135 rclk_rate = params_rate(params) * ratio;
136
137 /* Set audio source clock rates */
138 ret = set_audio_clock_rate(pll_out, rclk_rate);
139 if (ret < 0)
140 return ret;
141
142 /* Set S/PDIF uses internal source clock */
143 ret = snd_soc_dai_set_sysclk(cpu_dai, SND_SOC_SPDIF_INT_MCLK,
144 rclk_rate, SND_SOC_CLOCK_IN);
145 if (ret < 0)
146 return ret;
147
148 return ret;
149}
150
151static struct snd_soc_ops smdk_spdif_ops = {
152 .hw_params = smdk_hw_params,
153};
154
155static struct snd_soc_card smdk;
156
157static struct snd_soc_dai_link smdk_dai = {
158 .name = "S/PDIF",
159 .stream_name = "S/PDIF PCM Playback",
160 .platform_name = "s3c24xx-pcm-audio",
161 .cpu_dai_name = "samsung-spdif",
162 .codec_dai_name = "dit-hifi",
163 .codec_name = "spdif-dit",
164 .ops = &smdk_spdif_ops,
165};
166
167static struct snd_soc_card smdk = {
168 .name = "SMDK-S/PDIF",
169 .dai_link = &smdk_dai,
170 .num_links = 1,
171};
172
173static struct platform_device *smdk_snd_spdif_dit_device;
174static struct platform_device *smdk_snd_spdif_device;
175
176static int __init smdk_init(void)
177{
178 int ret;
179
180 smdk_snd_spdif_dit_device = platform_device_alloc("spdif-dit", -1);
181 if (!smdk_snd_spdif_dit_device)
182 return -ENOMEM;
183
184 ret = platform_device_add(smdk_snd_spdif_dit_device);
185 if (ret)
186 goto err2;
187
188 smdk_snd_spdif_device = platform_device_alloc("soc-audio", -1);
189 if (!smdk_snd_spdif_device) {
190 ret = -ENOMEM;
191 goto err2;
192 }
193
194 platform_set_drvdata(smdk_snd_spdif_device, &smdk);
195
196 ret = platform_device_add(smdk_snd_spdif_device);
197 if (ret)
198 goto err1;
199
200 /* Set audio clock heirachy manually */
201 ret = set_audio_clock_heirachy(smdk_snd_spdif_device);
202 if (ret)
203 goto err1;
204
205 return 0;
206err1:
207 platform_device_put(smdk_snd_spdif_device);
208err2:
209 platform_device_put(smdk_snd_spdif_dit_device);
210 return ret;
211}
212
213static void __exit smdk_exit(void)
214{
215 platform_device_unregister(smdk_snd_spdif_device);
216}
217
218module_init(smdk_init);
219module_exit(smdk_exit);
220
221MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
222MODULE_DESCRIPTION("ALSA SoC SMDK+S/PDIF");
223MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk_wm9713.c b/sound/soc/s3c24xx/smdk_wm9713.c
index 5527b9e88c98..33ba8fdbcf07 100644
--- a/sound/soc/s3c24xx/smdk_wm9713.c
+++ b/sound/soc/s3c24xx/smdk_wm9713.c
@@ -15,7 +15,6 @@
15#include <linux/device.h> 15#include <linux/device.h>
16#include <sound/soc.h> 16#include <sound/soc.h>
17 17
18#include "../codecs/wm9713.h"
19#include "s3c-dma.h" 18#include "s3c-dma.h"
20#include "s3c-ac97.h" 19#include "s3c-ac97.h"
21 20
@@ -46,46 +45,57 @@ static struct snd_soc_card smdk;
46static struct snd_soc_dai_link smdk_dai = { 45static struct snd_soc_dai_link smdk_dai = {
47 .name = "AC97", 46 .name = "AC97",
48 .stream_name = "AC97 PCM", 47 .stream_name = "AC97 PCM",
49 .cpu_dai = &s3c_ac97_dai[S3C_AC97_DAI_PCM], 48 .platform_name = "s3c24xx-pcm-audio",
50 .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], 49 .cpu_dai_name = "s3c-ac97",
50 .codec_dai_name = "wm9713-hifi",
51 .codec_name = "wm9713-codec",
51}; 52};
52 53
53static struct snd_soc_card smdk = { 54static struct snd_soc_card smdk = {
54 .name = "SMDK", 55 .name = "SMDK WM9713",
55 .platform = &s3c24xx_soc_platform,
56 .dai_link = &smdk_dai, 56 .dai_link = &smdk_dai,
57 .num_links = 1, 57 .num_links = 1,
58}; 58};
59 59
60static struct snd_soc_device smdk_snd_ac97_devdata = { 60static struct platform_device *smdk_snd_wm9713_device;
61 .card = &smdk,
62 .codec_dev = &soc_codec_dev_wm9713,
63};
64
65static struct platform_device *smdk_snd_ac97_device; 61static struct platform_device *smdk_snd_ac97_device;
66 62
67static int __init smdk_init(void) 63static int __init smdk_init(void)
68{ 64{
69 int ret; 65 int ret;
70 66
71 smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1); 67 smdk_snd_wm9713_device = platform_device_alloc("wm9713-codec", -1);
72 if (!smdk_snd_ac97_device) 68 if (!smdk_snd_wm9713_device)
73 return -ENOMEM; 69 return -ENOMEM;
74 70
75 platform_set_drvdata(smdk_snd_ac97_device, 71 ret = platform_device_add(smdk_snd_wm9713_device);
76 &smdk_snd_ac97_devdata); 72 if (ret)
77 smdk_snd_ac97_devdata.dev = &smdk_snd_ac97_device->dev; 73 goto err;
74
75 smdk_snd_ac97_device = platform_device_alloc("soc-audio", -1);
76 if (!smdk_snd_ac97_device) {
77 ret = -ENOMEM;
78 goto err;
79 }
80
81 platform_set_drvdata(smdk_snd_ac97_device, &smdk);
78 82
79 ret = platform_device_add(smdk_snd_ac97_device); 83 ret = platform_device_add(smdk_snd_ac97_device);
80 if (ret) 84 if (ret) {
81 platform_device_put(smdk_snd_ac97_device); 85 platform_device_put(smdk_snd_ac97_device);
86 goto err;
87 }
82 88
89 return 0;
90err:
91 platform_device_put(smdk_snd_wm9713_device);
83 return ret; 92 return ret;
84} 93}
85 94
86static void __exit smdk_exit(void) 95static void __exit smdk_exit(void)
87{ 96{
88 platform_device_unregister(smdk_snd_ac97_device); 97 platform_device_unregister(smdk_snd_ac97_device);
98 platform_device_unregister(smdk_snd_wm9713_device);
89} 99}
90 100
91module_init(smdk_init); 101module_init(smdk_init);
diff --git a/sound/soc/s3c24xx/spdif.c b/sound/soc/s3c24xx/spdif.c
new file mode 100644
index 000000000000..ce554e9cabcc
--- /dev/null
+++ b/sound/soc/s3c24xx/spdif.c
@@ -0,0 +1,501 @@
1/* sound/soc/s3c24xx/spdif.c
2 *
3 * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver
4 *
5 * Copyright (c) 2010 Samsung Electronics Co. Ltd
6 * http://www.samsung.com/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/clk.h>
14#include <linux/io.h>
15
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19
20#include <plat/audio.h>
21#include <mach/dma.h>
22
23#include "s3c-dma.h"
24#include "spdif.h"
25
26/* Registers */
27#define CLKCON 0x00
28#define CON 0x04
29#define BSTAS 0x08
30#define CSTAS 0x0C
31#define DATA_OUTBUF 0x10
32#define DCNT 0x14
33#define BSTAS_S 0x18
34#define DCNT_S 0x1C
35
36#define CLKCTL_MASK 0x7
37#define CLKCTL_MCLK_EXT (0x1 << 2)
38#define CLKCTL_PWR_ON (0x1 << 0)
39
40#define CON_MASK 0x3ffffff
41#define CON_FIFO_TH_SHIFT 19
42#define CON_FIFO_TH_MASK (0x7 << 19)
43#define CON_USERDATA_23RDBIT (0x1 << 12)
44
45#define CON_SW_RESET (0x1 << 5)
46
47#define CON_MCLKDIV_MASK (0x3 << 3)
48#define CON_MCLKDIV_256FS (0x0 << 3)
49#define CON_MCLKDIV_384FS (0x1 << 3)
50#define CON_MCLKDIV_512FS (0x2 << 3)
51
52#define CON_PCM_MASK (0x3 << 1)
53#define CON_PCM_16BIT (0x0 << 1)
54#define CON_PCM_20BIT (0x1 << 1)
55#define CON_PCM_24BIT (0x2 << 1)
56
57#define CON_PCM_DATA (0x1 << 0)
58
59#define CSTAS_MASK 0x3fffffff
60#define CSTAS_SAMP_FREQ_MASK (0xF << 24)
61#define CSTAS_SAMP_FREQ_44 (0x0 << 24)
62#define CSTAS_SAMP_FREQ_48 (0x2 << 24)
63#define CSTAS_SAMP_FREQ_32 (0x3 << 24)
64#define CSTAS_SAMP_FREQ_96 (0xA << 24)
65
66#define CSTAS_CATEGORY_MASK (0xFF << 8)
67#define CSTAS_CATEGORY_CODE_CDP (0x01 << 8)
68
69#define CSTAS_NO_COPYRIGHT (0x1 << 2)
70
71/**
72 * struct samsung_spdif_info - Samsung S/PDIF Controller information
73 * @lock: Spin lock for S/PDIF.
74 * @dev: The parent device passed to use from the probe.
75 * @regs: The pointer to the device register block.
76 * @clk_rate: Current clock rate for calcurate ratio.
77 * @pclk: The peri-clock pointer for spdif master operation.
78 * @sclk: The source clock pointer for making sync signals.
79 * @save_clkcon: Backup clkcon reg. in suspend.
80 * @save_con: Backup con reg. in suspend.
81 * @save_cstas: Backup cstas reg. in suspend.
82 * @dma_playback: DMA information for playback channel.
83 */
84struct samsung_spdif_info {
85 spinlock_t lock;
86 struct device *dev;
87 void __iomem *regs;
88 unsigned long clk_rate;
89 struct clk *pclk;
90 struct clk *sclk;
91 u32 saved_clkcon;
92 u32 saved_con;
93 u32 saved_cstas;
94 struct s3c_dma_params *dma_playback;
95};
96
97static struct s3c2410_dma_client spdif_dma_client_out = {
98 .name = "S/PDIF Stereo out",
99};
100
101static struct s3c_dma_params spdif_stereo_out;
102static struct samsung_spdif_info spdif_info;
103
104static inline struct samsung_spdif_info *to_info(struct snd_soc_dai *cpu_dai)
105{
106 return snd_soc_dai_get_drvdata(cpu_dai);
107}
108
109static void spdif_snd_txctrl(struct samsung_spdif_info *spdif, int on)
110{
111 void __iomem *regs = spdif->regs;
112 u32 clkcon;
113
114 dev_dbg(spdif->dev, "Entered %s\n", __func__);
115
116 clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
117 if (on)
118 writel(clkcon | CLKCTL_PWR_ON, regs + CLKCON);
119 else
120 writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON);
121}
122
123static int spdif_set_sysclk(struct snd_soc_dai *cpu_dai,
124 int clk_id, unsigned int freq, int dir)
125{
126 struct samsung_spdif_info *spdif = to_info(cpu_dai);
127 u32 clkcon;
128
129 dev_dbg(spdif->dev, "Entered %s\n", __func__);
130
131 clkcon = readl(spdif->regs + CLKCON);
132
133 if (clk_id == SND_SOC_SPDIF_INT_MCLK)
134 clkcon &= ~CLKCTL_MCLK_EXT;
135 else
136 clkcon |= CLKCTL_MCLK_EXT;
137
138 writel(clkcon, spdif->regs + CLKCON);
139
140 spdif->clk_rate = freq;
141
142 return 0;
143}
144
145static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
146 struct snd_soc_dai *dai)
147{
148 struct snd_soc_pcm_runtime *rtd = substream->private_data;
149 struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
150 unsigned long flags;
151
152 dev_dbg(spdif->dev, "Entered %s\n", __func__);
153
154 switch (cmd) {
155 case SNDRV_PCM_TRIGGER_START:
156 case SNDRV_PCM_TRIGGER_RESUME:
157 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
158 spin_lock_irqsave(&spdif->lock, flags);
159 spdif_snd_txctrl(spdif, 1);
160 spin_unlock_irqrestore(&spdif->lock, flags);
161 break;
162 case SNDRV_PCM_TRIGGER_STOP:
163 case SNDRV_PCM_TRIGGER_SUSPEND:
164 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
165 spin_lock_irqsave(&spdif->lock, flags);
166 spdif_snd_txctrl(spdif, 0);
167 spin_unlock_irqrestore(&spdif->lock, flags);
168 break;
169 default:
170 return -EINVAL;
171 }
172
173 return 0;
174}
175
176static int spdif_sysclk_ratios[] = {
177 512, 384, 256,
178};
179
180static int spdif_hw_params(struct snd_pcm_substream *substream,
181 struct snd_pcm_hw_params *params,
182 struct snd_soc_dai *socdai)
183{
184 struct snd_soc_pcm_runtime *rtd = substream->private_data;
185 struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
186 void __iomem *regs = spdif->regs;
187 struct s3c_dma_params *dma_data;
188 u32 con, clkcon, cstas;
189 unsigned long flags;
190 int i, ratio;
191
192 dev_dbg(spdif->dev, "Entered %s\n", __func__);
193
194 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
195 dma_data = spdif->dma_playback;
196 else {
197 dev_err(spdif->dev, "Capture is not supported\n");
198 return -EINVAL;
199 }
200
201 snd_soc_dai_set_dma_data(rtd->cpu_dai, substream, dma_data);
202
203 spin_lock_irqsave(&spdif->lock, flags);
204
205 con = readl(regs + CON) & CON_MASK;
206 cstas = readl(regs + CSTAS) & CSTAS_MASK;
207 clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
208
209 con &= ~CON_FIFO_TH_MASK;
210 con |= (0x7 << CON_FIFO_TH_SHIFT);
211 con |= CON_USERDATA_23RDBIT;
212 con |= CON_PCM_DATA;
213
214 con &= ~CON_PCM_MASK;
215 switch (params_format(params)) {
216 case SNDRV_PCM_FORMAT_S16_LE:
217 con |= CON_PCM_16BIT;
218 break;
219 default:
220 dev_err(spdif->dev, "Unsupported data size.\n");
221 goto err;
222 }
223
224 ratio = spdif->clk_rate / params_rate(params);
225 for (i = 0; i < ARRAY_SIZE(spdif_sysclk_ratios); i++)
226 if (ratio == spdif_sysclk_ratios[i])
227 break;
228 if (i == ARRAY_SIZE(spdif_sysclk_ratios)) {
229 dev_err(spdif->dev, "Invalid clock ratio %ld/%d\n",
230 spdif->clk_rate, params_rate(params));
231 goto err;
232 }
233
234 con &= ~CON_MCLKDIV_MASK;
235 switch (ratio) {
236 case 256:
237 con |= CON_MCLKDIV_256FS;
238 break;
239 case 384:
240 con |= CON_MCLKDIV_384FS;
241 break;
242 case 512:
243 con |= CON_MCLKDIV_512FS;
244 break;
245 }
246
247 cstas &= ~CSTAS_SAMP_FREQ_MASK;
248 switch (params_rate(params)) {
249 case 44100:
250 cstas |= CSTAS_SAMP_FREQ_44;
251 break;
252 case 48000:
253 cstas |= CSTAS_SAMP_FREQ_48;
254 break;
255 case 32000:
256 cstas |= CSTAS_SAMP_FREQ_32;
257 break;
258 case 96000:
259 cstas |= CSTAS_SAMP_FREQ_96;
260 break;
261 default:
262 dev_err(spdif->dev, "Invalid sampling rate %d\n",
263 params_rate(params));
264 goto err;
265 }
266
267 cstas &= ~CSTAS_CATEGORY_MASK;
268 cstas |= CSTAS_CATEGORY_CODE_CDP;
269 cstas |= CSTAS_NO_COPYRIGHT;
270
271 writel(con, regs + CON);
272 writel(cstas, regs + CSTAS);
273 writel(clkcon, regs + CLKCON);
274
275 spin_unlock_irqrestore(&spdif->lock, flags);
276
277 return 0;
278err:
279 spin_unlock_irqrestore(&spdif->lock, flags);
280 return -EINVAL;
281}
282
283static void spdif_shutdown(struct snd_pcm_substream *substream,
284 struct snd_soc_dai *dai)
285{
286 struct snd_soc_pcm_runtime *rtd = substream->private_data;
287 struct samsung_spdif_info *spdif = to_info(rtd->cpu_dai);
288 void __iomem *regs = spdif->regs;
289 u32 con, clkcon;
290
291 dev_dbg(spdif->dev, "Entered %s\n", __func__);
292
293 con = readl(regs + CON) & CON_MASK;
294 clkcon = readl(regs + CLKCON) & CLKCTL_MASK;
295
296 writel(con | CON_SW_RESET, regs + CON);
297 cpu_relax();
298
299 writel(clkcon & ~CLKCTL_PWR_ON, regs + CLKCON);
300}
301
302#ifdef CONFIG_PM
303static int spdif_suspend(struct snd_soc_dai *cpu_dai)
304{
305 struct samsung_spdif_info *spdif = to_info(cpu_dai);
306 u32 con = spdif->saved_con;
307
308 dev_dbg(spdif->dev, "Entered %s\n", __func__);
309
310 spdif->saved_clkcon = readl(spdif->regs + CLKCON) & CLKCTL_MASK;
311 spdif->saved_con = readl(spdif->regs + CON) & CON_MASK;
312 spdif->saved_cstas = readl(spdif->regs + CSTAS) & CSTAS_MASK;
313
314 writel(con | CON_SW_RESET, spdif->regs + CON);
315 cpu_relax();
316
317 return 0;
318}
319
320static int spdif_resume(struct snd_soc_dai *cpu_dai)
321{
322 struct samsung_spdif_info *spdif = to_info(cpu_dai);
323
324 dev_dbg(spdif->dev, "Entered %s\n", __func__);
325
326 writel(spdif->saved_clkcon, spdif->regs + CLKCON);
327 writel(spdif->saved_con, spdif->regs + CON);
328 writel(spdif->saved_cstas, spdif->regs + CSTAS);
329
330 return 0;
331}
332#else
333#define spdif_suspend NULL
334#define spdif_resume NULL
335#endif
336
337static struct snd_soc_dai_ops spdif_dai_ops = {
338 .set_sysclk = spdif_set_sysclk,
339 .trigger = spdif_trigger,
340 .hw_params = spdif_hw_params,
341 .shutdown = spdif_shutdown,
342};
343
344struct snd_soc_dai_driver samsung_spdif_dai = {
345 .name = "samsung-spdif",
346 .playback = {
347 .stream_name = "S/PDIF Playback",
348 .channels_min = 2,
349 .channels_max = 2,
350 .rates = (SNDRV_PCM_RATE_32000 |
351 SNDRV_PCM_RATE_44100 |
352 SNDRV_PCM_RATE_48000 |
353 SNDRV_PCM_RATE_96000),
354 .formats = SNDRV_PCM_FMTBIT_S16_LE, },
355 .ops = &spdif_dai_ops,
356 .suspend = spdif_suspend,
357 .resume = spdif_resume,
358};
359
360static __devinit int spdif_probe(struct platform_device *pdev)
361{
362 struct s3c_audio_pdata *spdif_pdata;
363 struct resource *mem_res, *dma_res;
364 struct samsung_spdif_info *spdif;
365 int ret;
366
367 spdif_pdata = pdev->dev.platform_data;
368
369 dev_dbg(&pdev->dev, "Entered %s\n", __func__);
370
371 dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
372 if (!dma_res) {
373 dev_err(&pdev->dev, "Unable to get dma resource.\n");
374 return -ENXIO;
375 }
376
377 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
378 if (!mem_res) {
379 dev_err(&pdev->dev, "Unable to get register resource.\n");
380 return -ENXIO;
381 }
382
383 if (spdif_pdata && spdif_pdata->cfg_gpio
384 && spdif_pdata->cfg_gpio(pdev)) {
385 dev_err(&pdev->dev, "Unable to configure GPIO pins\n");
386 return -EINVAL;
387 }
388
389 spdif = &spdif_info;
390 spdif->dev = &pdev->dev;
391
392 spin_lock_init(&spdif->lock);
393
394 spdif->pclk = clk_get(&pdev->dev, "spdif");
395 if (IS_ERR(spdif->pclk)) {
396 dev_err(&pdev->dev, "failed to get peri-clock\n");
397 ret = -ENOENT;
398 goto err0;
399 }
400 clk_enable(spdif->pclk);
401
402 spdif->sclk = clk_get(&pdev->dev, "sclk_spdif");
403 if (IS_ERR(spdif->sclk)) {
404 dev_err(&pdev->dev, "failed to get internal source clock\n");
405 ret = -ENOENT;
406 goto err1;
407 }
408 clk_enable(spdif->sclk);
409
410 /* Request S/PDIF Register's memory region */
411 if (!request_mem_region(mem_res->start,
412 resource_size(mem_res), "samsung-spdif")) {
413 dev_err(&pdev->dev, "Unable to request register region\n");
414 ret = -EBUSY;
415 goto err2;
416 }
417
418 spdif->regs = ioremap(mem_res->start, 0x100);
419 if (spdif->regs == NULL) {
420 dev_err(&pdev->dev, "Cannot ioremap registers\n");
421 ret = -ENXIO;
422 goto err3;
423 }
424
425 dev_set_drvdata(&pdev->dev, spdif);
426
427 ret = snd_soc_register_dai(&pdev->dev, &samsung_spdif_dai);
428 if (ret != 0) {
429 dev_err(&pdev->dev, "fail to register dai\n");
430 goto err4;
431 }
432
433 spdif_stereo_out.dma_size = 2;
434 spdif_stereo_out.client = &spdif_dma_client_out;
435 spdif_stereo_out.dma_addr = mem_res->start + DATA_OUTBUF;
436 spdif_stereo_out.channel = dma_res->start;
437
438 spdif->dma_playback = &spdif_stereo_out;
439
440 return 0;
441
442err4:
443 iounmap(spdif->regs);
444err3:
445 release_mem_region(mem_res->start, resource_size(mem_res));
446err2:
447 clk_disable(spdif->sclk);
448 clk_put(spdif->sclk);
449err1:
450 clk_disable(spdif->pclk);
451 clk_put(spdif->pclk);
452err0:
453 return ret;
454}
455
456static __devexit int spdif_remove(struct platform_device *pdev)
457{
458 struct samsung_spdif_info *spdif = &spdif_info;
459 struct resource *mem_res;
460
461 snd_soc_unregister_dai(&pdev->dev);
462
463 iounmap(spdif->regs);
464
465 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
466 if (mem_res)
467 release_mem_region(mem_res->start, resource_size(mem_res));
468
469 clk_disable(spdif->sclk);
470 clk_put(spdif->sclk);
471 clk_disable(spdif->pclk);
472 clk_put(spdif->pclk);
473
474 return 0;
475}
476
477static struct platform_driver samsung_spdif_driver = {
478 .probe = spdif_probe,
479 .remove = spdif_remove,
480 .driver = {
481 .name = "samsung-spdif",
482 .owner = THIS_MODULE,
483 },
484};
485
486static int __init spdif_init(void)
487{
488 return platform_driver_register(&samsung_spdif_driver);
489}
490module_init(spdif_init);
491
492static void __exit spdif_exit(void)
493{
494 platform_driver_unregister(&samsung_spdif_driver);
495}
496module_exit(spdif_exit);
497
498MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
499MODULE_DESCRIPTION("Samsung S/PDIF Controller Driver");
500MODULE_LICENSE("GPL");
501MODULE_ALIAS("platform:samsung-spdif");
diff --git a/sound/soc/s3c24xx/spdif.h b/sound/soc/s3c24xx/spdif.h
new file mode 100644
index 000000000000..3ed55592710f
--- /dev/null
+++ b/sound/soc/s3c24xx/spdif.h
@@ -0,0 +1,19 @@
1/* sound/soc/s3c24xx/spdif.h
2 *
3 * ALSA SoC Audio Layer - Samsung S/PDIF Controller driver
4 *
5 * Copyright (c) 2010 Samsung Electronics Co. Ltd
6 * http://www.samsung.com/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __SND_SOC_SAMSUNG_SPDIF_H
14#define __SND_SOC_SAMSUNG_SPDIF_H __FILE__
15
16#define SND_SOC_SPDIF_INT_MCLK 0
17#define SND_SOC_SPDIF_EXT_MCLK 1
18
19#endif /* __SND_SOC_SAMSUNG_SPDIF_H */
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index 59e3fa7bcb05..8778faa174a6 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -140,7 +140,7 @@ static void s6000_i2s_stop_channel(struct s6000_i2s_dev *dev, int channel)
140static void s6000_i2s_start(struct snd_pcm_substream *substream) 140static void s6000_i2s_start(struct snd_pcm_substream *substream)
141{ 141{
142 struct snd_soc_pcm_runtime *rtd = substream->private_data; 142 struct snd_soc_pcm_runtime *rtd = substream->private_data;
143 struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data; 143 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
144 int channel; 144 int channel;
145 145
146 channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 146 channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
@@ -152,7 +152,7 @@ static void s6000_i2s_start(struct snd_pcm_substream *substream)
152static void s6000_i2s_stop(struct snd_pcm_substream *substream) 152static void s6000_i2s_stop(struct snd_pcm_substream *substream)
153{ 153{
154 struct snd_soc_pcm_runtime *rtd = substream->private_data; 154 struct snd_soc_pcm_runtime *rtd = substream->private_data;
155 struct s6000_i2s_dev *dev = rtd->dai->cpu_dai->private_data; 155 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai);
156 int channel; 156 int channel;
157 157
158 channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 158 channel = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
@@ -194,7 +194,7 @@ static unsigned int s6000_i2s_int_sources(struct s6000_i2s_dev *dev)
194 194
195static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai) 195static unsigned int s6000_i2s_check_xrun(struct snd_soc_dai *cpu_dai)
196{ 196{
197 struct s6000_i2s_dev *dev = cpu_dai->private_data; 197 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
198 unsigned int errors; 198 unsigned int errors;
199 unsigned int ret; 199 unsigned int ret;
200 200
@@ -232,7 +232,7 @@ static void s6000_i2s_wait_disabled(struct s6000_i2s_dev *dev)
232static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 232static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
233 unsigned int fmt) 233 unsigned int fmt)
234{ 234{
235 struct s6000_i2s_dev *dev = cpu_dai->private_data; 235 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
236 u32 w; 236 u32 w;
237 237
238 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 238 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -273,7 +273,7 @@ static int s6000_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
273 273
274static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) 274static int s6000_i2s_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
275{ 275{
276 struct s6000_i2s_dev *dev = dai->private_data; 276 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
277 277
278 if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2) 278 if (!div || (div & 1) || div > (S6_I2S_DIV_MASK + 1) * 2)
279 return -EINVAL; 279 return -EINVAL;
@@ -287,7 +287,7 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
287 struct snd_pcm_hw_params *params, 287 struct snd_pcm_hw_params *params,
288 struct snd_soc_dai *dai) 288 struct snd_soc_dai *dai)
289{ 289{
290 struct s6000_i2s_dev *dev = dai->private_data; 290 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
291 int interf; 291 int interf;
292 u32 w = 0; 292 u32 w = 0;
293 293
@@ -326,15 +326,17 @@ static int s6000_i2s_hw_params(struct snd_pcm_substream *substream,
326 return 0; 326 return 0;
327} 327}
328 328
329static int s6000_i2s_dai_probe(struct platform_device *pdev, 329static int s6000_i2s_dai_probe(struct snd_soc_dai *dai)
330 struct snd_soc_dai *dai)
331{ 330{
332 struct s6000_i2s_dev *dev = dai->private_data; 331 struct s6000_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
333 struct s6000_snd_platform_data *pdata = pdev->dev.platform_data; 332 struct s6000_snd_platform_data *pdata = dai->dev->platform_data;
334 333
335 if (!pdata) 334 if (!pdata)
336 return -EINVAL; 335 return -EINVAL;
337 336
337 dai->capture_dma_data = &dev->dma_params;
338 dai->playback_dma_data = &dev->dma_params;
339
338 dev->wide = pdata->wide; 340 dev->wide = pdata->wide;
339 dev->channel_in = pdata->channel_in; 341 dev->channel_in = pdata->channel_in;
340 dev->channel_out = pdata->channel_out; 342 dev->channel_out = pdata->channel_out;
@@ -352,10 +354,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev,
352 354
353 dev->channel_in = 0; 355 dev->channel_in = 0;
354 dev->channel_out = 1; 356 dev->channel_out = 1;
355 dai->capture.channels_min = 2 * dev->lines_in; 357 dai->driver->capture.channels_min = 2 * dev->lines_in;
356 dai->capture.channels_max = dai->capture.channels_min; 358 dai->driver->capture.channels_max = dai->driver->capture.channels_min;
357 dai->playback.channels_min = 2 * dev->lines_out; 359 dai->driver->playback.channels_min = 2 * dev->lines_out;
358 dai->playback.channels_max = dai->playback.channels_min; 360 dai->driver->playback.channels_max = dai->driver->playback.channels_min;
359 361
360 for (i = 0; i < dev->lines_out; i++) 362 for (i = 0; i < dev->lines_out; i++)
361 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT); 363 s6_i2s_write_reg(dev, S6_I2S_DATA_CFG(i), S6_I2S_OUT);
@@ -372,10 +374,10 @@ static int s6000_i2s_dai_probe(struct platform_device *pdev,
372 if (dev->lines_in > 1 || dev->lines_out > 1) 374 if (dev->lines_in > 1 || dev->lines_out > 1)
373 return -EINVAL; 375 return -EINVAL;
374 376
375 dai->capture.channels_min = 2 * dev->lines_in; 377 dai->driver->capture.channels_min = 2 * dev->lines_in;
376 dai->capture.channels_max = 8 * dev->lines_in; 378 dai->driver->capture.channels_max = 8 * dev->lines_in;
377 dai->playback.channels_min = 2 * dev->lines_out; 379 dai->driver->playback.channels_min = 2 * dev->lines_out;
378 dai->playback.channels_max = 8 * dev->lines_out; 380 dai->driver->playback.channels_max = 8 * dev->lines_out;
379 381
380 if (dev->lines_in) 382 if (dev->lines_in)
381 cfg[dev->channel_in] = S6_I2S_IN; 383 cfg[dev->channel_in] = S6_I2S_IN;
@@ -413,9 +415,7 @@ static struct snd_soc_dai_ops s6000_i2s_dai_ops = {
413 .hw_params = s6000_i2s_hw_params, 415 .hw_params = s6000_i2s_hw_params,
414}; 416};
415 417
416struct snd_soc_dai s6000_i2s_dai = { 418static struct snd_soc_dai_driver s6000_i2s_dai = {
417 .name = "s6000-i2s",
418 .id = 0,
419 .probe = s6000_i2s_dai_probe, 419 .probe = s6000_i2s_dai_probe,
420 .playback = { 420 .playback = {
421 .channels_min = 2, 421 .channels_min = 2,
@@ -435,7 +435,6 @@ struct snd_soc_dai s6000_i2s_dai = {
435 }, 435 },
436 .ops = &s6000_i2s_dai_ops, 436 .ops = &s6000_i2s_dai_ops,
437} 437}
438EXPORT_SYMBOL_GPL(s6000_i2s_dai);
439 438
440static int __devinit s6000_i2s_probe(struct platform_device *pdev) 439static int __devinit s6000_i2s_probe(struct platform_device *pdev)
441{ 440{
@@ -513,11 +512,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
513 ret = -ENOMEM; 512 ret = -ENOMEM;
514 goto err_release_dma2; 513 goto err_release_dma2;
515 } 514 }
516 515 dev_set_drvdata(&pdev->dev, dev);
517 s6000_i2s_dai.dev = &pdev->dev;
518 s6000_i2s_dai.private_data = dev;
519 s6000_i2s_dai.capture.dma_data = &dev->dma_params;
520 s6000_i2s_dai.playback.dma_data = &dev->dma_params;
521 516
522 dev->sifbase = sifmem->start; 517 dev->sifbase = sifmem->start;
523 dev->scbbase = mmio; 518 dev->scbbase = mmio;
@@ -548,7 +543,7 @@ static int __devinit s6000_i2s_probe(struct platform_device *pdev)
548 S6_I2S_INT_UNDERRUN | 543 S6_I2S_INT_UNDERRUN |
549 S6_I2S_INT_OVERRUN); 544 S6_I2S_INT_OVERRUN);
550 545
551 ret = snd_soc_register_dai(&s6000_i2s_dai); 546 ret = snd_soc_register_dai(&pdev->dev, &s6000_i2s_dai);
552 if (ret) 547 if (ret)
553 goto err_release_dev; 548 goto err_release_dev;
554 549
@@ -573,17 +568,16 @@ err_release_none:
573 568
574static void __devexit s6000_i2s_remove(struct platform_device *pdev) 569static void __devexit s6000_i2s_remove(struct platform_device *pdev)
575{ 570{
576 struct s6000_i2s_dev *dev = s6000_i2s_dai.private_data; 571 struct s6000_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
577 struct resource *region; 572 struct resource *region;
578 void __iomem *mmio = dev->scbbase; 573 void __iomem *mmio = dev->scbbase;
579 574
580 snd_soc_unregister_dai(&s6000_i2s_dai); 575 snd_soc_unregister_dai(&pdev->dev);
581 576
582 s6000_i2s_stop_channel(dev, 0); 577 s6000_i2s_stop_channel(dev, 0);
583 s6000_i2s_stop_channel(dev, 1); 578 s6000_i2s_stop_channel(dev, 1);
584 579
585 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0); 580 s6_i2s_write_reg(dev, S6_I2S_INTERRUPT_ENABLE, 0);
586 s6000_i2s_dai.private_data = 0;
587 kfree(dev); 581 kfree(dev);
588 582
589 region = platform_get_resource(pdev, IORESOURCE_DMA, 0); 583 region = platform_get_resource(pdev, IORESOURCE_DMA, 0);
diff --git a/sound/soc/s6000/s6000-i2s.h b/sound/soc/s6000/s6000-i2s.h
index 2375fdfe6dba..86aa1921c89e 100644
--- a/sound/soc/s6000/s6000-i2s.h
+++ b/sound/soc/s6000/s6000-i2s.h
@@ -12,8 +12,6 @@
12#ifndef _S6000_I2S_H 12#ifndef _S6000_I2S_H
13#define _S6000_I2S_H 13#define _S6000_I2S_H
14 14
15extern struct snd_soc_dai s6000_i2s_dai;
16
17struct s6000_snd_platform_data { 15struct s6000_snd_platform_data {
18 int lines_in; 16 int lines_in;
19 int lines_out; 17 int lines_out;
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 9c7f7f00cebb..271fd222bf19 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -65,7 +65,7 @@ static void s6000_pcm_enqueue_dma(struct snd_pcm_substream *substream)
65 dma_addr_t dma_pos; 65 dma_addr_t dma_pos;
66 dma_addr_t src, dst; 66 dma_addr_t src, dst;
67 67
68 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 68 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
69 69
70 period_size = snd_pcm_lib_period_bytes(substream); 70 period_size = snd_pcm_lib_period_bytes(substream);
71 dma_offset = prtd->period * period_size; 71 dma_offset = prtd->period * period_size;
@@ -103,23 +103,25 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
103{ 103{
104 struct snd_pcm *pcm = data; 104 struct snd_pcm *pcm = data;
105 struct snd_soc_pcm_runtime *runtime = pcm->private_data; 105 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
106 struct s6000_pcm_dma_params *params =
107 snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream);
108 struct s6000_runtime_data *prtd; 106 struct s6000_runtime_data *prtd;
109 unsigned int has_xrun; 107 unsigned int has_xrun;
110 int i, ret = IRQ_NONE; 108 int i, ret = IRQ_NONE;
111 u32 channel[2] = {
112 [SNDRV_PCM_STREAM_PLAYBACK] = params->dma_out,
113 [SNDRV_PCM_STREAM_CAPTURE] = params->dma_in
114 };
115
116 has_xrun = params->check_xrun(runtime->dai->cpu_dai);
117 109
118 for (i = 0; i < ARRAY_SIZE(channel); ++i) { 110 for (i = 0; i < 2; ++i) {
119 struct snd_pcm_substream *substream = pcm->streams[i].substream; 111 struct snd_pcm_substream *substream = pcm->streams[i].substream;
112 struct s6000_pcm_dma_params *params =
113 snd_soc_dai_get_dma_data(runtime->cpu_dai, substream);
114 u32 channel;
120 unsigned int pending; 115 unsigned int pending;
121 116
122 if (!channel[i]) 117 if (substream == SNDRV_PCM_STREAM_PLAYBACK)
118 channel = params->dma_out;
119 else
120 channel = params->dma_in;
121
122 has_xrun = params->check_xrun(runtime->cpu_dai);
123
124 if (!channel)
123 continue; 125 continue;
124 126
125 if (unlikely(has_xrun & (1 << i)) && 127 if (unlikely(has_xrun & (1 << i)) &&
@@ -130,8 +132,8 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
130 ret = IRQ_HANDLED; 132 ret = IRQ_HANDLED;
131 } 133 }
132 134
133 pending = s6dmac_int_sources(DMA_MASK_DMAC(channel[i]), 135 pending = s6dmac_int_sources(DMA_MASK_DMAC(channel),
134 DMA_INDEX_CHNL(channel[i])); 136 DMA_INDEX_CHNL(channel));
135 137
136 if (pending & 1) { 138 if (pending & 1) {
137 ret = IRQ_HANDLED; 139 ret = IRQ_HANDLED;
@@ -139,10 +141,10 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
139 snd_pcm_running(substream))) { 141 snd_pcm_running(substream))) {
140 snd_pcm_period_elapsed(substream); 142 snd_pcm_period_elapsed(substream);
141 dev_dbg(pcm->dev, "period elapsed %x %x\n", 143 dev_dbg(pcm->dev, "period elapsed %x %x\n",
142 s6dmac_cur_src(DMA_MASK_DMAC(channel[i]), 144 s6dmac_cur_src(DMA_MASK_DMAC(channel),
143 DMA_INDEX_CHNL(channel[i])), 145 DMA_INDEX_CHNL(channel)),
144 s6dmac_cur_dst(DMA_MASK_DMAC(channel[i]), 146 s6dmac_cur_dst(DMA_MASK_DMAC(channel),
145 DMA_INDEX_CHNL(channel[i]))); 147 DMA_INDEX_CHNL(channel)));
146 prtd = substream->runtime->private_data; 148 prtd = substream->runtime->private_data;
147 spin_lock(&prtd->lock); 149 spin_lock(&prtd->lock);
148 s6000_pcm_enqueue_dma(substream); 150 s6000_pcm_enqueue_dma(substream);
@@ -154,16 +156,16 @@ static irqreturn_t s6000_pcm_irq(int irq, void *data)
154 if (pending & (1 << 3)) 156 if (pending & (1 << 3))
155 printk(KERN_WARNING 157 printk(KERN_WARNING
156 "s6000-pcm: DMA %x Underflow\n", 158 "s6000-pcm: DMA %x Underflow\n",
157 channel[i]); 159 channel);
158 if (pending & (1 << 4)) 160 if (pending & (1 << 4))
159 printk(KERN_WARNING 161 printk(KERN_WARNING
160 "s6000-pcm: DMA %x Overflow\n", 162 "s6000-pcm: DMA %x Overflow\n",
161 channel[i]); 163 channel);
162 if (pending & 0x1e0) 164 if (pending & 0x1e0)
163 printk(KERN_WARNING 165 printk(KERN_WARNING
164 "s6000-pcm: DMA %x Master Error " 166 "s6000-pcm: DMA %x Master Error "
165 "(mask %x)\n", 167 "(mask %x)\n",
166 channel[i], pending >> 5); 168 channel, pending >> 5);
167 169
168 } 170 }
169 } 171 }
@@ -180,7 +182,7 @@ static int s6000_pcm_start(struct snd_pcm_substream *substream)
180 int srcinc; 182 int srcinc;
181 u32 dma; 183 u32 dma;
182 184
183 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 185 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
184 186
185 spin_lock_irqsave(&prtd->lock, flags); 187 spin_lock_irqsave(&prtd->lock, flags);
186 188
@@ -221,7 +223,7 @@ static int s6000_pcm_stop(struct snd_pcm_substream *substream)
221 unsigned long flags; 223 unsigned long flags;
222 u32 channel; 224 u32 channel;
223 225
224 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 226 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
225 227
226 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 228 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
227 channel = par->dma_out; 229 channel = par->dma_out;
@@ -246,7 +248,7 @@ static int s6000_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
246 struct s6000_pcm_dma_params *par; 248 struct s6000_pcm_dma_params *par;
247 int ret; 249 int ret;
248 250
249 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 251 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
250 252
251 ret = par->trigger(substream, cmd, 0); 253 ret = par->trigger(substream, cmd, 0);
252 if (ret < 0) 254 if (ret < 0)
@@ -291,7 +293,7 @@ static snd_pcm_uframes_t s6000_pcm_pointer(struct snd_pcm_substream *substream)
291 unsigned int offset; 293 unsigned int offset;
292 dma_addr_t count; 294 dma_addr_t count;
293 295
294 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 296 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
295 297
296 spin_lock_irqsave(&prtd->lock, flags); 298 spin_lock_irqsave(&prtd->lock, flags);
297 299
@@ -321,7 +323,7 @@ static int s6000_pcm_open(struct snd_pcm_substream *substream)
321 struct s6000_runtime_data *prtd; 323 struct s6000_runtime_data *prtd;
322 int ret; 324 int ret;
323 325
324 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 326 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
325 snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware); 327 snd_soc_set_runtime_hwparams(substream, &s6000_pcm_hardware);
326 328
327 ret = snd_pcm_hw_constraint_step(runtime, 0, 329 ret = snd_pcm_hw_constraint_step(runtime, 0,
@@ -385,7 +387,7 @@ static int s6000_pcm_hw_params(struct snd_pcm_substream *substream,
385 return ret; 387 return ret;
386 } 388 }
387 389
388 par = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 390 par = snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
389 391
390 if (par->same_rate) { 392 if (par->same_rate) {
391 spin_lock(&par->lock); 393 spin_lock(&par->lock);
@@ -407,7 +409,7 @@ static int s6000_pcm_hw_free(struct snd_pcm_substream *substream)
407{ 409{
408 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 410 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
409 struct s6000_pcm_dma_params *par = 411 struct s6000_pcm_dma_params *par =
410 snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 412 snd_soc_dai_get_dma_data(soc_runtime->cpu_dai, substream);
411 413
412 spin_lock(&par->lock); 414 spin_lock(&par->lock);
413 par->in_use &= ~(1 << substream->stream); 415 par->in_use &= ~(1 << substream->stream);
@@ -433,7 +435,7 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
433{ 435{
434 struct snd_soc_pcm_runtime *runtime = pcm->private_data; 436 struct snd_soc_pcm_runtime *runtime = pcm->private_data;
435 struct s6000_pcm_dma_params *params = 437 struct s6000_pcm_dma_params *params =
436 snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 438 snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream);
437 439
438 free_irq(params->irq, pcm); 440 free_irq(params->irq, pcm);
439 snd_pcm_lib_preallocate_free_for_all(pcm); 441 snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -448,7 +450,8 @@ static int s6000_pcm_new(struct snd_card *card,
448 struct s6000_pcm_dma_params *params; 450 struct s6000_pcm_dma_params *params;
449 int res; 451 int res;
450 452
451 params = snd_soc_dai_get_dma_data(soc_runtime->dai->cpu_dai, substream); 453 params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
454 pcm->streams[0].substream);
452 455
453 if (!card->dev->dma_mask) 456 if (!card->dev->dma_mask)
454 card->dev->dma_mask = &s6000_pcm_dmamask; 457 card->dev->dma_mask = &s6000_pcm_dmamask;
@@ -490,25 +493,44 @@ static int s6000_pcm_new(struct snd_card *card,
490 return 0; 493 return 0;
491} 494}
492 495
493struct snd_soc_platform s6000_soc_platform = { 496static struct snd_soc_platform_driver s6000_soc_platform = {
494 .name = "s6000-audio", 497 .ops = &s6000_pcm_ops,
495 .pcm_ops = &s6000_pcm_ops,
496 .pcm_new = s6000_pcm_new, 498 .pcm_new = s6000_pcm_new,
497 .pcm_free = s6000_pcm_free, 499 .pcm_free = s6000_pcm_free,
498}; 500};
499EXPORT_SYMBOL_GPL(s6000_soc_platform);
500 501
501static int __init s6000_pcm_init(void) 502static int __devinit s6000_soc_platform_probe(struct platform_device *pdev)
503{
504 return snd_soc_register_platform(&pdev->dev, &s6000_soc_platform);
505}
506
507static int __devexit s6000_soc_platform_remove(struct platform_device *pdev)
508{
509 snd_soc_unregister_platform(&pdev->dev);
510 return 0;
511}
512
513static struct platform_driver s6000_pcm_driver = {
514 .driver = {
515 .name = "s6000-pcm-audio",
516 .owner = THIS_MODULE,
517 },
518
519 .probe = s6000_soc_platform_probe,
520 .remove = __devexit_p(s6000_soc_platform_remove),
521};
522
523static int __init snd_s6000_pcm_init(void)
502{ 524{
503 return snd_soc_register_platform(&s6000_soc_platform); 525 return platform_driver_register(&s6000_pcm_driver);
504} 526}
505module_init(s6000_pcm_init); 527module_init(snd_s6000_pcm_init);
506 528
507static void __exit s6000_pcm_exit(void) 529static void __exit snd_s6000_pcm_exit(void)
508{ 530{
509 snd_soc_unregister_platform(&s6000_soc_platform); 531 platform_driver_unregister(&s6000_pcm_driver);
510} 532}
511module_exit(s6000_pcm_exit); 533module_exit(snd_s6000_pcm_exit);
512 534
513MODULE_AUTHOR("Daniel Gloeckner"); 535MODULE_AUTHOR("Daniel Gloeckner");
514MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module"); 536MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
diff --git a/sound/soc/s6000/s6000-pcm.h b/sound/soc/s6000/s6000-pcm.h
index 96f23f6f52bf..09d9b883e58b 100644
--- a/sound/soc/s6000/s6000-pcm.h
+++ b/sound/soc/s6000/s6000-pcm.h
@@ -30,6 +30,4 @@ struct s6000_pcm_dma_params {
30 int rate; 30 int rate;
31}; 31};
32 32
33extern struct snd_soc_platform s6000_soc_platform;
34
35#endif 33#endif
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
index c1b40ac22c05..96c05e137538 100644
--- a/sound/soc/s6000/s6105-ipcam.c
+++ b/sound/soc/s6000/s6105-ipcam.c
@@ -32,8 +32,8 @@ static int s6105_hw_params(struct snd_pcm_substream *substream,
32 struct snd_pcm_hw_params *params) 32 struct snd_pcm_hw_params *params)
33{ 33{
34 struct snd_soc_pcm_runtime *rtd = substream->private_data; 34 struct snd_soc_pcm_runtime *rtd = substream->private_data;
35 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 35 struct snd_soc_dai *codec_dai = rtd->codec_dai;
36 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 36 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
37 int ret = 0; 37 int ret = 0;
38 38
39 /* set codec DAI configuration */ 39 /* set codec DAI configuration */
@@ -134,8 +134,10 @@ static const struct snd_kcontrol_new audio_out_mux = {
134}; 134};
135 135
136/* Logic for a aic3x as connected on the s6105 ip camera ref design */ 136/* Logic for a aic3x as connected on the s6105 ip camera ref design */
137static int s6105_aic3x_init(struct snd_soc_codec *codec) 137static int s6105_aic3x_init(struct snd_soc_pcm_runtime *rtd)
138{ 138{
139 struct snd_soc_codec *codec = rtd->codec;
140
139 /* Add s6105 specific widgets */ 141 /* Add s6105 specific widgets */
140 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets, 142 snd_soc_dapm_new_controls(codec, aic3x_dapm_widgets,
141 ARRAY_SIZE(aic3x_dapm_widgets)); 143 ARRAY_SIZE(aic3x_dapm_widgets));
@@ -165,7 +167,7 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec)
165 167
166 snd_soc_dapm_sync(codec); 168 snd_soc_dapm_sync(codec);
167 169
168 snd_ctl_add(codec->card, snd_ctl_new1(&audio_out_mux, codec)); 170 snd_ctl_add(codec->snd_card, snd_ctl_new1(&audio_out_mux, codec));
169 171
170 return 0; 172 return 0;
171} 173}
@@ -174,8 +176,10 @@ static int s6105_aic3x_init(struct snd_soc_codec *codec)
174static struct snd_soc_dai_link s6105_dai = { 176static struct snd_soc_dai_link s6105_dai = {
175 .name = "TLV320AIC31", 177 .name = "TLV320AIC31",
176 .stream_name = "AIC31", 178 .stream_name = "AIC31",
177 .cpu_dai = &s6000_i2s_dai, 179 .cpu_dai_name = "s6000-i2s",
178 .codec_dai = &aic3x_dai, 180 .codec_dai_name = "tlv320aic3x-hifi",
181 .platform_name = "s6000-pcm-audio",
182 .codec_name = "tlv320aic3x-codec.0-001a",
179 .init = s6105_aic3x_init, 183 .init = s6105_aic3x_init,
180 .ops = &s6105_ops, 184 .ops = &s6105_ops,
181}; 185};
@@ -183,22 +187,10 @@ static struct snd_soc_dai_link s6105_dai = {
183/* s6105 audio machine driver */ 187/* s6105 audio machine driver */
184static struct snd_soc_card snd_soc_card_s6105 = { 188static struct snd_soc_card snd_soc_card_s6105 = {
185 .name = "Stretch IP Camera", 189 .name = "Stretch IP Camera",
186 .platform = &s6000_soc_platform,
187 .dai_link = &s6105_dai, 190 .dai_link = &s6105_dai,
188 .num_links = 1, 191 .num_links = 1,
189}; 192};
190 193
191/* s6105 audio private data */
192static struct aic3x_setup_data s6105_aic3x_setup = {
193};
194
195/* s6105 audio subsystem */
196static struct snd_soc_device s6105_snd_devdata = {
197 .card = &snd_soc_card_s6105,
198 .codec_dev = &soc_codec_dev_aic3x,
199 .codec_data = &s6105_aic3x_setup,
200};
201
202static struct s6000_snd_platform_data __initdata s6105_snd_data = { 194static struct s6000_snd_platform_data __initdata s6105_snd_data = {
203 .wide = 0, 195 .wide = 0,
204 .channel_in = 0, 196 .channel_in = 0,
@@ -227,8 +219,7 @@ static int __init s6105_init(void)
227 if (!s6105_snd_device) 219 if (!s6105_snd_device)
228 return -ENOMEM; 220 return -ENOMEM;
229 221
230 platform_set_drvdata(s6105_snd_device, &s6105_snd_devdata); 222 platform_set_drvdata(s6105_snd_device, &snd_soc_card_s6105);
231 s6105_snd_devdata.dev = &s6105_snd_device->dev;
232 platform_device_add_data(s6105_snd_device, &s6105_snd_data, 223 platform_device_add_data(s6105_snd_device, &s6105_snd_data,
233 sizeof(s6105_snd_data)); 224 sizeof(s6105_snd_data));
234 225
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 52d7e8ed9c1f..7f0a496e07ce 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -47,7 +47,7 @@ config SND_SH7760_AC97
47 AC97 unit of the SH7760. 47 AC97 unit of the SH7760.
48 48
49config SND_FSI_AK4642 49config SND_FSI_AK4642
50 bool "FSI-AK4642 sound support" 50 tristate "FSI-AK4642 sound support"
51 depends on SND_SOC_SH4_FSI && I2C_SH_MOBILE 51 depends on SND_SOC_SH4_FSI && I2C_SH_MOBILE
52 select SND_SOC_AK4642 52 select SND_SOC_AK4642
53 help 53 help
@@ -55,13 +55,20 @@ config SND_FSI_AK4642
55 FSI - AK4642 unit 55 FSI - AK4642 unit
56 56
57config SND_FSI_DA7210 57config SND_FSI_DA7210
58 bool "FSI-DA7210 sound support" 58 tristate "FSI-DA7210 sound support"
59 depends on SND_SOC_SH4_FSI && I2C_SH_MOBILE 59 depends on SND_SOC_SH4_FSI && I2C_SH_MOBILE
60 select SND_SOC_DA7210 60 select SND_SOC_DA7210
61 help 61 help
62 This option enables generic sound support for the 62 This option enables generic sound support for the
63 FSI - DA7210 unit 63 FSI - DA7210 unit
64 64
65config SND_FSI_HDMI
66 tristate "FSI-HDMI sound support"
67 depends on SND_SOC_SH4_FSI && FB_SH_MOBILE_HDMI
68 help
69 This option enables generic sound support for the
70 FSI - HDMI unit
71
65config SND_SIU_MIGOR 72config SND_SIU_MIGOR
66 tristate "SIU sound support on Migo-R" 73 tristate "SIU sound support on Migo-R"
67 depends on SH_MIGOR 74 depends on SH_MIGOR
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile
index 8a5a19293bda..94476d4c0fd5 100644
--- a/sound/soc/sh/Makefile
+++ b/sound/soc/sh/Makefile
@@ -16,9 +16,11 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o
16snd-soc-sh7760-ac97-objs := sh7760-ac97.o 16snd-soc-sh7760-ac97-objs := sh7760-ac97.o
17snd-soc-fsi-ak4642-objs := fsi-ak4642.o 17snd-soc-fsi-ak4642-objs := fsi-ak4642.o
18snd-soc-fsi-da7210-objs := fsi-da7210.o 18snd-soc-fsi-da7210-objs := fsi-da7210.o
19snd-soc-fsi-hdmi-objs := fsi-hdmi.o
19snd-soc-migor-objs := migor.o 20snd-soc-migor-objs := migor.o
20 21
21obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o 22obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o
22obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o 23obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o
23obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o 24obj-$(CONFIG_SND_FSI_DA7210) += snd-soc-fsi-da7210.o
25obj-$(CONFIG_SND_FSI_HDMI) += snd-soc-fsi-hdmi.o
24obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o 26obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index 0d8bdf07729c..c326d29992fe 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -137,7 +137,7 @@ static void camelot_rxdma(void *data)
137static int camelot_pcm_open(struct snd_pcm_substream *substream) 137static int camelot_pcm_open(struct snd_pcm_substream *substream)
138{ 138{
139 struct snd_soc_pcm_runtime *rtd = substream->private_data; 139 struct snd_soc_pcm_runtime *rtd = substream->private_data;
140 struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; 140 struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
141 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; 141 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
142 int ret, dmairq; 142 int ret, dmairq;
143 143
@@ -150,7 +150,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)
150 ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam); 150 ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam);
151 if (unlikely(ret)) { 151 if (unlikely(ret)) {
152 pr_debug("audio unit %d irqs already taken!\n", 152 pr_debug("audio unit %d irqs already taken!\n",
153 rtd->dai->cpu_dai->id); 153 rtd->cpu_dai->id);
154 return -EBUSY; 154 return -EBUSY;
155 } 155 }
156 (void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam); 156 (void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam);
@@ -159,7 +159,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)
159 ret = dmabrg_request_irq(dmairq, camelot_txdma, cam); 159 ret = dmabrg_request_irq(dmairq, camelot_txdma, cam);
160 if (unlikely(ret)) { 160 if (unlikely(ret)) {
161 pr_debug("audio unit %d irqs already taken!\n", 161 pr_debug("audio unit %d irqs already taken!\n",
162 rtd->dai->cpu_dai->id); 162 rtd->cpu_dai->id);
163 return -EBUSY; 163 return -EBUSY;
164 } 164 }
165 (void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam); 165 (void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam);
@@ -170,7 +170,7 @@ static int camelot_pcm_open(struct snd_pcm_substream *substream)
170static int camelot_pcm_close(struct snd_pcm_substream *substream) 170static int camelot_pcm_close(struct snd_pcm_substream *substream)
171{ 171{
172 struct snd_soc_pcm_runtime *rtd = substream->private_data; 172 struct snd_soc_pcm_runtime *rtd = substream->private_data;
173 struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; 173 struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
174 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; 174 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
175 int dmairq; 175 int dmairq;
176 176
@@ -191,7 +191,7 @@ static int camelot_hw_params(struct snd_pcm_substream *substream,
191 struct snd_pcm_hw_params *hw_params) 191 struct snd_pcm_hw_params *hw_params)
192{ 192{
193 struct snd_soc_pcm_runtime *rtd = substream->private_data; 193 struct snd_soc_pcm_runtime *rtd = substream->private_data;
194 struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; 194 struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
195 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; 195 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
196 int ret; 196 int ret;
197 197
@@ -219,7 +219,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream)
219{ 219{
220 struct snd_pcm_runtime *runtime = substream->runtime; 220 struct snd_pcm_runtime *runtime = substream->runtime;
221 struct snd_soc_pcm_runtime *rtd = substream->private_data; 221 struct snd_soc_pcm_runtime *rtd = substream->private_data;
222 struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; 222 struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
223 223
224 pr_debug("PCM data: addr 0x%08ulx len %d\n", 224 pr_debug("PCM data: addr 0x%08ulx len %d\n",
225 (u32)runtime->dma_addr, runtime->dma_bytes); 225 (u32)runtime->dma_addr, runtime->dma_bytes);
@@ -266,7 +266,7 @@ static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam)
266static int camelot_trigger(struct snd_pcm_substream *substream, int cmd) 266static int camelot_trigger(struct snd_pcm_substream *substream, int cmd)
267{ 267{
268 struct snd_soc_pcm_runtime *rtd = substream->private_data; 268 struct snd_soc_pcm_runtime *rtd = substream->private_data;
269 struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; 269 struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
270 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; 270 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
271 271
272 switch (cmd) { 272 switch (cmd) {
@@ -293,7 +293,7 @@ static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream)
293{ 293{
294 struct snd_pcm_runtime *runtime = substream->runtime; 294 struct snd_pcm_runtime *runtime = substream->runtime;
295 struct snd_soc_pcm_runtime *rtd = substream->private_data; 295 struct snd_soc_pcm_runtime *rtd = substream->private_data;
296 struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; 296 struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
297 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; 297 int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1;
298 unsigned long pos; 298 unsigned long pos;
299 299
@@ -342,25 +342,44 @@ static int camelot_pcm_new(struct snd_card *card,
342 return 0; 342 return 0;
343} 343}
344 344
345struct snd_soc_platform sh7760_soc_platform = { 345static struct snd_soc_platform sh7760_soc_platform = {
346 .name = "sh7760-pcm",
347 .pcm_ops = &camelot_pcm_ops, 346 .pcm_ops = &camelot_pcm_ops,
348 .pcm_new = camelot_pcm_new, 347 .pcm_new = camelot_pcm_new,
349 .pcm_free = camelot_pcm_free, 348 .pcm_free = camelot_pcm_free,
350}; 349};
351EXPORT_SYMBOL_GPL(sh7760_soc_platform);
352 350
353static int __init sh7760_soc_platform_init(void) 351static int __devinit sh7760_soc_platform_probe(struct platform_device *pdev)
354{ 352{
355 return snd_soc_register_platform(&sh7760_soc_platform); 353 return snd_soc_register_platform(&pdev->dev, &sh7760_soc_platform);
356} 354}
357module_init(sh7760_soc_platform_init);
358 355
359static void __exit sh7760_soc_platform_exit(void) 356static int __devexit sh7760_soc_platform_remove(struct platform_device *pdev)
360{ 357{
361 snd_soc_unregister_platform(&sh7760_soc_platform); 358 snd_soc_unregister_platform(&pdev->dev);
359 return 0;
360}
361
362static struct platform_driver sh7760_pcm_driver = {
363 .driver = {
364 .name = "sh7760-pcm-audio",
365 .owner = THIS_MODULE,
366 },
367
368 .probe = sh7760_soc_platform_probe,
369 .remove = __devexit_p(sh7760_soc_platform_remove),
370};
371
372static int __init snd_sh7760_pcm_init(void)
373{
374 return platform_driver_register(&sh7760_pcm_driver);
375}
376module_init(snd_sh7760_pcm_init);
377
378static void __exit snd_sh7760_pcm_exit(void)
379{
380 platform_driver_unregister(&sh7760_pcm_driver);
362} 381}
363module_exit(sh7760_soc_platform_exit); 382module_exit(snd_sh7760_pcm_exit);
364 383
365MODULE_LICENSE("GPL"); 384MODULE_LICENSE("GPL");
366MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); 385MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index dad575a22622..d96602de71de 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -11,17 +11,17 @@
11 11
12#include <linux/platform_device.h> 12#include <linux/platform_device.h>
13#include <sound/sh_fsi.h> 13#include <sound/sh_fsi.h>
14#include <../sound/soc/codecs/ak4642.h>
15 14
16static int fsi_ak4642_dai_init(struct snd_soc_codec *codec) 15static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
17{ 16{
17 struct snd_soc_dai *dai = rtd->codec_dai;
18 int ret; 18 int ret;
19 19
20 ret = snd_soc_dai_set_fmt(&ak4642_dai, SND_SOC_DAIFMT_CBM_CFM); 20 ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM);
21 if (ret < 0) 21 if (ret < 0)
22 return ret; 22 return ret;
23 23
24 ret = snd_soc_dai_set_sysclk(&ak4642_dai, 0, 11289600, 0); 24 ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0);
25 25
26 return ret; 26 return ret;
27} 27}
@@ -29,24 +29,25 @@ static int fsi_ak4642_dai_init(struct snd_soc_codec *codec)
29static struct snd_soc_dai_link fsi_dai_link = { 29static struct snd_soc_dai_link fsi_dai_link = {
30 .name = "AK4642", 30 .name = "AK4642",
31 .stream_name = "AK4642", 31 .stream_name = "AK4642",
32 .cpu_dai = &fsi_soc_dai[FSI_PORT_A], 32 .cpu_dai_name = "fsia-dai", /* fsi A */
33 .codec_dai = &ak4642_dai, 33 .codec_dai_name = "ak4642-hifi",
34#ifdef CONFIG_MACH_AP4EVB
35 .platform_name = "sh_fsi2",
36 .codec_name = "ak4642-codec.0-0013",
37#else
38 .platform_name = "sh_fsi.0",
39 .codec_name = "ak4642-codec.0-0012",
40#endif
34 .init = fsi_ak4642_dai_init, 41 .init = fsi_ak4642_dai_init,
35 .ops = NULL, 42 .ops = NULL,
36}; 43};
37 44
38static struct snd_soc_card fsi_soc_card = { 45static struct snd_soc_card fsi_soc_card = {
39 .name = "FSI", 46 .name = "FSI (AK4642)",
40 .platform = &fsi_soc_platform,
41 .dai_link = &fsi_dai_link, 47 .dai_link = &fsi_dai_link,
42 .num_links = 1, 48 .num_links = 1,
43}; 49};
44 50
45static struct snd_soc_device fsi_snd_devdata = {
46 .card = &fsi_soc_card,
47 .codec_dev = &soc_codec_dev_ak4642,
48};
49
50static struct platform_device *fsi_snd_device; 51static struct platform_device *fsi_snd_device;
51 52
52static int __init fsi_ak4642_init(void) 53static int __init fsi_ak4642_init(void)
@@ -57,9 +58,7 @@ static int __init fsi_ak4642_init(void)
57 if (!fsi_snd_device) 58 if (!fsi_snd_device)
58 goto out; 59 goto out;
59 60
60 platform_set_drvdata(fsi_snd_device, 61 platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
61 &fsi_snd_devdata);
62 fsi_snd_devdata.dev = &fsi_snd_device->dev;
63 ret = platform_device_add(fsi_snd_device); 62 ret = platform_device_add(fsi_snd_device);
64 63
65 if (ret) 64 if (ret)
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
index 121bbb07bb03..a6adb6e43250 100644
--- a/sound/soc/sh/fsi-da7210.c
+++ b/sound/soc/sh/fsi-da7210.c
@@ -12,11 +12,12 @@
12 12
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <sound/sh_fsi.h> 14#include <sound/sh_fsi.h>
15#include "../codecs/da7210.h"
16 15
17static int fsi_da7210_init(struct snd_soc_codec *codec) 16static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
18{ 17{
19 return snd_soc_dai_set_fmt(&da7210_dai, 18 struct snd_soc_dai *dai = rtd->codec_dai;
19
20 return snd_soc_dai_set_fmt(dai,
20 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 21 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
21 SND_SOC_DAIFMT_CBM_CFM); 22 SND_SOC_DAIFMT_CBM_CFM);
22} 23}
@@ -24,23 +25,19 @@ static int fsi_da7210_init(struct snd_soc_codec *codec)
24static struct snd_soc_dai_link fsi_da7210_dai = { 25static struct snd_soc_dai_link fsi_da7210_dai = {
25 .name = "DA7210", 26 .name = "DA7210",
26 .stream_name = "DA7210", 27 .stream_name = "DA7210",
27 .cpu_dai = &fsi_soc_dai[FSI_PORT_B], 28 .cpu_dai_name = "fsib-dai", /* FSI B */
28 .codec_dai = &da7210_dai, 29 .codec_dai_name = "da7210-hifi",
30 .platform_name = "sh_fsi.0",
31 .codec_name = "da7210-codec.0-001a",
29 .init = fsi_da7210_init, 32 .init = fsi_da7210_init,
30}; 33};
31 34
32static struct snd_soc_card fsi_soc_card = { 35static struct snd_soc_card fsi_soc_card = {
33 .name = "FSI", 36 .name = "FSI (DA7210)",
34 .platform = &fsi_soc_platform,
35 .dai_link = &fsi_da7210_dai, 37 .dai_link = &fsi_da7210_dai,
36 .num_links = 1, 38 .num_links = 1,
37}; 39};
38 40
39static struct snd_soc_device fsi_da7210_snd_devdata = {
40 .card = &fsi_soc_card,
41 .codec_dev = &soc_codec_dev_da7210,
42};
43
44static struct platform_device *fsi_da7210_snd_device; 41static struct platform_device *fsi_da7210_snd_device;
45 42
46static int __init fsi_da7210_sound_init(void) 43static int __init fsi_da7210_sound_init(void)
@@ -51,8 +48,7 @@ static int __init fsi_da7210_sound_init(void)
51 if (!fsi_da7210_snd_device) 48 if (!fsi_da7210_snd_device)
52 return -ENOMEM; 49 return -ENOMEM;
53 50
54 platform_set_drvdata(fsi_da7210_snd_device, &fsi_da7210_snd_devdata); 51 platform_set_drvdata(fsi_da7210_snd_device, &fsi_soc_card);
55 fsi_da7210_snd_devdata.dev = &fsi_da7210_snd_device->dev;
56 ret = platform_device_add(fsi_da7210_snd_device); 52 ret = platform_device_add(fsi_da7210_snd_device);
57 if (ret) 53 if (ret)
58 platform_device_put(fsi_da7210_snd_device); 54 platform_device_put(fsi_da7210_snd_device);
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
new file mode 100644
index 000000000000..a52dd8ec71d3
--- /dev/null
+++ b/sound/soc/sh/fsi-hdmi.c
@@ -0,0 +1,60 @@
1/*
2 * FSI - HDMI sound support
3 *
4 * Copyright (C) 2010 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file "COPYING" in the main directory of this archive
9 * for more details.
10 */
11
12#include <linux/platform_device.h>
13#include <sound/sh_fsi.h>
14
15static struct snd_soc_dai_link fsi_dai_link = {
16 .name = "HDMI",
17 .stream_name = "HDMI",
18 .cpu_dai_name = "fsib-dai", /* fsi B */
19 .codec_dai_name = "sh_mobile_hdmi-hifi",
20 .platform_name = "sh_fsi2",
21 .codec_name = "sh-mobile-hdmi",
22};
23
24static struct snd_soc_card fsi_soc_card = {
25 .name = "FSI (SH MOBILE HDMI)",
26 .dai_link = &fsi_dai_link,
27 .num_links = 1,
28};
29
30static struct platform_device *fsi_snd_device;
31
32static int __init fsi_hdmi_init(void)
33{
34 int ret = -ENOMEM;
35
36 fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B);
37 if (!fsi_snd_device)
38 goto out;
39
40 platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
41 ret = platform_device_add(fsi_snd_device);
42
43 if (ret)
44 platform_device_put(fsi_snd_device);
45
46out:
47 return ret;
48}
49
50static void __exit fsi_hdmi_exit(void)
51{
52 platform_device_unregister(fsi_snd_device);
53}
54
55module_init(fsi_hdmi_init);
56module_exit(fsi_hdmi_exit);
57
58MODULE_LICENSE("GPL");
59MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
60MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 58c6bec642de..507e709f2807 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -80,11 +80,12 @@
80#define B_CLK 0x00000010 80#define B_CLK 0x00000010
81#define A_CLK 0x00000001 81#define A_CLK 0x00000001
82 82
83/* INT_ST */ 83/* IO SHIFT / MACRO */
84#define INT_B_IN (1 << 12) 84#define BI_SHIFT 12
85#define INT_B_OUT (1 << 8) 85#define BO_SHIFT 8
86#define INT_A_IN (1 << 4) 86#define AI_SHIFT 4
87#define INT_A_OUT (1 << 0) 87#define AO_SHIFT 0
88#define AB_IO(param, shift) (param << shift)
88 89
89/* SOFT_RST */ 90/* SOFT_RST */
90#define PBSR (1 << 12) /* Port B Software Reset */ 91#define PBSR (1 << 12) /* Port B Software Reset */
@@ -93,33 +94,43 @@
93#define FSISR (1 << 0) /* Software Reset */ 94#define FSISR (1 << 0) /* Software Reset */
94 95
95/* FIFO_SZ */ 96/* FIFO_SZ */
96#define OUT_SZ_MASK 0x7 97#define FIFO_SZ_MASK 0x7
97#define BO_SZ_SHIFT 8
98#define AO_SZ_SHIFT 0
99 98
100#define FSI_RATES SNDRV_PCM_RATE_8000_96000 99#define FSI_RATES SNDRV_PCM_RATE_8000_96000
101 100
102#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) 101#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
103 102
104/************************************************************************ 103/*
104 * FSI driver use below type name for variable
105 *
106 * xxx_len : data length
107 * xxx_width : data width
108 * xxx_offset : data offset
109 * xxx_num : number of data
110 */
111
112/*
113 * struct
114 */
105 115
116struct fsi_stream {
117 struct snd_pcm_substream *substream;
106 118
107 struct 119 int fifo_max_num;
120 int chan_num;
108 121
122 int buff_offset;
123 int buff_len;
124 int period_len;
125 int period_num;
126};
109 127
110************************************************************************/
111struct fsi_priv { 128struct fsi_priv {
112 void __iomem *base; 129 void __iomem *base;
113 struct snd_pcm_substream *substream;
114 struct fsi_master *master; 130 struct fsi_master *master;
115 131
116 int fifo_max; 132 struct fsi_stream playback;
117 int chan; 133 struct fsi_stream capture;
118
119 int byte_offset;
120 int period_len;
121 int buffer_len;
122 int periods;
123 134
124 u32 mst_ctrl; 135 u32 mst_ctrl;
125}; 136};
@@ -142,13 +153,10 @@ struct fsi_master {
142 spinlock_t lock; 153 spinlock_t lock;
143}; 154};
144 155
145/************************************************************************ 156/*
146 157 * basic read write function
147 158 */
148 basic read write function
149
150 159
151************************************************************************/
152static void __fsi_reg_write(u32 reg, u32 data) 160static void __fsi_reg_write(u32 reg, u32 data)
153{ 161{
154 /* valid data area is 24bit */ 162 /* valid data area is 24bit */
@@ -251,13 +259,10 @@ static void fsi_master_mask_set(struct fsi_master *master,
251 spin_unlock_irqrestore(&master->lock, flags); 259 spin_unlock_irqrestore(&master->lock, flags);
252} 260}
253 261
254/************************************************************************ 262/*
255 263 * basic function
256 264 */
257 basic function
258
259 265
260************************************************************************/
261static struct fsi_master *fsi_get_master(struct fsi_priv *fsi) 266static struct fsi_master *fsi_get_master(struct fsi_priv *fsi)
262{ 267{
263 return fsi->master; 268 return fsi->master;
@@ -271,16 +276,19 @@ static int fsi_is_port_a(struct fsi_priv *fsi)
271static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) 276static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
272{ 277{
273 struct snd_soc_pcm_runtime *rtd = substream->private_data; 278 struct snd_soc_pcm_runtime *rtd = substream->private_data;
274 struct snd_soc_dai_link *machine = rtd->dai;
275 279
276 return machine->cpu_dai; 280 return rtd->cpu_dai;
277} 281}
278 282
279static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) 283static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
280{ 284{
281 struct snd_soc_dai *dai = fsi_get_dai(substream); 285 struct snd_soc_dai *dai = fsi_get_dai(substream);
286 struct fsi_master *master = snd_soc_dai_get_drvdata(dai);
282 287
283 return dai->private_data; 288 if (dai->id == 0)
289 return &master->fsia;
290 else
291 return &master->fsib;
284} 292}
285 293
286static u32 fsi_get_info_flags(struct fsi_priv *fsi) 294static u32 fsi_get_info_flags(struct fsi_priv *fsi)
@@ -292,6 +300,22 @@ static u32 fsi_get_info_flags(struct fsi_priv *fsi)
292 master->info->portb_flags; 300 master->info->portb_flags;
293} 301}
294 302
303static inline int fsi_stream_is_play(int stream)
304{
305 return stream == SNDRV_PCM_STREAM_PLAYBACK;
306}
307
308static inline int fsi_is_play(struct snd_pcm_substream *substream)
309{
310 return fsi_stream_is_play(substream->stream);
311}
312
313static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi,
314 int is_play)
315{
316 return is_play ? &fsi->playback : &fsi->capture;
317}
318
295static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play) 319static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
296{ 320{
297 u32 mode; 321 u32 mode;
@@ -307,63 +331,144 @@ static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play)
307 return (mode & flags) != mode; 331 return (mode & flags) != mode;
308} 332}
309 333
310static u32 fsi_port_ab_io_bit(struct fsi_priv *fsi, int is_play) 334static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
311{ 335{
312 int is_porta = fsi_is_port_a(fsi); 336 int is_porta = fsi_is_port_a(fsi);
313 u32 data; 337 u32 shift;
314 338
315 if (is_porta) 339 if (is_porta)
316 data = is_play ? (1 << 0) : (1 << 4); 340 shift = is_play ? AO_SHIFT : AI_SHIFT;
317 else 341 else
318 data = is_play ? (1 << 8) : (1 << 12); 342 shift = is_play ? BO_SHIFT : BI_SHIFT;
319 343
320 return data; 344 return shift;
321} 345}
322 346
323static void fsi_stream_push(struct fsi_priv *fsi, 347static void fsi_stream_push(struct fsi_priv *fsi,
348 int is_play,
324 struct snd_pcm_substream *substream, 349 struct snd_pcm_substream *substream,
325 u32 buffer_len, 350 u32 buffer_len,
326 u32 period_len) 351 u32 period_len)
327{ 352{
328 fsi->substream = substream; 353 struct fsi_stream *io = fsi_get_stream(fsi, is_play);
329 fsi->buffer_len = buffer_len; 354
330 fsi->period_len = period_len; 355 io->substream = substream;
331 fsi->byte_offset = 0; 356 io->buff_len = buffer_len;
332 fsi->periods = 0; 357 io->buff_offset = 0;
358 io->period_len = period_len;
359 io->period_num = 0;
333} 360}
334 361
335static void fsi_stream_pop(struct fsi_priv *fsi) 362static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
336{ 363{
337 fsi->substream = NULL; 364 struct fsi_stream *io = fsi_get_stream(fsi, is_play);
338 fsi->buffer_len = 0; 365
339 fsi->period_len = 0; 366 io->substream = NULL;
340 fsi->byte_offset = 0; 367 io->buff_len = 0;
341 fsi->periods = 0; 368 io->buff_offset = 0;
369 io->period_len = 0;
370 io->period_num = 0;
342} 371}
343 372
344static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play) 373static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play)
345{ 374{
346 u32 status; 375 u32 status;
347 u32 reg = is_play ? DOFF_ST : DIFF_ST; 376 u32 reg = is_play ? DOFF_ST : DIFF_ST;
348 int residue; 377 struct fsi_stream *io = fsi_get_stream(fsi, is_play);
378 int data_num;
349 379
350 status = fsi_reg_read(fsi, reg); 380 status = fsi_reg_read(fsi, reg);
351 residue = 0x1ff & (status >> 8); 381 data_num = 0x1ff & (status >> 8);
352 residue *= fsi->chan; 382 data_num *= io->chan_num;
383
384 return data_num;
385}
386
387static int fsi_len2num(int len, int width)
388{
389 return len / width;
390}
391
392#define fsi_num2offset(a, b) fsi_num2len(a, b)
393static int fsi_num2len(int num, int width)
394{
395 return num * width;
396}
397
398static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play)
399{
400 struct fsi_stream *io = fsi_get_stream(fsi, is_play);
401 struct snd_pcm_substream *substream = io->substream;
402 struct snd_pcm_runtime *runtime = substream->runtime;
403
404 return frames_to_bytes(runtime, 1) / io->chan_num;
405}
406
407/*
408 * dma function
409 */
410
411static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream)
412{
413 int is_play = fsi_stream_is_play(stream);
414 struct fsi_stream *io = fsi_get_stream(fsi, is_play);
415
416 return io->substream->runtime->dma_area + io->buff_offset;
417}
418
419static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num)
420{
421 u16 *start;
422 int i;
423
424 start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
425
426 for (i = 0; i < num; i++)
427 fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8));
428}
429
430static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num)
431{
432 u16 *start;
433 int i;
353 434
354 return residue; 435 start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
436
437
438 for (i = 0; i < num; i++)
439 *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
355} 440}
356 441
357/************************************************************************ 442static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num)
443{
444 u32 *start;
445 int i;
446
447 start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
448
449
450 for (i = 0; i < num; i++)
451 fsi_reg_write(fsi, DODT, *(start + i));
452}
358 453
454static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num)
455{
456 u32 *start;
457 int i;
359 458
360 irq function 459 start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
361 460
461 for (i = 0; i < num; i++)
462 *(start + i) = fsi_reg_read(fsi, DIDT);
463}
464
465/*
466 * irq function
467 */
362 468
363************************************************************************/
364static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) 469static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
365{ 470{
366 u32 data = fsi_port_ab_io_bit(fsi, is_play); 471 u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
367 struct fsi_master *master = fsi_get_master(fsi); 472 struct fsi_master *master = fsi_get_master(fsi);
368 473
369 fsi_master_mask_set(master, master->core->imsk, data, data); 474 fsi_master_mask_set(master, master->core->imsk, data, data);
@@ -372,7 +477,7 @@ static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
372 477
373static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) 478static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
374{ 479{
375 u32 data = fsi_port_ab_io_bit(fsi, is_play); 480 u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
376 struct fsi_master *master = fsi_get_master(fsi); 481 struct fsi_master *master = fsi_get_master(fsi);
377 482
378 fsi_master_mask_set(master, master->core->imsk, data, 0); 483 fsi_master_mask_set(master, master->core->imsk, data, 0);
@@ -394,20 +499,18 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
394 u32 data = 0; 499 u32 data = 0;
395 struct fsi_master *master = fsi_get_master(fsi); 500 struct fsi_master *master = fsi_get_master(fsi);
396 501
397 data |= fsi_port_ab_io_bit(fsi, 0); 502 data |= AB_IO(1, fsi_get_port_shift(fsi, 0));
398 data |= fsi_port_ab_io_bit(fsi, 1); 503 data |= AB_IO(1, fsi_get_port_shift(fsi, 1));
399 504
400 /* clear interrupt factor */ 505 /* clear interrupt factor */
401 fsi_master_mask_set(master, master->core->int_st, data, 0); 506 fsi_master_mask_set(master, master->core->int_st, data, 0);
402} 507}
403 508
404/************************************************************************ 509/*
405 510 * SPDIF master clock function
406 511 *
407 SPDIF master clock function 512 * These functions are used later FSI2
408 513 */
409These functions are used later FSI2
410************************************************************************/
411static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable) 514static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
412{ 515{
413 struct fsi_master *master = fsi_get_master(fsi); 516 struct fsi_master *master = fsi_get_master(fsi);
@@ -424,13 +527,10 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
424 fsi_master_mask_set(master, fsi->mst_ctrl, val, 0); 527 fsi_master_mask_set(master, fsi->mst_ctrl, val, 0);
425} 528}
426 529
427/************************************************************************ 530/*
428 531 * ctrl function
429 532 */
430 ctrl function
431
432 533
433************************************************************************/
434static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) 534static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable)
435{ 535{
436 u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); 536 u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4);
@@ -447,14 +547,15 @@ static void fsi_fifo_init(struct fsi_priv *fsi,
447 struct snd_soc_dai *dai) 547 struct snd_soc_dai *dai)
448{ 548{
449 struct fsi_master *master = fsi_get_master(fsi); 549 struct fsi_master *master = fsi_get_master(fsi);
550 struct fsi_stream *io = fsi_get_stream(fsi, is_play);
450 u32 ctrl, shift, i; 551 u32 ctrl, shift, i;
451 552
452 /* get on-chip RAM capacity */ 553 /* get on-chip RAM capacity */
453 shift = fsi_master_read(master, FIFO_SZ); 554 shift = fsi_master_read(master, FIFO_SZ);
454 shift >>= fsi_is_port_a(fsi) ? AO_SZ_SHIFT : BO_SZ_SHIFT; 555 shift >>= fsi_get_port_shift(fsi, is_play);
455 shift &= OUT_SZ_MASK; 556 shift &= FIFO_SZ_MASK;
456 fsi->fifo_max = 256 << shift; 557 io->fifo_max_num = 256 << shift;
457 dev_dbg(dai->dev, "fifo = %d words\n", fsi->fifo_max); 558 dev_dbg(dai->dev, "fifo = %d words\n", io->fifo_max_num);
458 559
459 /* 560 /*
460 * The maximum number of sample data varies depending 561 * The maximum number of sample data varies depending
@@ -475,9 +576,10 @@ static void fsi_fifo_init(struct fsi_priv *fsi,
475 * 7 channels: 32 ( 32 x 7 = 224) 576 * 7 channels: 32 ( 32 x 7 = 224)
476 * 8 channels: 32 ( 32 x 8 = 256) 577 * 8 channels: 32 ( 32 x 8 = 256)
477 */ 578 */
478 for (i = 1; i < fsi->chan; i <<= 1) 579 for (i = 1; i < io->chan_num; i <<= 1)
479 fsi->fifo_max >>= 1; 580 io->fifo_max_num >>= 1;
480 dev_dbg(dai->dev, "%d channel %d store\n", fsi->chan, fsi->fifo_max); 581 dev_dbg(dai->dev, "%d channel %d store\n",
582 io->chan_num, io->fifo_max_num);
481 583
482 ctrl = is_play ? DOFF_CTL : DIFF_CTL; 584 ctrl = is_play ? DOFF_CTL : DIFF_CTL;
483 585
@@ -500,84 +602,114 @@ static void fsi_soft_all_reset(struct fsi_master *master)
500 mdelay(10); 602 mdelay(10);
501} 603}
502 604
503/* playback interrupt */ 605static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int startup, int stream)
504static int fsi_data_push(struct fsi_priv *fsi, int startup)
505{ 606{
506 struct snd_pcm_runtime *runtime; 607 struct snd_pcm_runtime *runtime;
507 struct snd_pcm_substream *substream = NULL; 608 struct snd_pcm_substream *substream = NULL;
508 u32 status; 609 int is_play = fsi_stream_is_play(stream);
509 int send; 610 struct fsi_stream *io = fsi_get_stream(fsi, is_play);
510 int fifo_free; 611 u32 status_reg = is_play ? DOFF_ST : DIFF_ST;
511 int width; 612 int data_residue_num;
512 u8 *start; 613 int data_num;
513 int i, over_period; 614 int data_num_max;
615 int ch_width;
616 int over_period;
617 void (*fn)(struct fsi_priv *fsi, int size);
514 618
515 if (!fsi || 619 if (!fsi ||
516 !fsi->substream || 620 !io->substream ||
517 !fsi->substream->runtime) 621 !io->substream->runtime)
518 return -EINVAL; 622 return -EINVAL;
519 623
520 over_period = 0; 624 over_period = 0;
521 substream = fsi->substream; 625 substream = io->substream;
522 runtime = substream->runtime; 626 runtime = substream->runtime;
523 627
524 /* FSI FIFO has limit. 628 /* FSI FIFO has limit.
525 * So, this driver can not send periods data at a time 629 * So, this driver can not send periods data at a time
526 */ 630 */
527 if (fsi->byte_offset >= 631 if (io->buff_offset >=
528 fsi->period_len * (fsi->periods + 1)) { 632 fsi_num2offset(io->period_num + 1, io->period_len)) {
529 633
530 over_period = 1; 634 over_period = 1;
531 fsi->periods = (fsi->periods + 1) % runtime->periods; 635 io->period_num = (io->period_num + 1) % runtime->periods;
532 636
533 if (0 == fsi->periods) 637 if (0 == io->period_num)
534 fsi->byte_offset = 0; 638 io->buff_offset = 0;
535 } 639 }
536 640
537 /* get 1 channel data width */ 641 /* get 1 channel data width */
538 width = frames_to_bytes(runtime, 1) / fsi->chan; 642 ch_width = fsi_get_frame_width(fsi, is_play);
539 643
540 /* get send size for alsa */ 644 /* get residue data number of alsa */
541 send = (fsi->buffer_len - fsi->byte_offset) / width; 645 data_residue_num = fsi_len2num(io->buff_len - io->buff_offset,
542 646 ch_width);
543 /* get FIFO free size */ 647
544 fifo_free = (fsi->fifo_max * fsi->chan) - fsi_get_fifo_residue(fsi, 1); 648 if (is_play) {
545 649 /*
546 /* size check */ 650 * for play-back
547 if (fifo_free < send) 651 *
548 send = fifo_free; 652 * data_num_max : number of FSI fifo free space
653 * data_num : number of ALSA residue data
654 */
655 data_num_max = io->fifo_max_num * io->chan_num;
656 data_num_max -= fsi_get_fifo_data_num(fsi, is_play);
657
658 data_num = data_residue_num;
659
660 switch (ch_width) {
661 case 2:
662 fn = fsi_dma_soft_push16;
663 break;
664 case 4:
665 fn = fsi_dma_soft_push32;
666 break;
667 default:
668 return -EINVAL;
669 }
670 } else {
671 /*
672 * for capture
673 *
674 * data_num_max : number of ALSA free space
675 * data_num : number of data in FSI fifo
676 */
677 data_num_max = data_residue_num;
678 data_num = fsi_get_fifo_data_num(fsi, is_play);
679
680 switch (ch_width) {
681 case 2:
682 fn = fsi_dma_soft_pop16;
683 break;
684 case 4:
685 fn = fsi_dma_soft_pop32;
686 break;
687 default:
688 return -EINVAL;
689 }
690 }
549 691
550 start = runtime->dma_area; 692 data_num = min(data_num, data_num_max);
551 start += fsi->byte_offset;
552 693
553 switch (width) { 694 fn(fsi, data_num);
554 case 2:
555 for (i = 0; i < send; i++)
556 fsi_reg_write(fsi, DODT,
557 ((u32)*((u16 *)start + i) << 8));
558 break;
559 case 4:
560 for (i = 0; i < send; i++)
561 fsi_reg_write(fsi, DODT, *((u32 *)start + i));
562 break;
563 default:
564 return -EINVAL;
565 }
566 695
567 fsi->byte_offset += send * width; 696 /* update buff_offset */
697 io->buff_offset += fsi_num2offset(data_num, ch_width);
568 698
569 status = fsi_reg_read(fsi, DOFF_ST); 699 /* check fifo status */
570 if (!startup) { 700 if (!startup) {
571 struct snd_soc_dai *dai = fsi_get_dai(substream); 701 struct snd_soc_dai *dai = fsi_get_dai(substream);
702 u32 status = fsi_reg_read(fsi, status_reg);
572 703
573 if (status & ERR_OVER) 704 if (status & ERR_OVER)
574 dev_err(dai->dev, "over run\n"); 705 dev_err(dai->dev, "over run\n");
575 if (status & ERR_UNDER) 706 if (status & ERR_UNDER)
576 dev_err(dai->dev, "under run\n"); 707 dev_err(dai->dev, "under run\n");
577 } 708 }
578 fsi_reg_write(fsi, DOFF_ST, 0); 709 fsi_reg_write(fsi, status_reg, 0);
579 710
580 fsi_irq_enable(fsi, 1); 711 /* re-enable irq */
712 fsi_irq_enable(fsi, is_play);
581 713
582 if (over_period) 714 if (over_period)
583 snd_pcm_period_elapsed(substream); 715 snd_pcm_period_elapsed(substream);
@@ -587,85 +719,12 @@ static int fsi_data_push(struct fsi_priv *fsi, int startup)
587 719
588static int fsi_data_pop(struct fsi_priv *fsi, int startup) 720static int fsi_data_pop(struct fsi_priv *fsi, int startup)
589{ 721{
590 struct snd_pcm_runtime *runtime; 722 return fsi_fifo_data_ctrl(fsi, startup, SNDRV_PCM_STREAM_CAPTURE);
591 struct snd_pcm_substream *substream = NULL; 723}
592 u32 status;
593 int free;
594 int fifo_fill;
595 int width;
596 u8 *start;
597 int i, over_period;
598
599 if (!fsi ||
600 !fsi->substream ||
601 !fsi->substream->runtime)
602 return -EINVAL;
603
604 over_period = 0;
605 substream = fsi->substream;
606 runtime = substream->runtime;
607
608 /* FSI FIFO has limit.
609 * So, this driver can not send periods data at a time
610 */
611 if (fsi->byte_offset >=
612 fsi->period_len * (fsi->periods + 1)) {
613
614 over_period = 1;
615 fsi->periods = (fsi->periods + 1) % runtime->periods;
616
617 if (0 == fsi->periods)
618 fsi->byte_offset = 0;
619 }
620
621 /* get 1 channel data width */
622 width = frames_to_bytes(runtime, 1) / fsi->chan;
623
624 /* get free space for alsa */
625 free = (fsi->buffer_len - fsi->byte_offset) / width;
626
627 /* get recv size */
628 fifo_fill = fsi_get_fifo_residue(fsi, 0);
629
630 if (free < fifo_fill)
631 fifo_fill = free;
632
633 start = runtime->dma_area;
634 start += fsi->byte_offset;
635
636 switch (width) {
637 case 2:
638 for (i = 0; i < fifo_fill; i++)
639 *((u16 *)start + i) =
640 (u16)(fsi_reg_read(fsi, DIDT) >> 8);
641 break;
642 case 4:
643 for (i = 0; i < fifo_fill; i++)
644 *((u32 *)start + i) = fsi_reg_read(fsi, DIDT);
645 break;
646 default:
647 return -EINVAL;
648 }
649
650 fsi->byte_offset += fifo_fill * width;
651
652 status = fsi_reg_read(fsi, DIFF_ST);
653 if (!startup) {
654 struct snd_soc_dai *dai = fsi_get_dai(substream);
655
656 if (status & ERR_OVER)
657 dev_err(dai->dev, "over run\n");
658 if (status & ERR_UNDER)
659 dev_err(dai->dev, "under run\n");
660 }
661 fsi_reg_write(fsi, DIFF_ST, 0);
662
663 fsi_irq_enable(fsi, 0);
664
665 if (over_period)
666 snd_pcm_period_elapsed(substream);
667 724
668 return 0; 725static int fsi_data_push(struct fsi_priv *fsi, int startup)
726{
727 return fsi_fifo_data_ctrl(fsi, startup, SNDRV_PCM_STREAM_PLAYBACK);
669} 728}
670 729
671static irqreturn_t fsi_interrupt(int irq, void *data) 730static irqreturn_t fsi_interrupt(int irq, void *data)
@@ -677,13 +736,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
677 fsi_master_mask_set(master, SOFT_RST, IR, 0); 736 fsi_master_mask_set(master, SOFT_RST, IR, 0);
678 fsi_master_mask_set(master, SOFT_RST, IR, IR); 737 fsi_master_mask_set(master, SOFT_RST, IR, IR);
679 738
680 if (int_st & INT_A_OUT) 739 if (int_st & AB_IO(1, AO_SHIFT))
681 fsi_data_push(&master->fsia, 0); 740 fsi_data_push(&master->fsia, 0);
682 if (int_st & INT_B_OUT) 741 if (int_st & AB_IO(1, BO_SHIFT))
683 fsi_data_push(&master->fsib, 0); 742 fsi_data_push(&master->fsib, 0);
684 if (int_st & INT_A_IN) 743 if (int_st & AB_IO(1, AI_SHIFT))
685 fsi_data_pop(&master->fsia, 0); 744 fsi_data_pop(&master->fsia, 0);
686 if (int_st & INT_B_IN) 745 if (int_st & AB_IO(1, BI_SHIFT))
687 fsi_data_pop(&master->fsib, 0); 746 fsi_data_pop(&master->fsib, 0);
688 747
689 fsi_irq_clear_all_status(master); 748 fsi_irq_clear_all_status(master);
@@ -691,25 +750,24 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
691 return IRQ_HANDLED; 750 return IRQ_HANDLED;
692} 751}
693 752
694/************************************************************************ 753/*
695 754 * dai ops
696 755 */
697 dai ops
698
699 756
700************************************************************************/
701static int fsi_dai_startup(struct snd_pcm_substream *substream, 757static int fsi_dai_startup(struct snd_pcm_substream *substream,
702 struct snd_soc_dai *dai) 758 struct snd_soc_dai *dai)
703{ 759{
704 struct fsi_priv *fsi = fsi_get_priv(substream); 760 struct fsi_priv *fsi = fsi_get_priv(substream);
705 u32 flags = fsi_get_info_flags(fsi);
706 struct fsi_master *master = fsi_get_master(fsi); 761 struct fsi_master *master = fsi_get_master(fsi);
762 struct fsi_stream *io;
763 u32 flags = fsi_get_info_flags(fsi);
707 u32 fmt; 764 u32 fmt;
708 u32 reg; 765 u32 reg;
709 u32 data; 766 u32 data;
710 int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 767 int is_play = fsi_is_play(substream);
711 int is_master; 768 int is_master;
712 int ret = 0; 769
770 io = fsi_get_stream(fsi, is_play);
713 771
714 pm_runtime_get_sync(dai->dev); 772 pm_runtime_get_sync(dai->dev);
715 773
@@ -741,29 +799,29 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
741 switch (fmt) { 799 switch (fmt) {
742 case SH_FSI_FMT_MONO: 800 case SH_FSI_FMT_MONO:
743 data = CR_MONO; 801 data = CR_MONO;
744 fsi->chan = 1; 802 io->chan_num = 1;
745 break; 803 break;
746 case SH_FSI_FMT_MONO_DELAY: 804 case SH_FSI_FMT_MONO_DELAY:
747 data = CR_MONO_D; 805 data = CR_MONO_D;
748 fsi->chan = 1; 806 io->chan_num = 1;
749 break; 807 break;
750 case SH_FSI_FMT_PCM: 808 case SH_FSI_FMT_PCM:
751 data = CR_PCM; 809 data = CR_PCM;
752 fsi->chan = 2; 810 io->chan_num = 2;
753 break; 811 break;
754 case SH_FSI_FMT_I2S: 812 case SH_FSI_FMT_I2S:
755 data = CR_I2S; 813 data = CR_I2S;
756 fsi->chan = 2; 814 io->chan_num = 2;
757 break; 815 break;
758 case SH_FSI_FMT_TDM: 816 case SH_FSI_FMT_TDM:
759 fsi->chan = is_play ? 817 io->chan_num = is_play ?
760 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); 818 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
761 data = CR_TDM | (fsi->chan - 1); 819 data = CR_TDM | (io->chan_num - 1);
762 break; 820 break;
763 case SH_FSI_FMT_TDM_DELAY: 821 case SH_FSI_FMT_TDM_DELAY:
764 fsi->chan = is_play ? 822 io->chan_num = is_play ?
765 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); 823 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
766 data = CR_TDM_D | (fsi->chan - 1); 824 data = CR_TDM_D | (io->chan_num - 1);
767 break; 825 break;
768 case SH_FSI_FMT_SPDIF: 826 case SH_FSI_FMT_SPDIF:
769 if (master->core->ver < 2) { 827 if (master->core->ver < 2) {
@@ -771,7 +829,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
771 return -EINVAL; 829 return -EINVAL;
772 } 830 }
773 data = CR_SPDIF; 831 data = CR_SPDIF;
774 fsi->chan = 2; 832 io->chan_num = 2;
775 fsi_spdif_clk_ctrl(fsi, 1); 833 fsi_spdif_clk_ctrl(fsi, 1);
776 fsi_reg_mask_set(fsi, OUT_SEL, 0x0010, 0x0010); 834 fsi_reg_mask_set(fsi, OUT_SEL, 0x0010, 0x0010);
777 break; 835 break;
@@ -788,14 +846,14 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
788 /* fifo init */ 846 /* fifo init */
789 fsi_fifo_init(fsi, is_play, dai); 847 fsi_fifo_init(fsi, is_play, dai);
790 848
791 return ret; 849 return 0;
792} 850}
793 851
794static void fsi_dai_shutdown(struct snd_pcm_substream *substream, 852static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
795 struct snd_soc_dai *dai) 853 struct snd_soc_dai *dai)
796{ 854{
797 struct fsi_priv *fsi = fsi_get_priv(substream); 855 struct fsi_priv *fsi = fsi_get_priv(substream);
798 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 856 int is_play = fsi_is_play(substream);
799 857
800 fsi_irq_disable(fsi, is_play); 858 fsi_irq_disable(fsi, is_play);
801 fsi_clk_ctrl(fsi, 0); 859 fsi_clk_ctrl(fsi, 0);
@@ -808,19 +866,19 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
808{ 866{
809 struct fsi_priv *fsi = fsi_get_priv(substream); 867 struct fsi_priv *fsi = fsi_get_priv(substream);
810 struct snd_pcm_runtime *runtime = substream->runtime; 868 struct snd_pcm_runtime *runtime = substream->runtime;
811 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 869 int is_play = fsi_is_play(substream);
812 int ret = 0; 870 int ret = 0;
813 871
814 switch (cmd) { 872 switch (cmd) {
815 case SNDRV_PCM_TRIGGER_START: 873 case SNDRV_PCM_TRIGGER_START:
816 fsi_stream_push(fsi, substream, 874 fsi_stream_push(fsi, is_play, substream,
817 frames_to_bytes(runtime, runtime->buffer_size), 875 frames_to_bytes(runtime, runtime->buffer_size),
818 frames_to_bytes(runtime, runtime->period_size)); 876 frames_to_bytes(runtime, runtime->period_size));
819 ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1); 877 ret = is_play ? fsi_data_push(fsi, 1) : fsi_data_pop(fsi, 1);
820 break; 878 break;
821 case SNDRV_PCM_TRIGGER_STOP: 879 case SNDRV_PCM_TRIGGER_STOP:
822 fsi_irq_disable(fsi, is_play); 880 fsi_irq_disable(fsi, is_play);
823 fsi_stream_pop(fsi); 881 fsi_stream_pop(fsi, is_play);
824 break; 882 break;
825 } 883 }
826 884
@@ -835,7 +893,7 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
835 struct fsi_master *master = fsi_get_master(fsi); 893 struct fsi_master *master = fsi_get_master(fsi);
836 int (*set_rate)(int is_porta, int rate) = master->info->set_rate; 894 int (*set_rate)(int is_porta, int rate) = master->info->set_rate;
837 int fsi_ver = master->core->ver; 895 int fsi_ver = master->core->ver;
838 int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 896 int is_play = fsi_is_play(substream);
839 int ret; 897 int ret;
840 898
841 /* if slave mode, set_rate is not needed */ 899 /* if slave mode, set_rate is not needed */
@@ -916,13 +974,10 @@ static struct snd_soc_dai_ops fsi_dai_ops = {
916 .hw_params = fsi_dai_hw_params, 974 .hw_params = fsi_dai_hw_params,
917}; 975};
918 976
919/************************************************************************ 977/*
920 978 * pcm ops
921 979 */
922 pcm ops
923
924 980
925************************************************************************/
926static struct snd_pcm_hardware fsi_pcm_hardware = { 981static struct snd_pcm_hardware fsi_pcm_hardware = {
927 .info = SNDRV_PCM_INFO_INTERLEAVED | 982 .info = SNDRV_PCM_INFO_INTERLEAVED |
928 SNDRV_PCM_INFO_MMAP | 983 SNDRV_PCM_INFO_MMAP |
@@ -971,9 +1026,10 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
971{ 1026{
972 struct snd_pcm_runtime *runtime = substream->runtime; 1027 struct snd_pcm_runtime *runtime = substream->runtime;
973 struct fsi_priv *fsi = fsi_get_priv(substream); 1028 struct fsi_priv *fsi = fsi_get_priv(substream);
1029 struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
974 long location; 1030 long location;
975 1031
976 location = (fsi->byte_offset - 1); 1032 location = (io->buff_offset - 1);
977 if (location < 0) 1033 if (location < 0)
978 location = 0; 1034 location = 0;
979 1035
@@ -988,13 +1044,10 @@ static struct snd_pcm_ops fsi_pcm_ops = {
988 .pointer = fsi_pointer, 1044 .pointer = fsi_pointer,
989}; 1045};
990 1046
991/************************************************************************ 1047/*
992 1048 * snd_soc_platform
993 1049 */
994 snd_soc_platform
995
996 1050
997************************************************************************/
998#define PREALLOC_BUFFER (32 * 1024) 1051#define PREALLOC_BUFFER (32 * 1024)
999#define PREALLOC_BUFFER_MAX (32 * 1024) 1052#define PREALLOC_BUFFER_MAX (32 * 1024)
1000 1053
@@ -1018,17 +1071,13 @@ static int fsi_pcm_new(struct snd_card *card,
1018 PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); 1071 PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
1019} 1072}
1020 1073
1021/************************************************************************ 1074/*
1022 1075 * alsa struct
1023 1076 */
1024 alsa struct
1025
1026 1077
1027************************************************************************/ 1078static struct snd_soc_dai_driver fsi_soc_dai[] = {
1028struct snd_soc_dai fsi_soc_dai[] = {
1029 { 1079 {
1030 .name = "FSIA", 1080 .name = "fsia-dai",
1031 .id = 0,
1032 .playback = { 1081 .playback = {
1033 .rates = FSI_RATES, 1082 .rates = FSI_RATES,
1034 .formats = FSI_FMTS, 1083 .formats = FSI_FMTS,
@@ -1044,8 +1093,7 @@ struct snd_soc_dai fsi_soc_dai[] = {
1044 .ops = &fsi_dai_ops, 1093 .ops = &fsi_dai_ops,
1045 }, 1094 },
1046 { 1095 {
1047 .name = "FSIB", 1096 .name = "fsib-dai",
1048 .id = 1,
1049 .playback = { 1097 .playback = {
1050 .rates = FSI_RATES, 1098 .rates = FSI_RATES,
1051 .formats = FSI_FMTS, 1099 .formats = FSI_FMTS,
@@ -1061,23 +1109,17 @@ struct snd_soc_dai fsi_soc_dai[] = {
1061 .ops = &fsi_dai_ops, 1109 .ops = &fsi_dai_ops,
1062 }, 1110 },
1063}; 1111};
1064EXPORT_SYMBOL_GPL(fsi_soc_dai);
1065 1112
1066struct snd_soc_platform fsi_soc_platform = { 1113static struct snd_soc_platform_driver fsi_soc_platform = {
1067 .name = "fsi-pcm", 1114 .ops = &fsi_pcm_ops,
1068 .pcm_ops = &fsi_pcm_ops,
1069 .pcm_new = fsi_pcm_new, 1115 .pcm_new = fsi_pcm_new,
1070 .pcm_free = fsi_pcm_free, 1116 .pcm_free = fsi_pcm_free,
1071}; 1117};
1072EXPORT_SYMBOL_GPL(fsi_soc_platform);
1073
1074/************************************************************************
1075
1076
1077 platform function
1078 1118
1119/*
1120 * platform function
1121 */
1079 1122
1080************************************************************************/
1081static int fsi_probe(struct platform_device *pdev) 1123static int fsi_probe(struct platform_device *pdev)
1082{ 1124{
1083 struct fsi_master *master; 1125 struct fsi_master *master;
@@ -1132,11 +1174,7 @@ static int fsi_probe(struct platform_device *pdev)
1132 1174
1133 pm_runtime_enable(&pdev->dev); 1175 pm_runtime_enable(&pdev->dev);
1134 pm_runtime_resume(&pdev->dev); 1176 pm_runtime_resume(&pdev->dev);
1135 1177 dev_set_drvdata(&pdev->dev, master);
1136 fsi_soc_dai[0].dev = &pdev->dev;
1137 fsi_soc_dai[0].private_data = &master->fsia;
1138 fsi_soc_dai[1].dev = &pdev->dev;
1139 fsi_soc_dai[1].private_data = &master->fsib;
1140 1178
1141 fsi_soft_all_reset(master); 1179 fsi_soft_all_reset(master);
1142 1180
@@ -1147,13 +1185,13 @@ static int fsi_probe(struct platform_device *pdev)
1147 goto exit_iounmap; 1185 goto exit_iounmap;
1148 } 1186 }
1149 1187
1150 ret = snd_soc_register_platform(&fsi_soc_platform); 1188 ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
1151 if (ret < 0) { 1189 if (ret < 0) {
1152 dev_err(&pdev->dev, "cannot snd soc register\n"); 1190 dev_err(&pdev->dev, "cannot snd soc register\n");
1153 goto exit_free_irq; 1191 goto exit_free_irq;
1154 } 1192 }
1155 1193
1156 return snd_soc_register_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); 1194 return snd_soc_register_dais(&pdev->dev, fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
1157 1195
1158exit_free_irq: 1196exit_free_irq:
1159 free_irq(irq, master); 1197 free_irq(irq, master);
@@ -1171,10 +1209,10 @@ static int fsi_remove(struct platform_device *pdev)
1171{ 1209{
1172 struct fsi_master *master; 1210 struct fsi_master *master;
1173 1211
1174 master = fsi_get_master(fsi_soc_dai[0].private_data); 1212 master = dev_get_drvdata(&pdev->dev);
1175 1213
1176 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); 1214 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
1177 snd_soc_unregister_platform(&fsi_soc_platform); 1215 snd_soc_unregister_platform(&pdev->dev);
1178 1216
1179 pm_runtime_disable(&pdev->dev); 1217 pm_runtime_disable(&pdev->dev);
1180 1218
@@ -1183,11 +1221,6 @@ static int fsi_remove(struct platform_device *pdev)
1183 iounmap(master->base); 1221 iounmap(master->base);
1184 kfree(master); 1222 kfree(master);
1185 1223
1186 fsi_soc_dai[0].dev = NULL;
1187 fsi_soc_dai[0].private_data = NULL;
1188 fsi_soc_dai[1].dev = NULL;
1189 fsi_soc_dai[1].private_data = NULL;
1190
1191 return 0; 1224 return 0;
1192} 1225}
1193 1226
@@ -1229,11 +1262,13 @@ static struct fsi_core fsi2_core = {
1229static struct platform_device_id fsi_id_table[] = { 1262static struct platform_device_id fsi_id_table[] = {
1230 { "sh_fsi", (kernel_ulong_t)&fsi1_core }, 1263 { "sh_fsi", (kernel_ulong_t)&fsi1_core },
1231 { "sh_fsi2", (kernel_ulong_t)&fsi2_core }, 1264 { "sh_fsi2", (kernel_ulong_t)&fsi2_core },
1265 {},
1232}; 1266};
1267MODULE_DEVICE_TABLE(platform, fsi_id_table);
1233 1268
1234static struct platform_driver fsi_driver = { 1269static struct platform_driver fsi_driver = {
1235 .driver = { 1270 .driver = {
1236 .name = "sh_fsi", 1271 .name = "fsi-pcm-audio",
1237 .pm = &fsi_pm_ops, 1272 .pm = &fsi_pm_ops,
1238 }, 1273 },
1239 .probe = fsi_probe, 1274 .probe = fsi_probe,
@@ -1250,6 +1285,7 @@ static void __exit fsi_mobile_exit(void)
1250{ 1285{
1251 platform_driver_unregister(&fsi_driver); 1286 platform_driver_unregister(&fsi_driver);
1252} 1287}
1288
1253module_init(fsi_mobile_init); 1289module_init(fsi_mobile_init);
1254module_exit(fsi_mobile_exit); 1290module_exit(fsi_mobile_exit);
1255 1291
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index 41db75af3c69..c87e3ff28a0a 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -239,8 +239,7 @@ static int hac_hw_params(struct snd_pcm_substream *substream,
239 struct snd_pcm_hw_params *params, 239 struct snd_pcm_hw_params *params,
240 struct snd_soc_dai *dai) 240 struct snd_soc_dai *dai)
241{ 241{
242 struct snd_soc_pcm_runtime *rtd = substream->private_data; 242 struct hac_priv *hac = &hac_cpu_data[dai->id];
243 struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id];
244 int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; 243 int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
245 244
246 switch (params->msbits) { 245 switch (params->msbits) {
@@ -271,10 +270,9 @@ static struct snd_soc_dai_ops hac_dai_ops = {
271 .hw_params = hac_hw_params, 270 .hw_params = hac_hw_params,
272}; 271};
273 272
274struct snd_soc_dai sh4_hac_dai[] = { 273static struct snd_soc_dai_driver sh4_hac_dai[] = {
275{ 274{
276 .name = "HAC0", 275 .name = "hac-dai.0",
277 .id = 0,
278 .ac97_control = 1, 276 .ac97_control = 1,
279 .playback = { 277 .playback = {
280 .rates = AC97_RATES, 278 .rates = AC97_RATES,
@@ -292,8 +290,7 @@ struct snd_soc_dai sh4_hac_dai[] = {
292}, 290},
293#ifdef CONFIG_CPU_SUBTYPE_SH7760 291#ifdef CONFIG_CPU_SUBTYPE_SH7760
294{ 292{
295 .name = "HAC1", 293 .name = "hac-dai.1",
296 .ac97_control = 1,
297 .id = 1, 294 .id = 1,
298 .playback = { 295 .playback = {
299 .rates = AC97_RATES, 296 .rates = AC97_RATES,
@@ -312,19 +309,40 @@ struct snd_soc_dai sh4_hac_dai[] = {
312}, 309},
313#endif 310#endif
314}; 311};
315EXPORT_SYMBOL_GPL(sh4_hac_dai);
316 312
317static int __init sh4_hac_init(void) 313static int __devinit hac_soc_platform_probe(struct platform_device *pdev)
314{
315 return snd_soc_register_dais(&pdev->dev, sh4_hac_dai,
316 ARRAY_SIZE(sh4_hac_dai));
317}
318
319static int __devexit hac_soc_platform_remove(struct platform_device *pdev)
320{
321 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(sh4_hac_dai));
322 return 0;
323}
324
325static struct platform_driver hac_pcm_driver = {
326 .driver = {
327 .name = "hac-pcm-audio",
328 .owner = THIS_MODULE,
329 },
330
331 .probe = hac_soc_platform_probe,
332 .remove = __devexit_p(hac_soc_platform_remove),
333};
334
335static int __init sh4_hac_pcm_init(void)
318{ 336{
319 return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); 337 return platform_driver_register(&hac_pcm_driver);
320} 338}
321module_init(sh4_hac_init); 339module_init(sh4_hac_pcm_init);
322 340
323static void __exit sh4_hac_exit(void) 341static void __exit sh4_hac_pcm_exit(void)
324{ 342{
325 snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); 343 platform_driver_unregister(&hac_pcm_driver);
326} 344}
327module_exit(sh4_hac_exit); 345module_exit(sh4_hac_pcm_exit);
328 346
329MODULE_LICENSE("GPL"); 347MODULE_LICENSE("GPL");
330MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); 348MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c
index 87e2b7fcbf17..ac6c49ce6fdf 100644
--- a/sound/soc/sh/migor.c
+++ b/sound/soc/sh/migor.c
@@ -51,7 +51,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,
51 struct snd_pcm_hw_params *params) 51 struct snd_pcm_hw_params *params)
52{ 52{
53 struct snd_soc_pcm_runtime *rtd = substream->private_data; 53 struct snd_soc_pcm_runtime *rtd = substream->private_data;
54 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 54 struct snd_soc_dai *codec_dai = rtd->codec_dai;
55 int ret; 55 int ret;
56 unsigned int rate = params_rate(params); 56 unsigned int rate = params_rate(params);
57 57
@@ -69,7 +69,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,
69 if (ret < 0) 69 if (ret < 0)
70 return ret; 70 return ret;
71 71
72 ret = snd_soc_dai_set_fmt(rtd->dai->cpu_dai, SND_SOC_DAIFMT_NB_IF | 72 ret = snd_soc_dai_set_fmt(rtd->cpu_dai, SND_SOC_DAIFMT_NB_IF |
73 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS); 73 SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS);
74 if (ret < 0) 74 if (ret < 0)
75 return ret; 75 return ret;
@@ -82,7 +82,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,
82 clk_set_rate(&siumckb_clk, codec_freq); 82 clk_set_rate(&siumckb_clk, codec_freq);
83 dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq); 83 dev_dbg(codec_dai->dev, "%s: configure %luHz\n", __func__, codec_freq);
84 84
85 ret = snd_soc_dai_set_sysclk(rtd->dai->cpu_dai, SIU_CLKB_EXT, 85 ret = snd_soc_dai_set_sysclk(rtd->cpu_dai, SIU_CLKB_EXT,
86 codec_freq / 2, SND_SOC_CLOCK_IN); 86 codec_freq / 2, SND_SOC_CLOCK_IN);
87 87
88 if (!ret) 88 if (!ret)
@@ -94,7 +94,7 @@ static int migor_hw_params(struct snd_pcm_substream *substream,
94static int migor_hw_free(struct snd_pcm_substream *substream) 94static int migor_hw_free(struct snd_pcm_substream *substream)
95{ 95{
96 struct snd_soc_pcm_runtime *rtd = substream->private_data; 96 struct snd_soc_pcm_runtime *rtd = substream->private_data;
97 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 97 struct snd_soc_dai *codec_dai = rtd->codec_dai;
98 98
99 if (use_count) { 99 if (use_count) {
100 use_count--; 100 use_count--;
@@ -137,8 +137,10 @@ static const struct snd_soc_dapm_route audio_map[] = {
137 { "Mic Bias", NULL, "External Microphone" }, 137 { "Mic Bias", NULL, "External Microphone" },
138}; 138};
139 139
140static int migor_dai_init(struct snd_soc_codec *codec) 140static int migor_dai_init(struct snd_soc_pcm_runtime *rtd)
141{ 141{
142 struct snd_soc_codec *codec = rtd->codec;
143
142 snd_soc_dapm_new_controls(codec, migor_dapm_widgets, 144 snd_soc_dapm_new_controls(codec, migor_dapm_widgets,
143 ARRAY_SIZE(migor_dapm_widgets)); 145 ARRAY_SIZE(migor_dapm_widgets));
144 146
@@ -151,8 +153,10 @@ static int migor_dai_init(struct snd_soc_codec *codec)
151static struct snd_soc_dai_link migor_dai = { 153static struct snd_soc_dai_link migor_dai = {
152 .name = "wm8978", 154 .name = "wm8978",
153 .stream_name = "WM8978", 155 .stream_name = "WM8978",
154 .cpu_dai = &siu_i2s_dai, 156 .cpu_dai_name = "siu-i2s-dai",
155 .codec_dai = &wm8978_dai, 157 .codec_dai_name = "wm8978-hifi",
158 .platform_name = "siu-pcm-audio",
159 .codec_name = "wm8978.0-001a",
156 .ops = &migor_dai_ops, 160 .ops = &migor_dai_ops,
157 .init = migor_dai_init, 161 .init = migor_dai_init,
158}; 162};
@@ -160,17 +164,10 @@ static struct snd_soc_dai_link migor_dai = {
160/* migor audio machine driver */ 164/* migor audio machine driver */
161static struct snd_soc_card snd_soc_migor = { 165static struct snd_soc_card snd_soc_migor = {
162 .name = "Migo-R", 166 .name = "Migo-R",
163 .platform = &siu_platform,
164 .dai_link = &migor_dai, 167 .dai_link = &migor_dai,
165 .num_links = 1, 168 .num_links = 1,
166}; 169};
167 170
168/* migor audio subsystem */
169static struct snd_soc_device migor_snd_devdata = {
170 .card = &snd_soc_migor,
171 .codec_dev = &soc_codec_dev_wm8978,
172};
173
174static struct platform_device *migor_snd_device; 171static struct platform_device *migor_snd_device;
175 172
176static int __init migor_init(void) 173static int __init migor_init(void)
@@ -195,9 +192,7 @@ static int __init migor_init(void)
195 goto epdevalloc; 192 goto epdevalloc;
196 } 193 }
197 194
198 platform_set_drvdata(migor_snd_device, &migor_snd_devdata); 195 platform_set_drvdata(migor_snd_device, &snd_soc_migor);
199
200 migor_snd_devdata.dev = &migor_snd_device->dev;
201 196
202 ret = platform_device_add(migor_snd_device); 197 ret = platform_device_add(migor_snd_device);
203 if (ret) 198 if (ret)
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c
index ce7f95b59de3..b897f7b96d89 100644
--- a/sound/soc/sh/sh7760-ac97.c
+++ b/sound/soc/sh/sh7760-ac97.c
@@ -15,41 +15,35 @@
15#include <sound/soc-dapm.h> 15#include <sound/soc-dapm.h>
16#include <asm/io.h> 16#include <asm/io.h>
17 17
18#include "../codecs/ac97.h"
19
20#define IPSEL 0xFE400034 18#define IPSEL 0xFE400034
21 19
22/* platform specific structs can be declared here */ 20/* platform specific structs can be declared here */
23extern struct snd_soc_dai sh4_hac_dai[2]; 21extern struct snd_soc_dai_driver sh4_hac_dai[2];
24extern struct snd_soc_platform sh7760_soc_platform; 22extern struct snd_soc_platform_driver sh7760_soc_platform;
25 23
26static int machine_init(struct snd_soc_codec *codec) 24static int machine_init(struct snd_soc_pcm_runtime *rtd)
27{ 25{
28 snd_soc_dapm_sync(codec); 26 snd_soc_dapm_sync(rtd->codec);
29 return 0; 27 return 0;
30} 28}
31 29
32static struct snd_soc_dai_link sh7760_ac97_dai = { 30static struct snd_soc_dai_link sh7760_ac97_dai = {
33 .name = "AC97", 31 .name = "AC97",
34 .stream_name = "AC97 HiFi", 32 .stream_name = "AC97 HiFi",
35 .cpu_dai = &sh4_hac_dai[0], /* HAC0 */ 33 .cpu_dai_name = "hac-dai.0", /* HAC0 */
36 .codec_dai = &ac97_dai, 34 .codec_dai_name = "ac97-hifi",
35 .platform_name = "sh7760-pcm-audio",
36 .codec_name = "ac97-codec",
37 .init = machine_init, 37 .init = machine_init,
38 .ops = NULL, 38 .ops = NULL,
39}; 39};
40 40
41static struct snd_soc_card sh7760_ac97_soc_machine = { 41static struct snd_soc_card sh7760_ac97_soc_machine = {
42 .name = "SH7760 AC97", 42 .name = "SH7760 AC97",
43 .platform = &sh7760_soc_platform,
44 .dai_link = &sh7760_ac97_dai, 43 .dai_link = &sh7760_ac97_dai,
45 .num_links = 1, 44 .num_links = 1,
46}; 45};
47 46
48static struct snd_soc_device sh7760_ac97_snd_devdata = {
49 .card = &sh7760_ac97_soc_machine,
50 .codec_dev = &soc_codec_dev_ac97,
51};
52
53static struct platform_device *sh7760_ac97_snd_device; 47static struct platform_device *sh7760_ac97_snd_device;
54 48
55static int __init sh7760_ac97_init(void) 49static int __init sh7760_ac97_init(void)
@@ -67,8 +61,7 @@ static int __init sh7760_ac97_init(void)
67 goto out; 61 goto out;
68 62
69 platform_set_drvdata(sh7760_ac97_snd_device, 63 platform_set_drvdata(sh7760_ac97_snd_device,
70 &sh7760_ac97_snd_devdata); 64 &sh7760_ac97_soc_machine);
71 sh7760_ac97_snd_devdata.dev = &sh7760_ac97_snd_device->dev;
72 ret = platform_device_add(sh7760_ac97_snd_device); 65 ret = platform_device_add(sh7760_ac97_snd_device);
73 66
74 if (ret) 67 if (ret)
diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h
index 492b1cae24cc..9f4dcb921ff0 100644
--- a/sound/soc/sh/siu.h
+++ b/sound/soc/sh/siu.h
@@ -98,7 +98,9 @@ enum {
98 SIU_CLKB_EXT 98 SIU_CLKB_EXT
99}; 99};
100 100
101struct device;
101struct siu_info { 102struct siu_info {
103 struct device *dev;
102 int port_id; 104 int port_id;
103 u32 __iomem *pram; 105 u32 __iomem *pram;
104 u32 __iomem *xram; 106 u32 __iomem *xram;
@@ -181,8 +183,8 @@ static inline u32 siu_read32(u32 __iomem *addr)
181#define SIU_BRGBSEL (0x108 / sizeof(u32)) 183#define SIU_BRGBSEL (0x108 / sizeof(u32))
182#define SIU_BRRB (0x10c / sizeof(u32)) 184#define SIU_BRRB (0x10c / sizeof(u32))
183 185
184extern struct snd_soc_platform siu_platform; 186extern struct snd_soc_platform_driver siu_platform;
185extern struct snd_soc_dai siu_i2s_dai; 187extern struct siu_info *siu_i2s_data;
186 188
187int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card); 189int siu_init_port(int port, struct siu_port **port_info, struct snd_card *card);
188void siu_free_port(struct siu_port *port_info); 190void siu_free_port(struct siu_port *port_info);
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index eeed5edd722b..af53b64d8af2 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -71,6 +71,8 @@ struct port_flag {
71 struct format_flag capture; 71 struct format_flag capture;
72}; 72};
73 73
74struct siu_info *siu_i2s_data;
75
74static struct port_flag siu_flags[SIU_PORT_NUM] = { 76static struct port_flag siu_flags[SIU_PORT_NUM] = {
75 [SIU_PORT_A] = { 77 [SIU_PORT_A] = {
76 .playback = { 78 .playback = {
@@ -104,13 +106,13 @@ static struct port_flag siu_flags[SIU_PORT_NUM] = {
104 106
105static void siu_dai_start(struct siu_port *port_info) 107static void siu_dai_start(struct siu_port *port_info)
106{ 108{
107 struct siu_info *info = siu_i2s_dai.private_data; 109 struct siu_info *info = siu_i2s_data;
108 u32 __iomem *base = info->reg; 110 u32 __iomem *base = info->reg;
109 111
110 dev_dbg(port_info->pcm->card->dev, "%s\n", __func__); 112 dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
111 113
112 /* Turn on SIU clock */ 114 /* Turn on SIU clock */
113 pm_runtime_get_sync(siu_i2s_dai.dev); 115 pm_runtime_get_sync(info->dev);
114 116
115 /* Issue software reset to siu */ 117 /* Issue software reset to siu */
116 siu_write32(base + SIU_SRCTL, 0); 118 siu_write32(base + SIU_SRCTL, 0);
@@ -148,21 +150,21 @@ static void siu_dai_start(struct siu_port *port_info)
148 siu_write32(base + SIU_SBDVCB, port_info->capture.volume); 150 siu_write32(base + SIU_SBDVCB, port_info->capture.volume);
149} 151}
150 152
151static void siu_dai_stop(void) 153static void siu_dai_stop(struct siu_port *port_info)
152{ 154{
153 struct siu_info *info = siu_i2s_dai.private_data; 155 struct siu_info *info = siu_i2s_data;
154 u32 __iomem *base = info->reg; 156 u32 __iomem *base = info->reg;
155 157
156 /* SIU software reset */ 158 /* SIU software reset */
157 siu_write32(base + SIU_SRCTL, 0); 159 siu_write32(base + SIU_SRCTL, 0);
158 160
159 /* Turn off SIU clock */ 161 /* Turn off SIU clock */
160 pm_runtime_put_sync(siu_i2s_dai.dev); 162 pm_runtime_put_sync(info->dev);
161} 163}
162 164
163static void siu_dai_spbAselect(struct siu_port *port_info) 165static void siu_dai_spbAselect(struct siu_port *port_info)
164{ 166{
165 struct siu_info *info = siu_i2s_dai.private_data; 167 struct siu_info *info = siu_i2s_data;
166 struct siu_firmware *fw = &info->fw; 168 struct siu_firmware *fw = &info->fw;
167 u32 *ydef = fw->yram0; 169 u32 *ydef = fw->yram0;
168 u32 idx; 170 u32 idx;
@@ -187,7 +189,7 @@ static void siu_dai_spbAselect(struct siu_port *port_info)
187 189
188static void siu_dai_spbBselect(struct siu_port *port_info) 190static void siu_dai_spbBselect(struct siu_port *port_info)
189{ 191{
190 struct siu_info *info = siu_i2s_dai.private_data; 192 struct siu_info *info = siu_i2s_data;
191 struct siu_firmware *fw = &info->fw; 193 struct siu_firmware *fw = &info->fw;
192 u32 *ydef = fw->yram0; 194 u32 *ydef = fw->yram0;
193 u32 idx; 195 u32 idx;
@@ -207,7 +209,7 @@ static void siu_dai_spbBselect(struct siu_port *port_info)
207 209
208static void siu_dai_open(struct siu_stream *siu_stream) 210static void siu_dai_open(struct siu_stream *siu_stream)
209{ 211{
210 struct siu_info *info = siu_i2s_dai.private_data; 212 struct siu_info *info = siu_i2s_data;
211 u32 __iomem *base = info->reg; 213 u32 __iomem *base = info->reg;
212 u32 srctl, ifctl; 214 u32 srctl, ifctl;
213 215
@@ -238,7 +240,7 @@ static void siu_dai_open(struct siu_stream *siu_stream)
238 */ 240 */
239static void siu_dai_pcmdatapack(struct siu_stream *siu_stream) 241static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)
240{ 242{
241 struct siu_info *info = siu_i2s_dai.private_data; 243 struct siu_info *info = siu_i2s_data;
242 u32 __iomem *base = info->reg; 244 u32 __iomem *base = info->reg;
243 u32 dpak; 245 u32 dpak;
244 246
@@ -258,7 +260,7 @@ static void siu_dai_pcmdatapack(struct siu_stream *siu_stream)
258 260
259static int siu_dai_spbstart(struct siu_port *port_info) 261static int siu_dai_spbstart(struct siu_port *port_info)
260{ 262{
261 struct siu_info *info = siu_i2s_dai.private_data; 263 struct siu_info *info = siu_i2s_data;
262 u32 __iomem *base = info->reg; 264 u32 __iomem *base = info->reg;
263 struct siu_firmware *fw = &info->fw; 265 struct siu_firmware *fw = &info->fw;
264 u32 *ydef = fw->yram0; 266 u32 *ydef = fw->yram0;
@@ -323,7 +325,7 @@ static int siu_dai_spbstart(struct siu_port *port_info)
323 325
324static void siu_dai_spbstop(struct siu_port *port_info) 326static void siu_dai_spbstop(struct siu_port *port_info)
325{ 327{
326 struct siu_info *info = siu_i2s_dai.private_data; 328 struct siu_info *info = siu_i2s_data;
327 u32 __iomem *base = info->reg; 329 u32 __iomem *base = info->reg;
328 330
329 siu_write32(base + SIU_SBACTIV, 0); 331 siu_write32(base + SIU_SBACTIV, 0);
@@ -402,7 +404,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl,
402{ 404{
403 struct siu_port *port_info = snd_kcontrol_chip(kctrl); 405 struct siu_port *port_info = snd_kcontrol_chip(kctrl);
404 struct device *dev = port_info->pcm->card->dev; 406 struct device *dev = port_info->pcm->card->dev;
405 struct siu_info *info = siu_i2s_dai.private_data; 407 struct siu_info *info = siu_i2s_data;
406 u32 __iomem *base = info->reg; 408 u32 __iomem *base = info->reg;
407 u32 new_vol; 409 u32 new_vol;
408 u32 cur_vol; 410 u32 cur_vol;
@@ -510,7 +512,7 @@ void siu_free_port(struct siu_port *port_info)
510static int siu_dai_startup(struct snd_pcm_substream *substream, 512static int siu_dai_startup(struct snd_pcm_substream *substream,
511 struct snd_soc_dai *dai) 513 struct snd_soc_dai *dai)
512{ 514{
513 struct siu_info *info = siu_i2s_dai.private_data; 515 struct siu_info *info = snd_soc_dai_get_drvdata(dai);
514 struct snd_pcm_runtime *rt = substream->runtime; 516 struct snd_pcm_runtime *rt = substream->runtime;
515 struct siu_port *port_info = siu_port_info(substream); 517 struct siu_port *port_info = siu_port_info(substream);
516 int ret; 518 int ret;
@@ -532,7 +534,7 @@ static int siu_dai_startup(struct snd_pcm_substream *substream,
532static void siu_dai_shutdown(struct snd_pcm_substream *substream, 534static void siu_dai_shutdown(struct snd_pcm_substream *substream,
533 struct snd_soc_dai *dai) 535 struct snd_soc_dai *dai)
534{ 536{
535 struct siu_info *info = siu_i2s_dai.private_data; 537 struct siu_info *info = snd_soc_dai_get_drvdata(dai);
536 struct siu_port *port_info = siu_port_info(substream); 538 struct siu_port *port_info = siu_port_info(substream);
537 539
538 dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__, 540 dev_dbg(substream->pcm->card->dev, "%s: port=%d@%p\n", __func__,
@@ -548,7 +550,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream,
548 /* during stmread or stmwrite ? */ 550 /* during stmread or stmwrite ? */
549 BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg); 551 BUG_ON(port_info->playback.rw_flg || port_info->capture.rw_flg);
550 siu_dai_spbstop(port_info); 552 siu_dai_spbstop(port_info);
551 siu_dai_stop(); 553 siu_dai_stop(port_info);
552 } 554 }
553} 555}
554 556
@@ -556,7 +558,7 @@ static void siu_dai_shutdown(struct snd_pcm_substream *substream,
556static int siu_dai_prepare(struct snd_pcm_substream *substream, 558static int siu_dai_prepare(struct snd_pcm_substream *substream,
557 struct snd_soc_dai *dai) 559 struct snd_soc_dai *dai)
558{ 560{
559 struct siu_info *info = siu_i2s_dai.private_data; 561 struct siu_info *info = snd_soc_dai_get_drvdata(dai);
560 struct snd_pcm_runtime *rt = substream->runtime; 562 struct snd_pcm_runtime *rt = substream->runtime;
561 struct siu_port *port_info = siu_port_info(substream); 563 struct siu_port *port_info = siu_port_info(substream);
562 struct siu_stream *siu_stream; 564 struct siu_stream *siu_stream;
@@ -605,7 +607,7 @@ fail:
605static int siu_dai_set_fmt(struct snd_soc_dai *dai, 607static int siu_dai_set_fmt(struct snd_soc_dai *dai,
606 unsigned int fmt) 608 unsigned int fmt)
607{ 609{
608 struct siu_info *info = siu_i2s_dai.private_data; 610 struct siu_info *info = snd_soc_dai_get_drvdata(dai);
609 u32 __iomem *base = info->reg; 611 u32 __iomem *base = info->reg;
610 u32 ifctl; 612 u32 ifctl;
611 613
@@ -671,21 +673,37 @@ static int siu_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
671 return -EINVAL; 673 return -EINVAL;
672 } 674 }
673 675
674 siu_clk = clk_get(siu_i2s_dai.dev, siu_name); 676 siu_clk = clk_get(dai->dev, siu_name);
675 if (IS_ERR(siu_clk)) 677 if (IS_ERR(siu_clk)) {
678 dev_err(dai->dev, "%s: cannot get a SIU clock: %ld\n", __func__,
679 PTR_ERR(siu_clk));
676 return PTR_ERR(siu_clk); 680 return PTR_ERR(siu_clk);
681 }
682
683 parent_clk = clk_get(dai->dev, parent_name);
684 if (IS_ERR(parent_clk)) {
685 ret = PTR_ERR(parent_clk);
686 dev_err(dai->dev, "cannot get a SIU clock parent: %d\n", ret);
687 goto epclkget;
688 }
677 689
678 parent_clk = clk_get(siu_i2s_dai.dev, parent_name); 690 ret = clk_set_parent(siu_clk, parent_clk);
679 if (!IS_ERR(parent_clk)) { 691 if (ret < 0) {
680 ret = clk_set_parent(siu_clk, parent_clk); 692 dev_err(dai->dev, "cannot reparent the SIU clock: %d\n", ret);
681 if (!ret) 693 goto eclksetp;
682 clk_set_rate(siu_clk, freq);
683 clk_put(parent_clk);
684 } 694 }
685 695
696 ret = clk_set_rate(siu_clk, freq);
697 if (ret < 0)
698 dev_err(dai->dev, "cannot set SIU clock rate: %d\n", ret);
699
700 /* TODO: when clkdev gets reference counting we'll move these to siu_dai_shutdown() */
701eclksetp:
702 clk_put(parent_clk);
703epclkget:
686 clk_put(siu_clk); 704 clk_put(siu_clk);
687 705
688 return 0; 706 return ret;
689} 707}
690 708
691static struct snd_soc_dai_ops siu_dai_ops = { 709static struct snd_soc_dai_ops siu_dai_ops = {
@@ -696,9 +714,8 @@ static struct snd_soc_dai_ops siu_dai_ops = {
696 .set_fmt = siu_dai_set_fmt, 714 .set_fmt = siu_dai_set_fmt,
697}; 715};
698 716
699struct snd_soc_dai siu_i2s_dai = { 717static struct snd_soc_dai_driver siu_i2s_dai = {
700 .name = "sh-siu", 718 .name = "siu-i2s-dai",
701 .id = 0,
702 .playback = { 719 .playback = {
703 .channels_min = 2, 720 .channels_min = 2,
704 .channels_max = 2, 721 .channels_max = 2,
@@ -713,7 +730,6 @@ struct snd_soc_dai siu_i2s_dai = {
713 }, 730 },
714 .ops = &siu_dai_ops, 731 .ops = &siu_dai_ops,
715}; 732};
716EXPORT_SYMBOL_GPL(siu_i2s_dai);
717 733
718static int __devinit siu_probe(struct platform_device *pdev) 734static int __devinit siu_probe(struct platform_device *pdev)
719{ 735{
@@ -725,6 +741,8 @@ static int __devinit siu_probe(struct platform_device *pdev)
725 info = kmalloc(sizeof(*info), GFP_KERNEL); 741 info = kmalloc(sizeof(*info), GFP_KERNEL);
726 if (!info) 742 if (!info)
727 return -ENOMEM; 743 return -ENOMEM;
744 siu_i2s_data = info;
745 info->dev = &pdev->dev;
728 746
729 ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev); 747 ret = request_firmware(&fw_entry, "siu_spb.bin", &pdev->dev);
730 if (ret) 748 if (ret)
@@ -767,14 +785,14 @@ static int __devinit siu_probe(struct platform_device *pdev)
767 if (!info->reg) 785 if (!info->reg)
768 goto emapreg; 786 goto emapreg;
769 787
770 siu_i2s_dai.dev = &pdev->dev; 788 dev_set_drvdata(&pdev->dev, info);
771 siu_i2s_dai.private_data = info;
772 789
773 ret = snd_soc_register_dais(&siu_i2s_dai, 1); 790 /* register using ARRAY version so we can keep dai name */
791 ret = snd_soc_register_dais(&pdev->dev, &siu_i2s_dai, 1);
774 if (ret < 0) 792 if (ret < 0)
775 goto edaiinit; 793 goto edaiinit;
776 794
777 ret = snd_soc_register_platform(&siu_platform); 795 ret = snd_soc_register_platform(&pdev->dev, &siu_platform);
778 if (ret < 0) 796 if (ret < 0)
779 goto esocregp; 797 goto esocregp;
780 798
@@ -783,7 +801,7 @@ static int __devinit siu_probe(struct platform_device *pdev)
783 return ret; 801 return ret;
784 802
785esocregp: 803esocregp:
786 snd_soc_unregister_dais(&siu_i2s_dai, 1); 804 snd_soc_unregister_dai(&pdev->dev);
787edaiinit: 805edaiinit:
788 iounmap(info->reg); 806 iounmap(info->reg);
789emapreg: 807emapreg:
@@ -804,13 +822,13 @@ ereqfw:
804 822
805static int __devexit siu_remove(struct platform_device *pdev) 823static int __devexit siu_remove(struct platform_device *pdev)
806{ 824{
807 struct siu_info *info = siu_i2s_dai.private_data; 825 struct siu_info *info = dev_get_drvdata(&pdev->dev);
808 struct resource *res; 826 struct resource *res;
809 827
810 pm_runtime_disable(&pdev->dev); 828 pm_runtime_disable(&pdev->dev);
811 829
812 snd_soc_unregister_platform(&siu_platform); 830 snd_soc_unregister_platform(&pdev->dev);
813 snd_soc_unregister_dais(&siu_i2s_dai, 1); 831 snd_soc_unregister_dai(&pdev->dev);
814 832
815 iounmap(info->reg); 833 iounmap(info->reg);
816 iounmap(info->yram); 834 iounmap(info->yram);
@@ -826,7 +844,8 @@ static int __devexit siu_remove(struct platform_device *pdev)
826 844
827static struct platform_driver siu_driver = { 845static struct platform_driver siu_driver = {
828 .driver = { 846 .driver = {
829 .name = "sh_siu", 847 .owner = THIS_MODULE,
848 .name = "siu-pcm-audio",
830 }, 849 },
831 .probe = siu_probe, 850 .probe = siu_probe,
832 .remove = __devexit_p(siu_remove), 851 .remove = __devexit_p(siu_remove),
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index b0ccd0b862fc..ed29c9e1ed4e 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -48,7 +48,7 @@ struct siu_port *siu_ports[SIU_PORT_NUM];
48/* transfersize is number of u32 dma transfers per period */ 48/* transfersize is number of u32 dma transfers per period */
49static int siu_pcm_stmwrite_stop(struct siu_port *port_info) 49static int siu_pcm_stmwrite_stop(struct siu_port *port_info)
50{ 50{
51 struct siu_info *info = siu_i2s_dai.private_data; 51 struct siu_info *info = siu_i2s_data;
52 u32 __iomem *base = info->reg; 52 u32 __iomem *base = info->reg;
53 struct siu_stream *siu_stream = &port_info->playback; 53 struct siu_stream *siu_stream = &port_info->playback;
54 u32 stfifo; 54 u32 stfifo;
@@ -114,7 +114,7 @@ static void siu_dma_tx_complete(void *arg)
114static int siu_pcm_wr_set(struct siu_port *port_info, 114static int siu_pcm_wr_set(struct siu_port *port_info,
115 dma_addr_t buff, u32 size) 115 dma_addr_t buff, u32 size)
116{ 116{
117 struct siu_info *info = siu_i2s_dai.private_data; 117 struct siu_info *info = siu_i2s_data;
118 u32 __iomem *base = info->reg; 118 u32 __iomem *base = info->reg;
119 struct siu_stream *siu_stream = &port_info->playback; 119 struct siu_stream *siu_stream = &port_info->playback;
120 struct snd_pcm_substream *substream = siu_stream->substream; 120 struct snd_pcm_substream *substream = siu_stream->substream;
@@ -162,7 +162,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
162static int siu_pcm_rd_set(struct siu_port *port_info, 162static int siu_pcm_rd_set(struct siu_port *port_info,
163 dma_addr_t buff, size_t size) 163 dma_addr_t buff, size_t size)
164{ 164{
165 struct siu_info *info = siu_i2s_dai.private_data; 165 struct siu_info *info = siu_i2s_data;
166 u32 __iomem *base = info->reg; 166 u32 __iomem *base = info->reg;
167 struct siu_stream *siu_stream = &port_info->capture; 167 struct siu_stream *siu_stream = &port_info->capture;
168 struct snd_pcm_substream *substream = siu_stream->substream; 168 struct snd_pcm_substream *substream = siu_stream->substream;
@@ -272,7 +272,7 @@ static int siu_pcm_stmread_start(struct siu_port *port_info)
272 272
273static int siu_pcm_stmread_stop(struct siu_port *port_info) 273static int siu_pcm_stmread_stop(struct siu_port *port_info)
274{ 274{
275 struct siu_info *info = siu_i2s_dai.private_data; 275 struct siu_info *info = siu_i2s_data;
276 u32 __iomem *base = info->reg; 276 u32 __iomem *base = info->reg;
277 struct siu_stream *siu_stream = &port_info->capture; 277 struct siu_stream *siu_stream = &port_info->capture;
278 struct device *dev = siu_stream->substream->pcm->card->dev; 278 struct device *dev = siu_stream->substream->pcm->card->dev;
@@ -296,7 +296,7 @@ static int siu_pcm_stmread_stop(struct siu_port *port_info)
296static int siu_pcm_hw_params(struct snd_pcm_substream *ss, 296static int siu_pcm_hw_params(struct snd_pcm_substream *ss,
297 struct snd_pcm_hw_params *hw_params) 297 struct snd_pcm_hw_params *hw_params)
298{ 298{
299 struct siu_info *info = siu_i2s_dai.private_data; 299 struct siu_info *info = siu_i2s_data;
300 struct device *dev = ss->pcm->card->dev; 300 struct device *dev = ss->pcm->card->dev;
301 int ret; 301 int ret;
302 302
@@ -311,7 +311,7 @@ static int siu_pcm_hw_params(struct snd_pcm_substream *ss,
311 311
312static int siu_pcm_hw_free(struct snd_pcm_substream *ss) 312static int siu_pcm_hw_free(struct snd_pcm_substream *ss)
313{ 313{
314 struct siu_info *info = siu_i2s_dai.private_data; 314 struct siu_info *info = siu_i2s_data;
315 struct siu_port *port_info = siu_port_info(ss); 315 struct siu_port *port_info = siu_port_info(ss);
316 struct device *dev = ss->pcm->card->dev; 316 struct device *dev = ss->pcm->card->dev;
317 struct siu_stream *siu_stream; 317 struct siu_stream *siu_stream;
@@ -342,11 +342,12 @@ static bool filter(struct dma_chan *chan, void *slave)
342static int siu_pcm_open(struct snd_pcm_substream *ss) 342static int siu_pcm_open(struct snd_pcm_substream *ss)
343{ 343{
344 /* Playback / Capture */ 344 /* Playback / Capture */
345 struct siu_info *info = siu_i2s_dai.private_data; 345 struct snd_soc_pcm_runtime *rtd = ss->private_data;
346 struct siu_platform *pdata = rtd->platform->dev->platform_data;
347 struct siu_info *info = siu_i2s_data;
346 struct siu_port *port_info = siu_port_info(ss); 348 struct siu_port *port_info = siu_port_info(ss);
347 struct siu_stream *siu_stream; 349 struct siu_stream *siu_stream;
348 u32 port = info->port_id; 350 u32 port = info->port_id;
349 struct siu_platform *pdata = siu_i2s_dai.dev->platform_data;
350 struct device *dev = ss->pcm->card->dev; 351 struct device *dev = ss->pcm->card->dev;
351 dma_cap_mask_t mask; 352 dma_cap_mask_t mask;
352 struct sh_dmae_slave *param; 353 struct sh_dmae_slave *param;
@@ -383,7 +384,7 @@ static int siu_pcm_open(struct snd_pcm_substream *ss)
383 384
384static int siu_pcm_close(struct snd_pcm_substream *ss) 385static int siu_pcm_close(struct snd_pcm_substream *ss)
385{ 386{
386 struct siu_info *info = siu_i2s_dai.private_data; 387 struct siu_info *info = siu_i2s_data;
387 struct device *dev = ss->pcm->card->dev; 388 struct device *dev = ss->pcm->card->dev;
388 struct siu_port *port_info = siu_port_info(ss); 389 struct siu_port *port_info = siu_port_info(ss);
389 struct siu_stream *siu_stream; 390 struct siu_stream *siu_stream;
@@ -405,7 +406,7 @@ static int siu_pcm_close(struct snd_pcm_substream *ss)
405 406
406static int siu_pcm_prepare(struct snd_pcm_substream *ss) 407static int siu_pcm_prepare(struct snd_pcm_substream *ss)
407{ 408{
408 struct siu_info *info = siu_i2s_dai.private_data; 409 struct siu_info *info = siu_i2s_data;
409 struct siu_port *port_info = siu_port_info(ss); 410 struct siu_port *port_info = siu_port_info(ss);
410 struct device *dev = ss->pcm->card->dev; 411 struct device *dev = ss->pcm->card->dev;
411 struct snd_pcm_runtime *rt = ss->runtime; 412 struct snd_pcm_runtime *rt = ss->runtime;
@@ -451,7 +452,7 @@ static int siu_pcm_prepare(struct snd_pcm_substream *ss)
451 452
452static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd) 453static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
453{ 454{
454 struct siu_info *info = siu_i2s_dai.private_data; 455 struct siu_info *info = siu_i2s_data;
455 struct device *dev = ss->pcm->card->dev; 456 struct device *dev = ss->pcm->card->dev;
456 struct siu_port *port_info = siu_port_info(ss); 457 struct siu_port *port_info = siu_port_info(ss);
457 int ret; 458 int ret;
@@ -494,7 +495,7 @@ static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
494static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss) 495static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss)
495{ 496{
496 struct device *dev = ss->pcm->card->dev; 497 struct device *dev = ss->pcm->card->dev;
497 struct siu_info *info = siu_i2s_dai.private_data; 498 struct siu_info *info = siu_i2s_data;
498 u32 __iomem *base = info->reg; 499 u32 __iomem *base = info->reg;
499 struct siu_port *port_info = siu_port_info(ss); 500 struct siu_port *port_info = siu_port_info(ss);
500 struct snd_pcm_runtime *rt = ss->runtime; 501 struct snd_pcm_runtime *rt = ss->runtime;
@@ -530,7 +531,7 @@ static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
530 struct snd_pcm *pcm) 531 struct snd_pcm *pcm)
531{ 532{
532 /* card->dev == socdev->dev, see snd_soc_new_pcms() */ 533 /* card->dev == socdev->dev, see snd_soc_new_pcms() */
533 struct siu_info *info = siu_i2s_dai.private_data; 534 struct siu_info *info = siu_i2s_data;
534 struct platform_device *pdev = to_platform_device(card->dev); 535 struct platform_device *pdev = to_platform_device(card->dev);
535 int ret; 536 int ret;
536 int i; 537 int i;
@@ -607,9 +608,8 @@ static struct snd_pcm_ops siu_pcm_ops = {
607 .pointer = siu_pcm_pointer_dma, 608 .pointer = siu_pcm_pointer_dma,
608}; 609};
609 610
610struct snd_soc_platform siu_platform = { 611struct snd_soc_platform_driver siu_platform = {
611 .name = "siu-audio", 612 .ops = &siu_pcm_ops,
612 .pcm_ops = &siu_pcm_ops,
613 .pcm_new = siu_pcm_new, 613 .pcm_new = siu_pcm_new,
614 .pcm_free = siu_pcm_free, 614 .pcm_free = siu_pcm_free,
615}; 615};
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index b378096cadb1..40bbdf1591dc 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -92,8 +92,7 @@ struct ssi_priv {
92static int ssi_startup(struct snd_pcm_substream *substream, 92static int ssi_startup(struct snd_pcm_substream *substream,
93 struct snd_soc_dai *dai) 93 struct snd_soc_dai *dai)
94{ 94{
95 struct snd_soc_pcm_runtime *rtd = substream->private_data; 95 struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
96 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
97 if (ssi->inuse) { 96 if (ssi->inuse) {
98 pr_debug("ssi: already in use!\n"); 97 pr_debug("ssi: already in use!\n");
99 return -EBUSY; 98 return -EBUSY;
@@ -105,8 +104,7 @@ static int ssi_startup(struct snd_pcm_substream *substream,
105static void ssi_shutdown(struct snd_pcm_substream *substream, 104static void ssi_shutdown(struct snd_pcm_substream *substream,
106 struct snd_soc_dai *dai) 105 struct snd_soc_dai *dai)
107{ 106{
108 struct snd_soc_pcm_runtime *rtd = substream->private_data; 107 struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
109 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
110 108
111 ssi->inuse = 0; 109 ssi->inuse = 0;
112} 110}
@@ -114,8 +112,7 @@ static void ssi_shutdown(struct snd_pcm_substream *substream,
114static int ssi_trigger(struct snd_pcm_substream *substream, int cmd, 112static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
115 struct snd_soc_dai *dai) 113 struct snd_soc_dai *dai)
116{ 114{
117 struct snd_soc_pcm_runtime *rtd = substream->private_data; 115 struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
118 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
119 116
120 switch (cmd) { 117 switch (cmd) {
121 case SNDRV_PCM_TRIGGER_START: 118 case SNDRV_PCM_TRIGGER_START:
@@ -135,8 +132,7 @@ static int ssi_hw_params(struct snd_pcm_substream *substream,
135 struct snd_pcm_hw_params *params, 132 struct snd_pcm_hw_params *params,
136 struct snd_soc_dai *dai) 133 struct snd_soc_dai *dai)
137{ 134{
138 struct snd_soc_pcm_runtime *rtd = substream->private_data; 135 struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
139 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
140 unsigned long ssicr = SSIREG(SSICR); 136 unsigned long ssicr = SSIREG(SSICR);
141 unsigned int bits, channels, swl, recv, i; 137 unsigned int bits, channels, swl, recv, i;
142 138
@@ -346,10 +342,9 @@ static struct snd_soc_dai_ops ssi_dai_ops = {
346 .set_fmt = ssi_set_fmt, 342 .set_fmt = ssi_set_fmt,
347}; 343};
348 344
349struct snd_soc_dai sh4_ssi_dai[] = { 345struct snd_soc_dai_driver sh4_ssi_dai[] = {
350{ 346{
351 .name = "SSI0", 347 .name = "ssi-dai.0",
352 .id = 0,
353 .playback = { 348 .playback = {
354 .rates = SSI_RATES, 349 .rates = SSI_RATES,
355 .formats = SSI_FMTS, 350 .formats = SSI_FMTS,
@@ -366,8 +361,7 @@ struct snd_soc_dai sh4_ssi_dai[] = {
366}, 361},
367#ifdef CONFIG_CPU_SUBTYPE_SH7760 362#ifdef CONFIG_CPU_SUBTYPE_SH7760
368{ 363{
369 .name = "SSI1", 364 .name = "ssi-dai.1",
370 .id = 1,
371 .playback = { 365 .playback = {
372 .rates = SSI_RATES, 366 .rates = SSI_RATES,
373 .formats = SSI_FMTS, 367 .formats = SSI_FMTS,
@@ -384,19 +378,40 @@ struct snd_soc_dai sh4_ssi_dai[] = {
384}, 378},
385#endif 379#endif
386}; 380};
387EXPORT_SYMBOL_GPL(sh4_ssi_dai);
388 381
389static int __init sh4_ssi_init(void) 382static int __devinit sh4_soc_dai_probe(struct platform_device *pdev)
383{
384 return snd_soc_register_dais(&pdev->dev, sh4_ssi_dai,
385 ARRAY_SIZE(sh4_ssi_dai));
386}
387
388static int __devexit sh4_soc_dai_remove(struct platform_device *pdev)
389{
390 snd_soc_unregister_dai(&pdev->dev, ARRAY_SIZE(sh4_ssi_dai));
391 return 0;
392}
393
394static struct platform_driver sh4_ssi_driver = {
395 .driver = {
396 .name = "sh4-ssi-dai",
397 .owner = THIS_MODULE,
398 },
399
400 .probe = sh4_soc_dai_probe,
401 .remove = __devexit_p(sh4_soc_dai_remove),
402};
403
404static int __init snd_sh4_ssi_init(void)
390{ 405{
391 return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); 406 return platform_driver_register(&sh4_ssi_driver);
392} 407}
393module_init(sh4_ssi_init); 408module_init(snd_sh4_ssi_init);
394 409
395static void __exit sh4_ssi_exit(void) 410static void __exit snd_sh4_ssi_exit(void)
396{ 411{
397 snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); 412 platform_driver_unregister(&sh4_ssi_driver);
398} 413}
399module_exit(sh4_ssi_exit); 414module_exit(snd_sh4_ssi_exit);
400 415
401MODULE_LICENSE("GPL"); 416MODULE_LICENSE("GPL");
402MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); 417MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index f6b0d2829ea9..d214f02cbb65 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -19,8 +19,15 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
19 unsigned int reg) 19 unsigned int reg)
20{ 20{
21 u16 *cache = codec->reg_cache; 21 u16 *cache = codec->reg_cache;
22 if (reg >= codec->reg_cache_size) 22
23 return -1; 23 if (reg >= codec->driver->reg_cache_size ||
24 snd_soc_codec_volatile_register(codec, reg)) {
25 if (codec->cache_only)
26 return -1;
27
28 return codec->hw_read(codec, reg);
29 }
30
24 return cache[reg]; 31 return cache[reg];
25} 32}
26 33
@@ -31,13 +38,12 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
31 u8 data[2]; 38 u8 data[2];
32 int ret; 39 int ret;
33 40
34 BUG_ON(codec->volatile_register);
35
36 data[0] = (reg << 4) | ((value >> 8) & 0x000f); 41 data[0] = (reg << 4) | ((value >> 8) & 0x000f);
37 data[1] = value & 0x00ff; 42 data[1] = value & 0x00ff;
38 43
39 if (reg < codec->reg_cache_size) 44 if (!snd_soc_codec_volatile_register(codec, reg) &&
40 cache[reg] = value; 45 reg < codec->driver->reg_cache_size)
46 cache[reg] = value;
41 47
42 if (codec->cache_only) { 48 if (codec->cache_only) {
43 codec->cache_sync = 1; 49 codec->cache_sync = 1;
@@ -89,8 +95,15 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
89 unsigned int reg) 95 unsigned int reg)
90{ 96{
91 u16 *cache = codec->reg_cache; 97 u16 *cache = codec->reg_cache;
92 if (reg >= codec->reg_cache_size) 98
93 return -1; 99 if (reg >= codec->driver->reg_cache_size ||
100 snd_soc_codec_volatile_register(codec, reg)) {
101 if (codec->cache_only)
102 return -1;
103
104 return codec->hw_read(codec, reg);
105 }
106
94 return cache[reg]; 107 return cache[reg];
95} 108}
96 109
@@ -101,13 +114,12 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
101 u8 data[2]; 114 u8 data[2];
102 int ret; 115 int ret;
103 116
104 BUG_ON(codec->volatile_register);
105
106 data[0] = (reg << 1) | ((value >> 8) & 0x0001); 117 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
107 data[1] = value & 0x00ff; 118 data[1] = value & 0x00ff;
108 119
109 if (reg < codec->reg_cache_size) 120 if (!snd_soc_codec_volatile_register(codec, reg) &&
110 cache[reg] = value; 121 reg < codec->driver->reg_cache_size)
122 cache[reg] = value;
111 123
112 if (codec->cache_only) { 124 if (codec->cache_only) {
113 codec->cache_sync = 1; 125 codec->cache_sync = 1;
@@ -161,14 +173,13 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
161 u8 *cache = codec->reg_cache; 173 u8 *cache = codec->reg_cache;
162 u8 data[2]; 174 u8 data[2];
163 175
164 BUG_ON(codec->volatile_register);
165
166 reg &= 0xff; 176 reg &= 0xff;
167 data[0] = reg; 177 data[0] = reg;
168 data[1] = value & 0xff; 178 data[1] = value & 0xff;
169 179
170 if (reg < codec->reg_cache_size) 180 if (!snd_soc_codec_volatile_register(codec, reg) &&
171 cache[reg] = value; 181 reg < codec->driver->reg_cache_size)
182 cache[reg] = value;
172 183
173 if (codec->cache_only) { 184 if (codec->cache_only) {
174 codec->cache_sync = 1; 185 codec->cache_sync = 1;
@@ -187,12 +198,49 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
187 unsigned int reg) 198 unsigned int reg)
188{ 199{
189 u8 *cache = codec->reg_cache; 200 u8 *cache = codec->reg_cache;
201
190 reg &= 0xff; 202 reg &= 0xff;
191 if (reg >= codec->reg_cache_size) 203 if (reg >= codec->driver->reg_cache_size ||
192 return -1; 204 snd_soc_codec_volatile_register(codec, reg)) {
205 if (codec->cache_only)
206 return -1;
207
208 return codec->hw_read(codec, reg);
209 }
210
193 return cache[reg]; 211 return cache[reg];
194} 212}
195 213
214#if defined(CONFIG_SPI_MASTER)
215static int snd_soc_8_8_spi_write(void *control_data, const char *data,
216 int len)
217{
218 struct spi_device *spi = control_data;
219 struct spi_transfer t;
220 struct spi_message m;
221 u8 msg[2];
222
223 if (len <= 0)
224 return 0;
225
226 msg[0] = data[0];
227 msg[1] = data[1];
228
229 spi_message_init(&m);
230 memset(&t, 0, (sizeof t));
231
232 t.tx_buf = &msg[0];
233 t.len = len;
234
235 spi_message_add_tail(&t, &m);
236 spi_sync(spi, &m);
237
238 return len;
239}
240#else
241#define snd_soc_8_8_spi_write NULL
242#endif
243
196static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, 244static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
197 unsigned int value) 245 unsigned int value)
198{ 246{
@@ -203,9 +251,9 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
203 data[1] = (value >> 8) & 0xff; 251 data[1] = (value >> 8) & 0xff;
204 data[2] = value & 0xff; 252 data[2] = value & 0xff;
205 253
206 if (!snd_soc_codec_volatile_register(codec, reg) 254 if (!snd_soc_codec_volatile_register(codec, reg) &&
207 && reg < codec->reg_cache_size) 255 reg < codec->driver->reg_cache_size)
208 reg_cache[reg] = value; 256 reg_cache[reg] = value;
209 257
210 if (codec->cache_only) { 258 if (codec->cache_only) {
211 codec->cache_sync = 1; 259 codec->cache_sync = 1;
@@ -225,10 +273,10 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
225{ 273{
226 u16 *cache = codec->reg_cache; 274 u16 *cache = codec->reg_cache;
227 275
228 if (reg >= codec->reg_cache_size || 276 if (reg >= codec->driver->reg_cache_size ||
229 snd_soc_codec_volatile_register(codec, reg)) { 277 snd_soc_codec_volatile_register(codec, reg)) {
230 if (codec->cache_only) 278 if (codec->cache_only)
231 return -EINVAL; 279 return -1;
232 280
233 return codec->hw_read(codec, reg); 281 return codec->hw_read(codec, reg);
234 } else { 282 } else {
@@ -236,6 +284,37 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
236 } 284 }
237} 285}
238 286
287#if defined(CONFIG_SPI_MASTER)
288static int snd_soc_8_16_spi_write(void *control_data, const char *data,
289 int len)
290{
291 struct spi_device *spi = control_data;
292 struct spi_transfer t;
293 struct spi_message m;
294 u8 msg[3];
295
296 if (len <= 0)
297 return 0;
298
299 msg[0] = data[0];
300 msg[1] = data[1];
301 msg[2] = data[2];
302
303 spi_message_init(&m);
304 memset(&t, 0, (sizeof t));
305
306 t.tx_buf = &msg[0];
307 t.len = len;
308
309 spi_message_add_tail(&t, &m);
310 spi_sync(spi, &m);
311
312 return len;
313}
314#else
315#define snd_soc_8_16_spi_write NULL
316#endif
317
239#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) 318#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
240static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec, 319static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
241 unsigned int r) 320 unsigned int r)
@@ -344,8 +423,14 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
344 u8 *cache = codec->reg_cache; 423 u8 *cache = codec->reg_cache;
345 424
346 reg &= 0xff; 425 reg &= 0xff;
347 if (reg >= codec->reg_cache_size) 426 if (reg >= codec->driver->reg_cache_size ||
348 return -1; 427 snd_soc_codec_volatile_register(codec, reg)) {
428 if (codec->cache_only)
429 return -1;
430
431 return codec->hw_read(codec, reg);
432 }
433
349 return cache[reg]; 434 return cache[reg];
350} 435}
351 436
@@ -356,15 +441,14 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
356 u8 data[3]; 441 u8 data[3];
357 int ret; 442 int ret;
358 443
359 BUG_ON(codec->volatile_register);
360
361 data[0] = (reg >> 8) & 0xff; 444 data[0] = (reg >> 8) & 0xff;
362 data[1] = reg & 0xff; 445 data[1] = reg & 0xff;
363 data[2] = value; 446 data[2] = value;
364 447
365 reg &= 0xff; 448 reg &= 0xff;
366 if (reg < codec->reg_cache_size) 449 if (!snd_soc_codec_volatile_register(codec, reg) &&
367 cache[reg] = value; 450 reg < codec->driver->reg_cache_size)
451 cache[reg] = value;
368 452
369 if (codec->cache_only) { 453 if (codec->cache_only) {
370 codec->cache_sync = 1; 454 codec->cache_sync = 1;
@@ -452,10 +536,10 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
452{ 536{
453 u16 *cache = codec->reg_cache; 537 u16 *cache = codec->reg_cache;
454 538
455 if (reg >= codec->reg_cache_size || 539 if (reg >= codec->driver->reg_cache_size ||
456 snd_soc_codec_volatile_register(codec, reg)) { 540 snd_soc_codec_volatile_register(codec, reg)) {
457 if (codec->cache_only) 541 if (codec->cache_only)
458 return -EINVAL; 542 return -1;
459 543
460 return codec->hw_read(codec, reg); 544 return codec->hw_read(codec, reg);
461 } 545 }
@@ -475,8 +559,9 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
475 data[2] = (value >> 8) & 0xff; 559 data[2] = (value >> 8) & 0xff;
476 data[3] = value & 0xff; 560 data[3] = value & 0xff;
477 561
478 if (reg < codec->reg_cache_size) 562 if (!snd_soc_codec_volatile_register(codec, reg) &&
479 cache[reg] = value; 563 reg < codec->driver->reg_cache_size)
564 cache[reg] = value;
480 565
481 if (codec->cache_only) { 566 if (codec->cache_only) {
482 codec->cache_sync = 1; 567 codec->cache_sync = 1;
@@ -494,6 +579,38 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
494 return -EIO; 579 return -EIO;
495} 580}
496 581
582#if defined(CONFIG_SPI_MASTER)
583static int snd_soc_16_16_spi_write(void *control_data, const char *data,
584 int len)
585{
586 struct spi_device *spi = control_data;
587 struct spi_transfer t;
588 struct spi_message m;
589 u8 msg[4];
590
591 if (len <= 0)
592 return 0;
593
594 msg[0] = data[0];
595 msg[1] = data[1];
596 msg[2] = data[2];
597 msg[3] = data[3];
598
599 spi_message_init(&m);
600 memset(&t, 0, (sizeof t));
601
602 t.tx_buf = &msg[0];
603 t.len = len;
604
605 spi_message_add_tail(&t, &m);
606 spi_sync(spi, &m);
607
608 return len;
609}
610#else
611#define snd_soc_16_16_spi_write NULL
612#endif
613
497static struct { 614static struct {
498 int addr_bits; 615 int addr_bits;
499 int data_bits; 616 int data_bits;
@@ -516,11 +633,13 @@ static struct {
516 .addr_bits = 8, .data_bits = 8, 633 .addr_bits = 8, .data_bits = 8,
517 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read, 634 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
518 .i2c_read = snd_soc_8_8_read_i2c, 635 .i2c_read = snd_soc_8_8_read_i2c,
636 .spi_write = snd_soc_8_8_spi_write,
519 }, 637 },
520 { 638 {
521 .addr_bits = 8, .data_bits = 16, 639 .addr_bits = 8, .data_bits = 16,
522 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read, 640 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
523 .i2c_read = snd_soc_8_16_read_i2c, 641 .i2c_read = snd_soc_8_16_read_i2c,
642 .spi_write = snd_soc_8_16_spi_write,
524 }, 643 },
525 { 644 {
526 .addr_bits = 16, .data_bits = 8, 645 .addr_bits = 16, .data_bits = 8,
@@ -532,6 +651,7 @@ static struct {
532 .addr_bits = 16, .data_bits = 16, 651 .addr_bits = 16, .data_bits = 16,
533 .write = snd_soc_16_16_write, .read = snd_soc_16_16_read, 652 .write = snd_soc_16_16_write, .read = snd_soc_16_16_read,
534 .i2c_read = snd_soc_16_16_read_i2c, 653 .i2c_read = snd_soc_16_16_read_i2c,
654 .spi_write = snd_soc_16_16_spi_write,
535 }, 655 },
536}; 656};
537 657
@@ -572,8 +692,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
572 return -EINVAL; 692 return -EINVAL;
573 } 693 }
574 694
575 codec->write = io_types[i].write; 695 codec->driver->write = io_types[i].write;
576 codec->read = io_types[i].read; 696 codec->driver->read = io_types[i].read;
577 697
578 switch (control) { 698 switch (control) {
579 case SND_SOC_CUSTOM: 699 case SND_SOC_CUSTOM:
@@ -585,11 +705,19 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
585#endif 705#endif
586 if (io_types[i].i2c_read) 706 if (io_types[i].i2c_read)
587 codec->hw_read = io_types[i].i2c_read; 707 codec->hw_read = io_types[i].i2c_read;
708
709 codec->control_data = container_of(codec->dev,
710 struct i2c_client,
711 dev);
588 break; 712 break;
589 713
590 case SND_SOC_SPI: 714 case SND_SOC_SPI:
591 if (io_types[i].spi_write) 715 if (io_types[i].spi_write)
592 codec->hw_write = io_types[i].spi_write; 716 codec->hw_write = io_types[i].spi_write;
717
718 codec->control_data = container_of(codec->dev,
719 struct spi_device,
720 dev);
593 break; 721 break;
594 } 722 }
595 723
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4057d35343bb..1c8f3f507f54 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3,6 +3,8 @@
3 * 3 *
4 * Copyright 2005 Wolfson Microelectronics PLC. 4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd. 5 * Copyright 2005 Openedhand Ltd.
6 * Copyright (C) 2010 Slimlogic Ltd.
7 * Copyright (C) 2010 Texas Instruments Inc.
6 * 8 *
7 * Author: Liam Girdwood <lrg@slimlogic.co.uk> 9 * Author: Liam Girdwood <lrg@slimlogic.co.uk>
8 * with code, comments and ideas from :- 10 * with code, comments and ideas from :-
@@ -37,6 +39,8 @@
37#include <sound/soc-dapm.h> 39#include <sound/soc-dapm.h>
38#include <sound/initval.h> 40#include <sound/initval.h>
39 41
42#define NAME_SIZE 32
43
40static DEFINE_MUTEX(pcm_mutex); 44static DEFINE_MUTEX(pcm_mutex);
41static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); 45static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
42 46
@@ -52,6 +56,7 @@ static LIST_HEAD(codec_list);
52 56
53static int snd_soc_register_card(struct snd_soc_card *card); 57static int snd_soc_register_card(struct snd_soc_card *card);
54static int snd_soc_unregister_card(struct snd_soc_card *card); 58static int snd_soc_unregister_card(struct snd_soc_card *card);
59static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
55 60
56/* 61/*
57 * This is a timeout to do a DAPM powerdown after a stream is closed(). 62 * This is a timeout to do a DAPM powerdown after a stream is closed().
@@ -86,30 +91,30 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
86{ 91{
87 int ret, i, step = 1, count = 0; 92 int ret, i, step = 1, count = 0;
88 93
89 if (!codec->reg_cache_size) 94 if (!codec->driver->reg_cache_size)
90 return 0; 95 return 0;
91 96
92 if (codec->reg_cache_step) 97 if (codec->driver->reg_cache_step)
93 step = codec->reg_cache_step; 98 step = codec->driver->reg_cache_step;
94 99
95 count += sprintf(buf, "%s registers\n", codec->name); 100 count += sprintf(buf, "%s registers\n", codec->name);
96 for (i = 0; i < codec->reg_cache_size; i += step) { 101 for (i = 0; i < codec->driver->reg_cache_size; i += step) {
97 if (codec->readable_register && !codec->readable_register(i)) 102 if (codec->driver->readable_register && !codec->driver->readable_register(i))
98 continue; 103 continue;
99 104
100 count += sprintf(buf + count, "%2x: ", i); 105 count += sprintf(buf + count, "%2x: ", i);
101 if (count >= PAGE_SIZE - 1) 106 if (count >= PAGE_SIZE - 1)
102 break; 107 break;
103 108
104 if (codec->display_register) { 109 if (codec->driver->display_register) {
105 count += codec->display_register(codec, buf + count, 110 count += codec->driver->display_register(codec, buf + count,
106 PAGE_SIZE - count, i); 111 PAGE_SIZE - count, i);
107 } else { 112 } else {
108 /* If the read fails it's almost certainly due to 113 /* If the read fails it's almost certainly due to
109 * the register being volatile and the device being 114 * the register being volatile and the device being
110 * powered off. 115 * powered off.
111 */ 116 */
112 ret = codec->read(codec, i); 117 ret = codec->driver->read(codec, i);
113 if (ret >= 0) 118 if (ret >= 0)
114 count += snprintf(buf + count, 119 count += snprintf(buf + count,
115 PAGE_SIZE - count, 120 PAGE_SIZE - count,
@@ -137,8 +142,10 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
137static ssize_t codec_reg_show(struct device *dev, 142static ssize_t codec_reg_show(struct device *dev,
138 struct device_attribute *attr, char *buf) 143 struct device_attribute *attr, char *buf)
139{ 144{
140 struct snd_soc_device *devdata = dev_get_drvdata(dev); 145 struct snd_soc_pcm_runtime *rtd =
141 return soc_codec_reg_show(devdata->card->codec, buf); 146 container_of(dev, struct snd_soc_pcm_runtime, dev);
147
148 return soc_codec_reg_show(rtd->codec, buf);
142} 149}
143 150
144static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); 151static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
@@ -146,20 +153,20 @@ static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
146static ssize_t pmdown_time_show(struct device *dev, 153static ssize_t pmdown_time_show(struct device *dev,
147 struct device_attribute *attr, char *buf) 154 struct device_attribute *attr, char *buf)
148{ 155{
149 struct snd_soc_device *socdev = dev_get_drvdata(dev); 156 struct snd_soc_pcm_runtime *rtd =
150 struct snd_soc_card *card = socdev->card; 157 container_of(dev, struct snd_soc_pcm_runtime, dev);
151 158
152 return sprintf(buf, "%ld\n", card->pmdown_time); 159 return sprintf(buf, "%ld\n", rtd->pmdown_time);
153} 160}
154 161
155static ssize_t pmdown_time_set(struct device *dev, 162static ssize_t pmdown_time_set(struct device *dev,
156 struct device_attribute *attr, 163 struct device_attribute *attr,
157 const char *buf, size_t count) 164 const char *buf, size_t count)
158{ 165{
159 struct snd_soc_device *socdev = dev_get_drvdata(dev); 166 struct snd_soc_pcm_runtime *rtd =
160 struct snd_soc_card *card = socdev->card; 167 container_of(dev, struct snd_soc_pcm_runtime, dev);
161 168
162 strict_strtol(buf, 10, &card->pmdown_time); 169 strict_strtol(buf, 10, &rtd->pmdown_time);
163 170
164 return count; 171 return count;
165} 172}
@@ -203,19 +210,19 @@ static ssize_t codec_reg_write_file(struct file *file,
203 return -EFAULT; 210 return -EFAULT;
204 buf[buf_size] = 0; 211 buf[buf_size] = 0;
205 212
206 if (codec->reg_cache_step) 213 if (codec->driver->reg_cache_step)
207 step = codec->reg_cache_step; 214 step = codec->driver->reg_cache_step;
208 215
209 while (*start == ' ') 216 while (*start == ' ')
210 start++; 217 start++;
211 reg = simple_strtoul(start, &start, 16); 218 reg = simple_strtoul(start, &start, 16);
212 if ((reg >= codec->reg_cache_size) || (reg % step)) 219 if ((reg >= codec->driver->reg_cache_size) || (reg % step))
213 return -EINVAL; 220 return -EINVAL;
214 while (*start == ' ') 221 while (*start == ' ')
215 start++; 222 start++;
216 if (strict_strtoul(start, 16, &value)) 223 if (strict_strtoul(start, 16, &value))
217 return -EINVAL; 224 return -EINVAL;
218 codec->write(codec, reg, value); 225 codec->driver->write(codec, reg, value);
219 return buf_size; 226 return buf_size;
220} 227}
221 228
@@ -228,16 +235,7 @@ static const struct file_operations codec_reg_fops = {
228 235
229static void soc_init_codec_debugfs(struct snd_soc_codec *codec) 236static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
230{ 237{
231 char codec_root[128]; 238 codec->debugfs_codec_root = debugfs_create_dir(codec->name ,
232
233 if (codec->dev)
234 snprintf(codec_root, sizeof(codec_root),
235 "%s.%s", codec->name, dev_name(codec->dev));
236 else
237 snprintf(codec_root, sizeof(codec_root),
238 "%s", codec->name);
239
240 codec->debugfs_codec_root = debugfs_create_dir(codec_root,
241 debugfs_root); 239 debugfs_root);
242 if (!codec->debugfs_codec_root) { 240 if (!codec->debugfs_codec_root) {
243 printk(KERN_WARNING 241 printk(KERN_WARNING
@@ -273,6 +271,106 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
273 debugfs_remove_recursive(codec->debugfs_codec_root); 271 debugfs_remove_recursive(codec->debugfs_codec_root);
274} 272}
275 273
274static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
275 size_t count, loff_t *ppos)
276{
277 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
278 ssize_t len, ret = 0;
279 struct snd_soc_codec *codec;
280
281 if (!buf)
282 return -ENOMEM;
283
284 list_for_each_entry(codec, &codec_list, list) {
285 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
286 codec->name);
287 if (len >= 0)
288 ret += len;
289 if (ret > PAGE_SIZE) {
290 ret = PAGE_SIZE;
291 break;
292 }
293 }
294
295 if (ret >= 0)
296 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
297
298 kfree(buf);
299
300 return ret;
301}
302
303static const struct file_operations codec_list_fops = {
304 .read = codec_list_read_file,
305 .llseek = default_llseek,/* read accesses f_pos */
306};
307
308static ssize_t dai_list_read_file(struct file *file, char __user *user_buf,
309 size_t count, loff_t *ppos)
310{
311 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
312 ssize_t len, ret = 0;
313 struct snd_soc_dai *dai;
314
315 if (!buf)
316 return -ENOMEM;
317
318 list_for_each_entry(dai, &dai_list, list) {
319 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name);
320 if (len >= 0)
321 ret += len;
322 if (ret > PAGE_SIZE) {
323 ret = PAGE_SIZE;
324 break;
325 }
326 }
327
328 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
329
330 kfree(buf);
331
332 return ret;
333}
334
335static const struct file_operations dai_list_fops = {
336 .read = dai_list_read_file,
337 .llseek = default_llseek,/* read accesses f_pos */
338};
339
340static ssize_t platform_list_read_file(struct file *file,
341 char __user *user_buf,
342 size_t count, loff_t *ppos)
343{
344 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
345 ssize_t len, ret = 0;
346 struct snd_soc_platform *platform;
347
348 if (!buf)
349 return -ENOMEM;
350
351 list_for_each_entry(platform, &platform_list, list) {
352 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
353 platform->name);
354 if (len >= 0)
355 ret += len;
356 if (ret > PAGE_SIZE) {
357 ret = PAGE_SIZE;
358 break;
359 }
360 }
361
362 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
363
364 kfree(buf);
365
366 return ret;
367}
368
369static const struct file_operations platform_list_fops = {
370 .read = platform_list_read_file,
371 .llseek = default_llseek,/* read accesses f_pos */
372};
373
276#else 374#else
277 375
278static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) 376static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
@@ -306,7 +404,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
306 codec->ac97->dev.release = soc_ac97_device_release; 404 codec->ac97->dev.release = soc_ac97_device_release;
307 405
308 dev_set_name(&codec->ac97->dev, "%d-%d:%s", 406 dev_set_name(&codec->ac97->dev, "%d-%d:%s",
309 codec->card->number, 0, codec->name); 407 codec->card->snd_card->number, 0, codec->name);
310 err = device_register(&codec->ac97->dev); 408 err = device_register(&codec->ac97->dev);
311 if (err < 0) { 409 if (err < 0) {
312 snd_printk(KERN_ERR "Can't register ac97 bus\n"); 410 snd_printk(KERN_ERR "Can't register ac97 bus\n");
@@ -320,24 +418,21 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
320static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) 418static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
321{ 419{
322 struct snd_soc_pcm_runtime *rtd = substream->private_data; 420 struct snd_soc_pcm_runtime *rtd = substream->private_data;
323 struct snd_soc_device *socdev = rtd->socdev; 421 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
324 struct snd_soc_card *card = socdev->card; 422 struct snd_soc_dai *codec_dai = rtd->codec_dai;
325 struct snd_soc_dai_link *machine = rtd->dai;
326 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
327 struct snd_soc_dai *codec_dai = machine->codec_dai;
328 int ret; 423 int ret;
329 424
330 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || 425 if (codec_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_rates ||
331 machine->symmetric_rates) { 426 rtd->dai_link->symmetric_rates) {
332 dev_dbg(card->dev, "Symmetry forces %dHz rate\n", 427 dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n",
333 machine->rate); 428 rtd->rate);
334 429
335 ret = snd_pcm_hw_constraint_minmax(substream->runtime, 430 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
336 SNDRV_PCM_HW_PARAM_RATE, 431 SNDRV_PCM_HW_PARAM_RATE,
337 machine->rate, 432 rtd->rate,
338 machine->rate); 433 rtd->rate);
339 if (ret < 0) { 434 if (ret < 0) {
340 dev_err(card->dev, 435 dev_err(&rtd->dev,
341 "Unable to apply rate symmetry constraint: %d\n", ret); 436 "Unable to apply rate symmetry constraint: %d\n", ret);
342 return ret; 437 return ret;
343 } 438 }
@@ -354,20 +449,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
354static int soc_pcm_open(struct snd_pcm_substream *substream) 449static int soc_pcm_open(struct snd_pcm_substream *substream)
355{ 450{
356 struct snd_soc_pcm_runtime *rtd = substream->private_data; 451 struct snd_soc_pcm_runtime *rtd = substream->private_data;
357 struct snd_soc_device *socdev = rtd->socdev;
358 struct snd_soc_card *card = socdev->card;
359 struct snd_pcm_runtime *runtime = substream->runtime; 452 struct snd_pcm_runtime *runtime = substream->runtime;
360 struct snd_soc_dai_link *machine = rtd->dai; 453 struct snd_soc_platform *platform = rtd->platform;
361 struct snd_soc_platform *platform = card->platform; 454 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
362 struct snd_soc_dai *cpu_dai = machine->cpu_dai; 455 struct snd_soc_dai *codec_dai = rtd->codec_dai;
363 struct snd_soc_dai *codec_dai = machine->codec_dai; 456 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
457 struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
364 int ret = 0; 458 int ret = 0;
365 459
366 mutex_lock(&pcm_mutex); 460 mutex_lock(&pcm_mutex);
367 461
368 /* startup the audio subsystem */ 462 /* startup the audio subsystem */
369 if (cpu_dai->ops->startup) { 463 if (cpu_dai->driver->ops->startup) {
370 ret = cpu_dai->ops->startup(substream, cpu_dai); 464 ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
371 if (ret < 0) { 465 if (ret < 0) {
372 printk(KERN_ERR "asoc: can't open interface %s\n", 466 printk(KERN_ERR "asoc: can't open interface %s\n",
373 cpu_dai->name); 467 cpu_dai->name);
@@ -375,16 +469,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
375 } 469 }
376 } 470 }
377 471
378 if (platform->pcm_ops->open) { 472 if (platform->driver->ops->open) {
379 ret = platform->pcm_ops->open(substream); 473 ret = platform->driver->ops->open(substream);
380 if (ret < 0) { 474 if (ret < 0) {
381 printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); 475 printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
382 goto platform_err; 476 goto platform_err;
383 } 477 }
384 } 478 }
385 479
386 if (codec_dai->ops->startup) { 480 if (codec_dai->driver->ops->startup) {
387 ret = codec_dai->ops->startup(substream, codec_dai); 481 ret = codec_dai->driver->ops->startup(substream, codec_dai);
388 if (ret < 0) { 482 if (ret < 0) {
389 printk(KERN_ERR "asoc: can't open codec %s\n", 483 printk(KERN_ERR "asoc: can't open codec %s\n",
390 codec_dai->name); 484 codec_dai->name);
@@ -392,10 +486,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
392 } 486 }
393 } 487 }
394 488
395 if (machine->ops && machine->ops->startup) { 489 if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
396 ret = machine->ops->startup(substream); 490 ret = rtd->dai_link->ops->startup(substream);
397 if (ret < 0) { 491 if (ret < 0) {
398 printk(KERN_ERR "asoc: %s startup failed\n", machine->name); 492 printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
399 goto machine_err; 493 goto machine_err;
400 } 494 }
401 } 495 }
@@ -403,50 +497,50 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
403 /* Check that the codec and cpu DAI's are compatible */ 497 /* Check that the codec and cpu DAI's are compatible */
404 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 498 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
405 runtime->hw.rate_min = 499 runtime->hw.rate_min =
406 max(codec_dai->playback.rate_min, 500 max(codec_dai_drv->playback.rate_min,
407 cpu_dai->playback.rate_min); 501 cpu_dai_drv->playback.rate_min);
408 runtime->hw.rate_max = 502 runtime->hw.rate_max =
409 min(codec_dai->playback.rate_max, 503 min(codec_dai_drv->playback.rate_max,
410 cpu_dai->playback.rate_max); 504 cpu_dai_drv->playback.rate_max);
411 runtime->hw.channels_min = 505 runtime->hw.channels_min =
412 max(codec_dai->playback.channels_min, 506 max(codec_dai_drv->playback.channels_min,
413 cpu_dai->playback.channels_min); 507 cpu_dai_drv->playback.channels_min);
414 runtime->hw.channels_max = 508 runtime->hw.channels_max =
415 min(codec_dai->playback.channels_max, 509 min(codec_dai_drv->playback.channels_max,
416 cpu_dai->playback.channels_max); 510 cpu_dai_drv->playback.channels_max);
417 runtime->hw.formats = 511 runtime->hw.formats =
418 codec_dai->playback.formats & cpu_dai->playback.formats; 512 codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
419 runtime->hw.rates = 513 runtime->hw.rates =
420 codec_dai->playback.rates & cpu_dai->playback.rates; 514 codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
421 if (codec_dai->playback.rates 515 if (codec_dai_drv->playback.rates
422 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) 516 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
423 runtime->hw.rates |= cpu_dai->playback.rates; 517 runtime->hw.rates |= cpu_dai_drv->playback.rates;
424 if (cpu_dai->playback.rates 518 if (cpu_dai_drv->playback.rates
425 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) 519 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
426 runtime->hw.rates |= codec_dai->playback.rates; 520 runtime->hw.rates |= codec_dai_drv->playback.rates;
427 } else { 521 } else {
428 runtime->hw.rate_min = 522 runtime->hw.rate_min =
429 max(codec_dai->capture.rate_min, 523 max(codec_dai_drv->capture.rate_min,
430 cpu_dai->capture.rate_min); 524 cpu_dai_drv->capture.rate_min);
431 runtime->hw.rate_max = 525 runtime->hw.rate_max =
432 min(codec_dai->capture.rate_max, 526 min(codec_dai_drv->capture.rate_max,
433 cpu_dai->capture.rate_max); 527 cpu_dai_drv->capture.rate_max);
434 runtime->hw.channels_min = 528 runtime->hw.channels_min =
435 max(codec_dai->capture.channels_min, 529 max(codec_dai_drv->capture.channels_min,
436 cpu_dai->capture.channels_min); 530 cpu_dai_drv->capture.channels_min);
437 runtime->hw.channels_max = 531 runtime->hw.channels_max =
438 min(codec_dai->capture.channels_max, 532 min(codec_dai_drv->capture.channels_max,
439 cpu_dai->capture.channels_max); 533 cpu_dai_drv->capture.channels_max);
440 runtime->hw.formats = 534 runtime->hw.formats =
441 codec_dai->capture.formats & cpu_dai->capture.formats; 535 codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
442 runtime->hw.rates = 536 runtime->hw.rates =
443 codec_dai->capture.rates & cpu_dai->capture.rates; 537 codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
444 if (codec_dai->capture.rates 538 if (codec_dai_drv->capture.rates
445 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) 539 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
446 runtime->hw.rates |= cpu_dai->capture.rates; 540 runtime->hw.rates |= cpu_dai_drv->capture.rates;
447 if (cpu_dai->capture.rates 541 if (cpu_dai_drv->capture.rates
448 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) 542 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
449 runtime->hw.rates |= codec_dai->capture.rates; 543 runtime->hw.rates |= codec_dai_drv->capture.rates;
450 } 544 }
451 545
452 snd_pcm_limit_hw_rates(runtime); 546 snd_pcm_limit_hw_rates(runtime);
@@ -462,7 +556,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
462 } 556 }
463 if (!runtime->hw.channels_min || !runtime->hw.channels_max) { 557 if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
464 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", 558 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
465 codec_dai->name, cpu_dai->name); 559 codec_dai->name, cpu_dai->name);
466 goto config_err; 560 goto config_err;
467 } 561 }
468 562
@@ -473,7 +567,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
473 goto config_err; 567 goto config_err;
474 } 568 }
475 569
476 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); 570 pr_debug("asoc: %s <-> %s info:\n",
571 codec_dai->name, cpu_dai->name);
477 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); 572 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
478 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, 573 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
479 runtime->hw.channels_max); 574 runtime->hw.channels_max);
@@ -481,33 +576,33 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
481 runtime->hw.rate_max); 576 runtime->hw.rate_max);
482 577
483 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 578 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
484 cpu_dai->playback.active++; 579 cpu_dai->playback_active++;
485 codec_dai->playback.active++; 580 codec_dai->playback_active++;
486 } else { 581 } else {
487 cpu_dai->capture.active++; 582 cpu_dai->capture_active++;
488 codec_dai->capture.active++; 583 codec_dai->capture_active++;
489 } 584 }
490 cpu_dai->active++; 585 cpu_dai->active++;
491 codec_dai->active++; 586 codec_dai->active++;
492 card->codec->active++; 587 rtd->codec->active++;
493 mutex_unlock(&pcm_mutex); 588 mutex_unlock(&pcm_mutex);
494 return 0; 589 return 0;
495 590
496config_err: 591config_err:
497 if (machine->ops && machine->ops->shutdown) 592 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
498 machine->ops->shutdown(substream); 593 rtd->dai_link->ops->shutdown(substream);
499 594
500machine_err: 595machine_err:
501 if (codec_dai->ops->shutdown) 596 if (codec_dai->driver->ops->shutdown)
502 codec_dai->ops->shutdown(substream, codec_dai); 597 codec_dai->driver->ops->shutdown(substream, codec_dai);
503 598
504codec_dai_err: 599codec_dai_err:
505 if (platform->pcm_ops->close) 600 if (platform->driver->ops->close)
506 platform->pcm_ops->close(substream); 601 platform->driver->ops->close(substream);
507 602
508platform_err: 603platform_err:
509 if (cpu_dai->ops->shutdown) 604 if (cpu_dai->driver->ops->shutdown)
510 cpu_dai->ops->shutdown(substream, cpu_dai); 605 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
511out: 606out:
512 mutex_unlock(&pcm_mutex); 607 mutex_unlock(&pcm_mutex);
513 return ret; 608 return ret;
@@ -520,29 +615,25 @@ out:
520 */ 615 */
521static void close_delayed_work(struct work_struct *work) 616static void close_delayed_work(struct work_struct *work)
522{ 617{
523 struct snd_soc_card *card = container_of(work, struct snd_soc_card, 618 struct snd_soc_pcm_runtime *rtd =
524 delayed_work.work); 619 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
525 struct snd_soc_codec *codec = card->codec; 620 struct snd_soc_dai *codec_dai = rtd->codec_dai;
526 struct snd_soc_dai *codec_dai;
527 int i;
528 621
529 mutex_lock(&pcm_mutex); 622 mutex_lock(&pcm_mutex);
530 for (i = 0; i < codec->num_dai; i++) { 623
531 codec_dai = &codec->dai[i]; 624 pr_debug("pop wq checking: %s status: %s waiting: %s\n",
532 625 codec_dai->driver->playback.stream_name,
533 pr_debug("pop wq checking: %s status: %s waiting: %s\n", 626 codec_dai->playback_active ? "active" : "inactive",
534 codec_dai->playback.stream_name, 627 codec_dai->pop_wait ? "yes" : "no");
535 codec_dai->playback.active ? "active" : "inactive", 628
536 codec_dai->pop_wait ? "yes" : "no"); 629 /* are we waiting on this codec DAI stream */
537 630 if (codec_dai->pop_wait == 1) {
538 /* are we waiting on this codec DAI stream */ 631 codec_dai->pop_wait = 0;
539 if (codec_dai->pop_wait == 1) { 632 snd_soc_dapm_stream_event(rtd,
540 codec_dai->pop_wait = 0; 633 codec_dai->driver->playback.stream_name,
541 snd_soc_dapm_stream_event(codec, 634 SND_SOC_DAPM_STREAM_STOP);
542 codec_dai->playback.stream_name,
543 SND_SOC_DAPM_STREAM_STOP);
544 }
545 } 635 }
636
546 mutex_unlock(&pcm_mutex); 637 mutex_unlock(&pcm_mutex);
547} 638}
548 639
@@ -554,22 +645,19 @@ static void close_delayed_work(struct work_struct *work)
554static int soc_codec_close(struct snd_pcm_substream *substream) 645static int soc_codec_close(struct snd_pcm_substream *substream)
555{ 646{
556 struct snd_soc_pcm_runtime *rtd = substream->private_data; 647 struct snd_soc_pcm_runtime *rtd = substream->private_data;
557 struct snd_soc_device *socdev = rtd->socdev; 648 struct snd_soc_platform *platform = rtd->platform;
558 struct snd_soc_card *card = socdev->card; 649 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
559 struct snd_soc_dai_link *machine = rtd->dai; 650 struct snd_soc_dai *codec_dai = rtd->codec_dai;
560 struct snd_soc_platform *platform = card->platform; 651 struct snd_soc_codec *codec = rtd->codec;
561 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
562 struct snd_soc_dai *codec_dai = machine->codec_dai;
563 struct snd_soc_codec *codec = card->codec;
564 652
565 mutex_lock(&pcm_mutex); 653 mutex_lock(&pcm_mutex);
566 654
567 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 655 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
568 cpu_dai->playback.active--; 656 cpu_dai->playback_active--;
569 codec_dai->playback.active--; 657 codec_dai->playback_active--;
570 } else { 658 } else {
571 cpu_dai->capture.active--; 659 cpu_dai->capture_active--;
572 codec_dai->capture.active--; 660 codec_dai->capture_active--;
573 } 661 }
574 662
575 cpu_dai->active--; 663 cpu_dai->active--;
@@ -582,27 +670,28 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
582 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 670 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
583 snd_soc_dai_digital_mute(codec_dai, 1); 671 snd_soc_dai_digital_mute(codec_dai, 1);
584 672
585 if (cpu_dai->ops->shutdown) 673 if (cpu_dai->driver->ops->shutdown)
586 cpu_dai->ops->shutdown(substream, cpu_dai); 674 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
587 675
588 if (codec_dai->ops->shutdown) 676 if (codec_dai->driver->ops->shutdown)
589 codec_dai->ops->shutdown(substream, codec_dai); 677 codec_dai->driver->ops->shutdown(substream, codec_dai);
590 678
591 if (machine->ops && machine->ops->shutdown) 679 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
592 machine->ops->shutdown(substream); 680 rtd->dai_link->ops->shutdown(substream);
593 681
594 if (platform->pcm_ops->close) 682 if (platform->driver->ops->close)
595 platform->pcm_ops->close(substream); 683 platform->driver->ops->close(substream);
684 cpu_dai->runtime = NULL;
596 685
597 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 686 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
598 /* start delayed pop wq here for playback streams */ 687 /* start delayed pop wq here for playback streams */
599 codec_dai->pop_wait = 1; 688 codec_dai->pop_wait = 1;
600 schedule_delayed_work(&card->delayed_work, 689 schedule_delayed_work(&rtd->delayed_work,
601 msecs_to_jiffies(card->pmdown_time)); 690 msecs_to_jiffies(rtd->pmdown_time));
602 } else { 691 } else {
603 /* capture streams can be powered down now */ 692 /* capture streams can be powered down now */
604 snd_soc_dapm_stream_event(codec, 693 snd_soc_dapm_stream_event(rtd,
605 codec_dai->capture.stream_name, 694 codec_dai->driver->capture.stream_name,
606 SND_SOC_DAPM_STREAM_STOP); 695 SND_SOC_DAPM_STREAM_STOP);
607 } 696 }
608 697
@@ -618,43 +707,39 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
618static int soc_pcm_prepare(struct snd_pcm_substream *substream) 707static int soc_pcm_prepare(struct snd_pcm_substream *substream)
619{ 708{
620 struct snd_soc_pcm_runtime *rtd = substream->private_data; 709 struct snd_soc_pcm_runtime *rtd = substream->private_data;
621 struct snd_soc_device *socdev = rtd->socdev; 710 struct snd_soc_platform *platform = rtd->platform;
622 struct snd_soc_card *card = socdev->card; 711 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
623 struct snd_soc_dai_link *machine = rtd->dai; 712 struct snd_soc_dai *codec_dai = rtd->codec_dai;
624 struct snd_soc_platform *platform = card->platform;
625 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
626 struct snd_soc_dai *codec_dai = machine->codec_dai;
627 struct snd_soc_codec *codec = card->codec;
628 int ret = 0; 713 int ret = 0;
629 714
630 mutex_lock(&pcm_mutex); 715 mutex_lock(&pcm_mutex);
631 716
632 if (machine->ops && machine->ops->prepare) { 717 if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
633 ret = machine->ops->prepare(substream); 718 ret = rtd->dai_link->ops->prepare(substream);
634 if (ret < 0) { 719 if (ret < 0) {
635 printk(KERN_ERR "asoc: machine prepare error\n"); 720 printk(KERN_ERR "asoc: machine prepare error\n");
636 goto out; 721 goto out;
637 } 722 }
638 } 723 }
639 724
640 if (platform->pcm_ops->prepare) { 725 if (platform->driver->ops->prepare) {
641 ret = platform->pcm_ops->prepare(substream); 726 ret = platform->driver->ops->prepare(substream);
642 if (ret < 0) { 727 if (ret < 0) {
643 printk(KERN_ERR "asoc: platform prepare error\n"); 728 printk(KERN_ERR "asoc: platform prepare error\n");
644 goto out; 729 goto out;
645 } 730 }
646 } 731 }
647 732
648 if (codec_dai->ops->prepare) { 733 if (codec_dai->driver->ops->prepare) {
649 ret = codec_dai->ops->prepare(substream, codec_dai); 734 ret = codec_dai->driver->ops->prepare(substream, codec_dai);
650 if (ret < 0) { 735 if (ret < 0) {
651 printk(KERN_ERR "asoc: codec DAI prepare error\n"); 736 printk(KERN_ERR "asoc: codec DAI prepare error\n");
652 goto out; 737 goto out;
653 } 738 }
654 } 739 }
655 740
656 if (cpu_dai->ops->prepare) { 741 if (cpu_dai->driver->ops->prepare) {
657 ret = cpu_dai->ops->prepare(substream, cpu_dai); 742 ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
658 if (ret < 0) { 743 if (ret < 0) {
659 printk(KERN_ERR "asoc: cpu DAI prepare error\n"); 744 printk(KERN_ERR "asoc: cpu DAI prepare error\n");
660 goto out; 745 goto out;
@@ -665,16 +750,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
665 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 750 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
666 codec_dai->pop_wait) { 751 codec_dai->pop_wait) {
667 codec_dai->pop_wait = 0; 752 codec_dai->pop_wait = 0;
668 cancel_delayed_work(&card->delayed_work); 753 cancel_delayed_work(&rtd->delayed_work);
669 } 754 }
670 755
671 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 756 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
672 snd_soc_dapm_stream_event(codec, 757 snd_soc_dapm_stream_event(rtd,
673 codec_dai->playback.stream_name, 758 codec_dai->driver->playback.stream_name,
674 SND_SOC_DAPM_STREAM_START); 759 SND_SOC_DAPM_STREAM_START);
675 else 760 else
676 snd_soc_dapm_stream_event(codec, 761 snd_soc_dapm_stream_event(rtd,
677 codec_dai->capture.stream_name, 762 codec_dai->driver->capture.stream_name,
678 SND_SOC_DAPM_STREAM_START); 763 SND_SOC_DAPM_STREAM_START);
679 764
680 snd_soc_dai_digital_mute(codec_dai, 0); 765 snd_soc_dai_digital_mute(codec_dai, 0);
@@ -693,26 +778,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
693 struct snd_pcm_hw_params *params) 778 struct snd_pcm_hw_params *params)
694{ 779{
695 struct snd_soc_pcm_runtime *rtd = substream->private_data; 780 struct snd_soc_pcm_runtime *rtd = substream->private_data;
696 struct snd_soc_device *socdev = rtd->socdev; 781 struct snd_soc_platform *platform = rtd->platform;
697 struct snd_soc_dai_link *machine = rtd->dai; 782 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
698 struct snd_soc_card *card = socdev->card; 783 struct snd_soc_dai *codec_dai = rtd->codec_dai;
699 struct snd_soc_platform *platform = card->platform;
700 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
701 struct snd_soc_dai *codec_dai = machine->codec_dai;
702 int ret = 0; 784 int ret = 0;
703 785
704 mutex_lock(&pcm_mutex); 786 mutex_lock(&pcm_mutex);
705 787
706 if (machine->ops && machine->ops->hw_params) { 788 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
707 ret = machine->ops->hw_params(substream, params); 789 ret = rtd->dai_link->ops->hw_params(substream, params);
708 if (ret < 0) { 790 if (ret < 0) {
709 printk(KERN_ERR "asoc: machine hw_params failed\n"); 791 printk(KERN_ERR "asoc: machine hw_params failed\n");
710 goto out; 792 goto out;
711 } 793 }
712 } 794 }
713 795
714 if (codec_dai->ops->hw_params) { 796 if (codec_dai->driver->ops->hw_params) {
715 ret = codec_dai->ops->hw_params(substream, params, codec_dai); 797 ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
716 if (ret < 0) { 798 if (ret < 0) {
717 printk(KERN_ERR "asoc: can't set codec %s hw params\n", 799 printk(KERN_ERR "asoc: can't set codec %s hw params\n",
718 codec_dai->name); 800 codec_dai->name);
@@ -720,8 +802,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
720 } 802 }
721 } 803 }
722 804
723 if (cpu_dai->ops->hw_params) { 805 if (cpu_dai->driver->ops->hw_params) {
724 ret = cpu_dai->ops->hw_params(substream, params, cpu_dai); 806 ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
725 if (ret < 0) { 807 if (ret < 0) {
726 printk(KERN_ERR "asoc: interface %s hw params failed\n", 808 printk(KERN_ERR "asoc: interface %s hw params failed\n",
727 cpu_dai->name); 809 cpu_dai->name);
@@ -729,8 +811,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
729 } 811 }
730 } 812 }
731 813
732 if (platform->pcm_ops->hw_params) { 814 if (platform->driver->ops->hw_params) {
733 ret = platform->pcm_ops->hw_params(substream, params); 815 ret = platform->driver->ops->hw_params(substream, params);
734 if (ret < 0) { 816 if (ret < 0) {
735 printk(KERN_ERR "asoc: platform %s hw params failed\n", 817 printk(KERN_ERR "asoc: platform %s hw params failed\n",
736 platform->name); 818 platform->name);
@@ -738,23 +820,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
738 } 820 }
739 } 821 }
740 822
741 machine->rate = params_rate(params); 823 rtd->rate = params_rate(params);
742 824
743out: 825out:
744 mutex_unlock(&pcm_mutex); 826 mutex_unlock(&pcm_mutex);
745 return ret; 827 return ret;
746 828
747platform_err: 829platform_err:
748 if (cpu_dai->ops->hw_free) 830 if (cpu_dai->driver->ops->hw_free)
749 cpu_dai->ops->hw_free(substream, cpu_dai); 831 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
750 832
751interface_err: 833interface_err:
752 if (codec_dai->ops->hw_free) 834 if (codec_dai->driver->ops->hw_free)
753 codec_dai->ops->hw_free(substream, codec_dai); 835 codec_dai->driver->ops->hw_free(substream, codec_dai);
754 836
755codec_err: 837codec_err:
756 if (machine->ops && machine->ops->hw_free) 838 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
757 machine->ops->hw_free(substream); 839 rtd->dai_link->ops->hw_free(substream);
758 840
759 mutex_unlock(&pcm_mutex); 841 mutex_unlock(&pcm_mutex);
760 return ret; 842 return ret;
@@ -766,13 +848,10 @@ codec_err:
766static int soc_pcm_hw_free(struct snd_pcm_substream *substream) 848static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
767{ 849{
768 struct snd_soc_pcm_runtime *rtd = substream->private_data; 850 struct snd_soc_pcm_runtime *rtd = substream->private_data;
769 struct snd_soc_device *socdev = rtd->socdev; 851 struct snd_soc_platform *platform = rtd->platform;
770 struct snd_soc_dai_link *machine = rtd->dai; 852 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
771 struct snd_soc_card *card = socdev->card; 853 struct snd_soc_dai *codec_dai = rtd->codec_dai;
772 struct snd_soc_platform *platform = card->platform; 854 struct snd_soc_codec *codec = rtd->codec;
773 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
774 struct snd_soc_dai *codec_dai = machine->codec_dai;
775 struct snd_soc_codec *codec = card->codec;
776 855
777 mutex_lock(&pcm_mutex); 856 mutex_lock(&pcm_mutex);
778 857
@@ -781,19 +860,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
781 snd_soc_dai_digital_mute(codec_dai, 1); 860 snd_soc_dai_digital_mute(codec_dai, 1);
782 861
783 /* free any machine hw params */ 862 /* free any machine hw params */
784 if (machine->ops && machine->ops->hw_free) 863 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
785 machine->ops->hw_free(substream); 864 rtd->dai_link->ops->hw_free(substream);
786 865
787 /* free any DMA resources */ 866 /* free any DMA resources */
788 if (platform->pcm_ops->hw_free) 867 if (platform->driver->ops->hw_free)
789 platform->pcm_ops->hw_free(substream); 868 platform->driver->ops->hw_free(substream);
790 869
791 /* now free hw params for the DAI's */ 870 /* now free hw params for the DAI's */
792 if (codec_dai->ops->hw_free) 871 if (codec_dai->driver->ops->hw_free)
793 codec_dai->ops->hw_free(substream, codec_dai); 872 codec_dai->driver->ops->hw_free(substream, codec_dai);
794 873
795 if (cpu_dai->ops->hw_free) 874 if (cpu_dai->driver->ops->hw_free)
796 cpu_dai->ops->hw_free(substream, cpu_dai); 875 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
797 876
798 mutex_unlock(&pcm_mutex); 877 mutex_unlock(&pcm_mutex);
799 return 0; 878 return 0;
@@ -802,28 +881,25 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
802static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 881static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
803{ 882{
804 struct snd_soc_pcm_runtime *rtd = substream->private_data; 883 struct snd_soc_pcm_runtime *rtd = substream->private_data;
805 struct snd_soc_device *socdev = rtd->socdev; 884 struct snd_soc_platform *platform = rtd->platform;
806 struct snd_soc_card *card= socdev->card; 885 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
807 struct snd_soc_dai_link *machine = rtd->dai; 886 struct snd_soc_dai *codec_dai = rtd->codec_dai;
808 struct snd_soc_platform *platform = card->platform;
809 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
810 struct snd_soc_dai *codec_dai = machine->codec_dai;
811 int ret; 887 int ret;
812 888
813 if (codec_dai->ops->trigger) { 889 if (codec_dai->driver->ops->trigger) {
814 ret = codec_dai->ops->trigger(substream, cmd, codec_dai); 890 ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
815 if (ret < 0) 891 if (ret < 0)
816 return ret; 892 return ret;
817 } 893 }
818 894
819 if (platform->pcm_ops->trigger) { 895 if (platform->driver->ops->trigger) {
820 ret = platform->pcm_ops->trigger(substream, cmd); 896 ret = platform->driver->ops->trigger(substream, cmd);
821 if (ret < 0) 897 if (ret < 0)
822 return ret; 898 return ret;
823 } 899 }
824 900
825 if (cpu_dai->ops->trigger) { 901 if (cpu_dai->driver->ops->trigger) {
826 ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai); 902 ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
827 if (ret < 0) 903 if (ret < 0)
828 return ret; 904 return ret;
829 } 905 }
@@ -838,27 +914,24 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
838static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) 914static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
839{ 915{
840 struct snd_soc_pcm_runtime *rtd = substream->private_data; 916 struct snd_soc_pcm_runtime *rtd = substream->private_data;
841 struct snd_soc_device *socdev = rtd->socdev; 917 struct snd_soc_platform *platform = rtd->platform;
842 struct snd_soc_card *card = socdev->card; 918 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
843 struct snd_soc_platform *platform = card->platform; 919 struct snd_soc_dai *codec_dai = rtd->codec_dai;
844 struct snd_soc_dai_link *machine = rtd->dai;
845 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
846 struct snd_soc_dai *codec_dai = machine->codec_dai;
847 struct snd_pcm_runtime *runtime = substream->runtime; 920 struct snd_pcm_runtime *runtime = substream->runtime;
848 snd_pcm_uframes_t offset = 0; 921 snd_pcm_uframes_t offset = 0;
849 snd_pcm_sframes_t delay = 0; 922 snd_pcm_sframes_t delay = 0;
850 923
851 if (platform->pcm_ops->pointer) 924 if (platform->driver->ops->pointer)
852 offset = platform->pcm_ops->pointer(substream); 925 offset = platform->driver->ops->pointer(substream);
853 926
854 if (cpu_dai->ops->delay) 927 if (cpu_dai->driver->ops->delay)
855 delay += cpu_dai->ops->delay(substream, cpu_dai); 928 delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
856 929
857 if (codec_dai->ops->delay) 930 if (codec_dai->driver->ops->delay)
858 delay += codec_dai->ops->delay(substream, codec_dai); 931 delay += codec_dai->driver->ops->delay(substream, codec_dai);
859 932
860 if (platform->delay) 933 if (platform->driver->delay)
861 delay += platform->delay(substream, codec_dai); 934 delay += platform->driver->delay(substream, codec_dai);
862 935
863 runtime->delay = delay; 936 runtime->delay = delay;
864 937
@@ -881,104 +954,111 @@ static struct snd_pcm_ops soc_pcm_ops = {
881static int soc_suspend(struct device *dev) 954static int soc_suspend(struct device *dev)
882{ 955{
883 struct platform_device *pdev = to_platform_device(dev); 956 struct platform_device *pdev = to_platform_device(dev);
884 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 957 struct snd_soc_card *card = platform_get_drvdata(pdev);
885 struct snd_soc_card *card = socdev->card;
886 struct snd_soc_platform *platform = card->platform;
887 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
888 struct snd_soc_codec *codec = card->codec;
889 int i; 958 int i;
890 959
891 /* If the initialization of this soc device failed, there is no codec 960 /* If the initialization of this soc device failed, there is no codec
892 * associated with it. Just bail out in this case. 961 * associated with it. Just bail out in this case.
893 */ 962 */
894 if (!codec) 963 if (list_empty(&card->codec_dev_list))
895 return 0; 964 return 0;
896 965
897 /* Due to the resume being scheduled into a workqueue we could 966 /* Due to the resume being scheduled into a workqueue we could
898 * suspend before that's finished - wait for it to complete. 967 * suspend before that's finished - wait for it to complete.
899 */ 968 */
900 snd_power_lock(codec->card); 969 snd_power_lock(card->snd_card);
901 snd_power_wait(codec->card, SNDRV_CTL_POWER_D0); 970 snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0);
902 snd_power_unlock(codec->card); 971 snd_power_unlock(card->snd_card);
903 972
904 /* we're going to block userspace touching us until resume completes */ 973 /* we're going to block userspace touching us until resume completes */
905 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); 974 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);
906 975
907 /* mute any active DAC's */ 976 /* mute any active DAC's */
908 for (i = 0; i < card->num_links; i++) { 977 for (i = 0; i < card->num_rtd; i++) {
909 struct snd_soc_dai *dai = card->dai_link[i].codec_dai; 978 struct snd_soc_dai *dai = card->rtd[i].codec_dai;
979 struct snd_soc_dai_driver *drv = dai->driver;
910 980
911 if (card->dai_link[i].ignore_suspend) 981 if (card->rtd[i].dai_link->ignore_suspend)
912 continue; 982 continue;
913 983
914 if (dai->ops->digital_mute && dai->playback.active) 984 if (drv->ops->digital_mute && dai->playback_active)
915 dai->ops->digital_mute(dai, 1); 985 drv->ops->digital_mute(dai, 1);
916 } 986 }
917 987
918 /* suspend all pcms */ 988 /* suspend all pcms */
919 for (i = 0; i < card->num_links; i++) { 989 for (i = 0; i < card->num_rtd; i++) {
920 if (card->dai_link[i].ignore_suspend) 990 if (card->rtd[i].dai_link->ignore_suspend)
921 continue; 991 continue;
922 992
923 snd_pcm_suspend_all(card->dai_link[i].pcm); 993 snd_pcm_suspend_all(card->rtd[i].pcm);
924 } 994 }
925 995
926 if (card->suspend_pre) 996 if (card->suspend_pre)
927 card->suspend_pre(pdev, PMSG_SUSPEND); 997 card->suspend_pre(pdev, PMSG_SUSPEND);
928 998
929 for (i = 0; i < card->num_links; i++) { 999 for (i = 0; i < card->num_rtd; i++) {
930 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1000 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
1001 struct snd_soc_platform *platform = card->rtd[i].platform;
931 1002
932 if (card->dai_link[i].ignore_suspend) 1003 if (card->rtd[i].dai_link->ignore_suspend)
933 continue; 1004 continue;
934 1005
935 if (cpu_dai->suspend && !cpu_dai->ac97_control) 1006 if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control)
936 cpu_dai->suspend(cpu_dai); 1007 cpu_dai->driver->suspend(cpu_dai);
937 if (platform->suspend) 1008 if (platform->driver->suspend && !platform->suspended) {
938 platform->suspend(&card->dai_link[i]); 1009 platform->driver->suspend(cpu_dai);
1010 platform->suspended = 1;
1011 }
939 } 1012 }
940 1013
941 /* close any waiting streams and save state */ 1014 /* close any waiting streams and save state */
942 run_delayed_work(&card->delayed_work); 1015 for (i = 0; i < card->num_rtd; i++) {
943 codec->suspend_bias_level = codec->bias_level; 1016 run_delayed_work(&card->rtd[i].delayed_work);
1017 card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level;
1018 }
944 1019
945 for (i = 0; i < codec->num_dai; i++) { 1020 for (i = 0; i < card->num_rtd; i++) {
946 char *stream = codec->dai[i].playback.stream_name; 1021 struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
947 1022
948 if (card->dai_link[i].ignore_suspend) 1023 if (card->rtd[i].dai_link->ignore_suspend)
949 continue; 1024 continue;
950 1025
951 if (stream != NULL) 1026 if (driver->playback.stream_name != NULL)
952 snd_soc_dapm_stream_event(codec, stream, 1027 snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
953 SND_SOC_DAPM_STREAM_SUSPEND); 1028 SND_SOC_DAPM_STREAM_SUSPEND);
954 stream = codec->dai[i].capture.stream_name; 1029
955 if (stream != NULL) 1030 if (driver->capture.stream_name != NULL)
956 snd_soc_dapm_stream_event(codec, stream, 1031 snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
957 SND_SOC_DAPM_STREAM_SUSPEND); 1032 SND_SOC_DAPM_STREAM_SUSPEND);
958 } 1033 }
959 1034
960 /* If there are paths active then the CODEC will be held with 1035 /* suspend all CODECs */
961 * bias _ON and should not be suspended. */ 1036 for (i = 0; i < card->num_rtd; i++) {
962 if (codec_dev->suspend) { 1037 struct snd_soc_codec *codec = card->rtd[i].codec;
963 switch (codec->bias_level) { 1038 /* If there are paths active then the CODEC will be held with
964 case SND_SOC_BIAS_STANDBY: 1039 * bias _ON and should not be suspended. */
965 case SND_SOC_BIAS_OFF: 1040 if (!codec->suspended && codec->driver->suspend) {
966 codec_dev->suspend(pdev, PMSG_SUSPEND); 1041 switch (codec->bias_level) {
967 break; 1042 case SND_SOC_BIAS_STANDBY:
968 default: 1043 case SND_SOC_BIAS_OFF:
969 dev_dbg(socdev->dev, "CODEC is on over suspend\n"); 1044 codec->driver->suspend(codec, PMSG_SUSPEND);
970 break; 1045 codec->suspended = 1;
1046 break;
1047 default:
1048 dev_dbg(codec->dev, "CODEC is on over suspend\n");
1049 break;
1050 }
971 } 1051 }
972 } 1052 }
973 1053
974 for (i = 0; i < card->num_links; i++) { 1054 for (i = 0; i < card->num_rtd; i++) {
975 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1055 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
976 1056
977 if (card->dai_link[i].ignore_suspend) 1057 if (card->rtd[i].dai_link->ignore_suspend)
978 continue; 1058 continue;
979 1059
980 if (cpu_dai->suspend && cpu_dai->ac97_control) 1060 if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control)
981 cpu_dai->suspend(cpu_dai); 1061 cpu_dai->driver->suspend(cpu_dai);
982 } 1062 }
983 1063
984 if (card->suspend_post) 1064 if (card->suspend_post)
@@ -992,127 +1072,127 @@ static int soc_suspend(struct device *dev)
992 */ 1072 */
993static void soc_resume_deferred(struct work_struct *work) 1073static void soc_resume_deferred(struct work_struct *work)
994{ 1074{
995 struct snd_soc_card *card = container_of(work, 1075 struct snd_soc_card *card =
996 struct snd_soc_card, 1076 container_of(work, struct snd_soc_card, deferred_resume_work);
997 deferred_resume_work); 1077 struct platform_device *pdev = to_platform_device(card->dev);
998 struct snd_soc_device *socdev = card->socdev;
999 struct snd_soc_platform *platform = card->platform;
1000 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
1001 struct snd_soc_codec *codec = card->codec;
1002 struct platform_device *pdev = to_platform_device(socdev->dev);
1003 int i; 1078 int i;
1004 1079
1005 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, 1080 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
1006 * so userspace apps are blocked from touching us 1081 * so userspace apps are blocked from touching us
1007 */ 1082 */
1008 1083
1009 dev_dbg(socdev->dev, "starting resume work\n"); 1084 dev_dbg(card->dev, "starting resume work\n");
1010 1085
1011 /* Bring us up into D2 so that DAPM starts enabling things */ 1086 /* Bring us up into D2 so that DAPM starts enabling things */
1012 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D2); 1087 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
1013 1088
1014 if (card->resume_pre) 1089 if (card->resume_pre)
1015 card->resume_pre(pdev); 1090 card->resume_pre(pdev);
1016 1091
1017 for (i = 0; i < card->num_links; i++) { 1092 /* resume AC97 DAIs */
1018 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1093 for (i = 0; i < card->num_rtd; i++) {
1094 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
1019 1095
1020 if (card->dai_link[i].ignore_suspend) 1096 if (card->rtd[i].dai_link->ignore_suspend)
1021 continue; 1097 continue;
1022 1098
1023 if (cpu_dai->resume && cpu_dai->ac97_control) 1099 if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control)
1024 cpu_dai->resume(cpu_dai); 1100 cpu_dai->driver->resume(cpu_dai);
1025 } 1101 }
1026 1102
1027 /* If the CODEC was idle over suspend then it will have been 1103 for (i = 0; i < card->num_rtd; i++) {
1028 * left with bias OFF or STANDBY and suspended so we must now 1104 struct snd_soc_codec *codec = card->rtd[i].codec;
1029 * resume. Otherwise the suspend was suppressed. 1105 /* If the CODEC was idle over suspend then it will have been
1030 */ 1106 * left with bias OFF or STANDBY and suspended so we must now
1031 if (codec_dev->resume) { 1107 * resume. Otherwise the suspend was suppressed.
1032 switch (codec->bias_level) { 1108 */
1033 case SND_SOC_BIAS_STANDBY: 1109 if (codec->driver->resume && codec->suspended) {
1034 case SND_SOC_BIAS_OFF: 1110 switch (codec->bias_level) {
1035 codec_dev->resume(pdev); 1111 case SND_SOC_BIAS_STANDBY:
1036 break; 1112 case SND_SOC_BIAS_OFF:
1037 default: 1113 codec->driver->resume(codec);
1038 dev_dbg(socdev->dev, "CODEC was on over suspend\n"); 1114 codec->suspended = 0;
1039 break; 1115 break;
1116 default:
1117 dev_dbg(codec->dev, "CODEC was on over suspend\n");
1118 break;
1119 }
1040 } 1120 }
1041 } 1121 }
1042 1122
1043 for (i = 0; i < codec->num_dai; i++) { 1123 for (i = 0; i < card->num_rtd; i++) {
1044 char *stream = codec->dai[i].playback.stream_name; 1124 struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
1045 1125
1046 if (card->dai_link[i].ignore_suspend) 1126 if (card->rtd[i].dai_link->ignore_suspend)
1047 continue; 1127 continue;
1048 1128
1049 if (stream != NULL) 1129 if (driver->playback.stream_name != NULL)
1050 snd_soc_dapm_stream_event(codec, stream, 1130 snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
1051 SND_SOC_DAPM_STREAM_RESUME); 1131 SND_SOC_DAPM_STREAM_RESUME);
1052 stream = codec->dai[i].capture.stream_name; 1132
1053 if (stream != NULL) 1133 if (driver->capture.stream_name != NULL)
1054 snd_soc_dapm_stream_event(codec, stream, 1134 snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
1055 SND_SOC_DAPM_STREAM_RESUME); 1135 SND_SOC_DAPM_STREAM_RESUME);
1056 } 1136 }
1057 1137
1058 /* unmute any active DACs */ 1138 /* unmute any active DACs */
1059 for (i = 0; i < card->num_links; i++) { 1139 for (i = 0; i < card->num_rtd; i++) {
1060 struct snd_soc_dai *dai = card->dai_link[i].codec_dai; 1140 struct snd_soc_dai *dai = card->rtd[i].codec_dai;
1141 struct snd_soc_dai_driver *drv = dai->driver;
1061 1142
1062 if (card->dai_link[i].ignore_suspend) 1143 if (card->rtd[i].dai_link->ignore_suspend)
1063 continue; 1144 continue;
1064 1145
1065 if (dai->ops->digital_mute && dai->playback.active) 1146 if (drv->ops->digital_mute && dai->playback_active)
1066 dai->ops->digital_mute(dai, 0); 1147 drv->ops->digital_mute(dai, 0);
1067 } 1148 }
1068 1149
1069 for (i = 0; i < card->num_links; i++) { 1150 for (i = 0; i < card->num_rtd; i++) {
1070 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1151 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
1152 struct snd_soc_platform *platform = card->rtd[i].platform;
1071 1153
1072 if (card->dai_link[i].ignore_suspend) 1154 if (card->rtd[i].dai_link->ignore_suspend)
1073 continue; 1155 continue;
1074 1156
1075 if (cpu_dai->resume && !cpu_dai->ac97_control) 1157 if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control)
1076 cpu_dai->resume(cpu_dai); 1158 cpu_dai->driver->resume(cpu_dai);
1077 if (platform->resume) 1159 if (platform->driver->resume && platform->suspended) {
1078 platform->resume(&card->dai_link[i]); 1160 platform->driver->resume(cpu_dai);
1161 platform->suspended = 0;
1162 }
1079 } 1163 }
1080 1164
1081 if (card->resume_post) 1165 if (card->resume_post)
1082 card->resume_post(pdev); 1166 card->resume_post(pdev);
1083 1167
1084 dev_dbg(socdev->dev, "resume work completed\n"); 1168 dev_dbg(card->dev, "resume work completed\n");
1085 1169
1086 /* userspace can access us now we are back as we were before */ 1170 /* userspace can access us now we are back as we were before */
1087 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); 1171 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0);
1088} 1172}
1089 1173
1090/* powers up audio subsystem after a suspend */ 1174/* powers up audio subsystem after a suspend */
1091static int soc_resume(struct device *dev) 1175static int soc_resume(struct device *dev)
1092{ 1176{
1093 struct platform_device *pdev = to_platform_device(dev); 1177 struct platform_device *pdev = to_platform_device(dev);
1094 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1178 struct snd_soc_card *card = platform_get_drvdata(pdev);
1095 struct snd_soc_card *card = socdev->card; 1179 int i;
1096 struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai;
1097
1098 /* If the initialization of this soc device failed, there is no codec
1099 * associated with it. Just bail out in this case.
1100 */
1101 if (!card->codec)
1102 return 0;
1103 1180
1104 /* AC97 devices might have other drivers hanging off them so 1181 /* AC97 devices might have other drivers hanging off them so
1105 * need to resume immediately. Other drivers don't have that 1182 * need to resume immediately. Other drivers don't have that
1106 * problem and may take a substantial amount of time to resume 1183 * problem and may take a substantial amount of time to resume
1107 * due to I/O costs and anti-pop so handle them out of line. 1184 * due to I/O costs and anti-pop so handle them out of line.
1108 */ 1185 */
1109 if (cpu_dai->ac97_control) { 1186 for (i = 0; i < card->num_rtd; i++) {
1110 dev_dbg(socdev->dev, "Resuming AC97 immediately\n"); 1187 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
1111 soc_resume_deferred(&card->deferred_resume_work); 1188 if (cpu_dai->driver->ac97_control) {
1112 } else { 1189 dev_dbg(dev, "Resuming AC97 immediately\n");
1113 dev_dbg(socdev->dev, "Scheduling resume work\n"); 1190 soc_resume_deferred(&card->deferred_resume_work);
1114 if (!schedule_work(&card->deferred_resume_work)) 1191 } else {
1115 dev_err(socdev->dev, "resume work item may be lost\n"); 1192 dev_dbg(dev, "Scheduling resume work\n");
1193 if (!schedule_work(&card->deferred_resume_work))
1194 dev_err(dev, "resume work item may be lost\n");
1195 }
1116 } 1196 }
1117 1197
1118 return 0; 1198 return 0;
@@ -1125,198 +1205,440 @@ static int soc_resume(struct device *dev)
1125static struct snd_soc_dai_ops null_dai_ops = { 1205static struct snd_soc_dai_ops null_dai_ops = {
1126}; 1206};
1127 1207
1128static void snd_soc_instantiate_card(struct snd_soc_card *card) 1208static int soc_bind_dai_link(struct snd_soc_card *card, int num)
1129{ 1209{
1130 struct platform_device *pdev = container_of(card->dev, 1210 struct snd_soc_dai_link *dai_link = &card->dai_link[num];
1131 struct platform_device, 1211 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1132 dev);
1133 struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
1134 struct snd_soc_codec *codec; 1212 struct snd_soc_codec *codec;
1135 struct snd_soc_platform *platform; 1213 struct snd_soc_platform *platform;
1136 struct snd_soc_dai *dai; 1214 struct snd_soc_dai *codec_dai, *cpu_dai;
1137 int i, found, ret, ac97;
1138 1215
1139 if (card->instantiated) 1216 if (rtd->complete)
1140 return; 1217 return 1;
1218 dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
1141 1219
1142 found = 0; 1220 /* do we already have the CPU DAI for this link ? */
1143 list_for_each_entry(platform, &platform_list, list) 1221 if (rtd->cpu_dai) {
1144 if (card->platform == platform) { 1222 goto find_codec;
1145 found = 1; 1223 }
1146 break; 1224 /* no, then find CPU DAI from registered DAIs*/
1225 list_for_each_entry(cpu_dai, &dai_list, list) {
1226 if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) {
1227
1228 if (!try_module_get(cpu_dai->dev->driver->owner))
1229 return -ENODEV;
1230
1231 rtd->cpu_dai = cpu_dai;
1232 goto find_codec;
1147 } 1233 }
1148 if (!found) {
1149 dev_dbg(card->dev, "Platform %s not registered\n",
1150 card->platform->name);
1151 return;
1152 } 1234 }
1235 dev_dbg(card->dev, "CPU DAI %s not registered\n",
1236 dai_link->cpu_dai_name);
1153 1237
1154 ac97 = 0; 1238find_codec:
1155 for (i = 0; i < card->num_links; i++) { 1239 /* do we already have the CODEC for this link ? */
1156 found = 0; 1240 if (rtd->codec) {
1157 list_for_each_entry(dai, &dai_list, list) 1241 goto find_platform;
1158 if (card->dai_link[i].cpu_dai == dai) { 1242 }
1159 found = 1; 1243
1160 break; 1244 /* no, then find CODEC from registered CODECs*/
1245 list_for_each_entry(codec, &codec_list, list) {
1246 if (!strcmp(codec->name, dai_link->codec_name)) {
1247 rtd->codec = codec;
1248
1249 if (!try_module_get(codec->dev->driver->owner))
1250 return -ENODEV;
1251
1252 /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/
1253 list_for_each_entry(codec_dai, &dai_list, list) {
1254 if (codec->dev == codec_dai->dev &&
1255 !strcmp(codec_dai->name, dai_link->codec_dai_name)) {
1256 rtd->codec_dai = codec_dai;
1257 goto find_platform;
1258 }
1161 } 1259 }
1162 if (!found) { 1260 dev_dbg(card->dev, "CODEC DAI %s not registered\n",
1163 dev_dbg(card->dev, "DAI %s not registered\n", 1261 dai_link->codec_dai_name);
1164 card->dai_link[i].cpu_dai->name); 1262
1165 return; 1263 goto find_platform;
1166 } 1264 }
1265 }
1266 dev_dbg(card->dev, "CODEC %s not registered\n",
1267 dai_link->codec_name);
1167 1268
1168 if (card->dai_link[i].cpu_dai->ac97_control) 1269find_platform:
1169 ac97 = 1; 1270 /* do we already have the CODEC DAI for this link ? */
1271 if (rtd->platform) {
1272 goto out;
1170 } 1273 }
1274 /* no, then find CPU DAI from registered DAIs*/
1275 list_for_each_entry(platform, &platform_list, list) {
1276 if (!strcmp(platform->name, dai_link->platform_name)) {
1171 1277
1172 for (i = 0; i < card->num_links; i++) { 1278 if (!try_module_get(platform->dev->driver->owner))
1173 if (!card->dai_link[i].codec_dai->ops) 1279 return -ENODEV;
1174 card->dai_link[i].codec_dai->ops = &null_dai_ops; 1280
1281 rtd->platform = platform;
1282 goto out;
1283 }
1175 } 1284 }
1176 1285
1177 /* If we have AC97 in the system then don't wait for the 1286 dev_dbg(card->dev, "platform %s not registered\n",
1178 * codec. This will need revisiting if we have to handle 1287 dai_link->platform_name);
1179 * systems with mixed AC97 and non-AC97 parts. Only check for 1288 return 0;
1180 * DAIs currently; we can't do this per link since some AC97 1289
1181 * codecs have non-AC97 DAIs. 1290out:
1182 */ 1291 /* mark rtd as complete if we found all 4 of our client devices */
1183 if (!ac97) 1292 if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) {
1184 for (i = 0; i < card->num_links; i++) { 1293 rtd->complete = 1;
1185 found = 0; 1294 card->num_rtd++;
1186 list_for_each_entry(dai, &dai_list, list) 1295 }
1187 if (card->dai_link[i].codec_dai == dai) { 1296 return 1;
1188 found = 1; 1297}
1189 break; 1298
1190 } 1299static void soc_remove_dai_link(struct snd_soc_card *card, int num)
1191 if (!found) { 1300{
1192 dev_dbg(card->dev, "DAI %s not registered\n", 1301 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1193 card->dai_link[i].codec_dai->name); 1302 struct snd_soc_codec *codec = rtd->codec;
1194 return; 1303 struct snd_soc_platform *platform = rtd->platform;
1195 } 1304 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
1305 int err;
1306
1307 /* unregister the rtd device */
1308 if (rtd->dev_registered) {
1309 device_remove_file(&rtd->dev, &dev_attr_pmdown_time);
1310 device_unregister(&rtd->dev);
1311 rtd->dev_registered = 0;
1312 }
1313
1314 /* remove the CODEC DAI */
1315 if (codec_dai && codec_dai->probed) {
1316 if (codec_dai->driver->remove) {
1317 err = codec_dai->driver->remove(codec_dai);
1318 if (err < 0)
1319 printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);
1196 } 1320 }
1321 codec_dai->probed = 0;
1322 list_del(&codec_dai->card_list);
1323 }
1197 1324
1198 /* Note that we do not current check for codec components */ 1325 /* remove the platform */
1326 if (platform && platform->probed) {
1327 if (platform->driver->remove) {
1328 err = platform->driver->remove(platform);
1329 if (err < 0)
1330 printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
1331 }
1332 platform->probed = 0;
1333 list_del(&platform->card_list);
1334 module_put(platform->dev->driver->owner);
1335 }
1199 1336
1200 dev_dbg(card->dev, "All components present, instantiating\n"); 1337 /* remove the CODEC */
1338 if (codec && codec->probed) {
1339 if (codec->driver->remove) {
1340 err = codec->driver->remove(codec);
1341 if (err < 0)
1342 printk(KERN_ERR "asoc: failed to remove %s\n", codec->name);
1343 }
1201 1344
1202 /* Found everything, bring it up */ 1345 /* Make sure all DAPM widgets are freed */
1203 card->pmdown_time = pmdown_time; 1346 snd_soc_dapm_free(codec);
1204 1347
1205 if (card->probe) { 1348 soc_cleanup_codec_debugfs(codec);
1206 ret = card->probe(pdev); 1349 device_remove_file(&rtd->dev, &dev_attr_codec_reg);
1207 if (ret < 0) 1350 codec->probed = 0;
1208 return; 1351 list_del(&codec->card_list);
1352 module_put(codec->dev->driver->owner);
1209 } 1353 }
1210 1354
1211 for (i = 0; i < card->num_links; i++) { 1355 /* remove the cpu_dai */
1212 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1356 if (cpu_dai && cpu_dai->probed) {
1213 if (cpu_dai->probe) { 1357 if (cpu_dai->driver->remove) {
1214 ret = cpu_dai->probe(pdev, cpu_dai); 1358 err = cpu_dai->driver->remove(cpu_dai);
1215 if (ret < 0) 1359 if (err < 0)
1216 goto cpu_dai_err; 1360 printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);
1217 } 1361 }
1362 cpu_dai->probed = 0;
1363 list_del(&cpu_dai->card_list);
1364 module_put(cpu_dai->dev->driver->owner);
1218 } 1365 }
1366}
1219 1367
1220 if (codec_dev->probe) { 1368static void rtd_release(struct device *dev) {}
1221 ret = codec_dev->probe(pdev); 1369
1222 if (ret < 0) 1370static int soc_probe_dai_link(struct snd_soc_card *card, int num)
1223 goto cpu_dai_err; 1371{
1372 struct snd_soc_dai_link *dai_link = &card->dai_link[num];
1373 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1374 struct snd_soc_codec *codec = rtd->codec;
1375 struct snd_soc_platform *platform = rtd->platform;
1376 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
1377 int ret;
1378
1379 dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
1380
1381 /* config components */
1382 codec_dai->codec = codec;
1383 codec->card = card;
1384 cpu_dai->platform = platform;
1385 rtd->card = card;
1386 rtd->dev.parent = card->dev;
1387 codec_dai->card = card;
1388 cpu_dai->card = card;
1389
1390 /* set default power off timeout */
1391 rtd->pmdown_time = pmdown_time;
1392
1393 /* probe the cpu_dai */
1394 if (!cpu_dai->probed) {
1395 if (cpu_dai->driver->probe) {
1396 ret = cpu_dai->driver->probe(cpu_dai);
1397 if (ret < 0) {
1398 printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
1399 cpu_dai->name);
1400 return ret;
1401 }
1402 }
1403 cpu_dai->probed = 1;
1404 /* mark cpu_dai as probed and add to card cpu_dai list */
1405 list_add(&cpu_dai->card_list, &card->dai_dev_list);
1224 } 1406 }
1225 codec = card->codec;
1226 1407
1227 if (platform->probe) { 1408 /* probe the CODEC */
1228 ret = platform->probe(pdev); 1409 if (!codec->probed) {
1229 if (ret < 0) 1410 if (codec->driver->probe) {
1230 goto platform_err; 1411 ret = codec->driver->probe(codec);
1412 if (ret < 0) {
1413 printk(KERN_ERR "asoc: failed to probe CODEC %s\n",
1414 codec->name);
1415 return ret;
1416 }
1417 }
1418
1419 soc_init_codec_debugfs(codec);
1420
1421 /* mark codec as probed and add to card codec list */
1422 codec->probed = 1;
1423 list_add(&codec->card_list, &card->codec_dev_list);
1231 } 1424 }
1232 1425
1233 /* DAPM stream work */ 1426 /* probe the platform */
1234 INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work); 1427 if (!platform->probed) {
1235#ifdef CONFIG_PM 1428 if (platform->driver->probe) {
1236 /* deferred resume work */ 1429 ret = platform->driver->probe(platform);
1237 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); 1430 if (ret < 0) {
1238#endif 1431 printk(KERN_ERR "asoc: failed to probe platform %s\n",
1432 platform->name);
1433 return ret;
1434 }
1435 }
1436 /* mark platform as probed and add to card platform list */
1437 platform->probed = 1;
1438 list_add(&platform->card_list, &card->platform_dev_list);
1439 }
1239 1440
1240 for (i = 0; i < card->num_links; i++) { 1441 /* probe the CODEC DAI */
1241 if (card->dai_link[i].init) { 1442 if (!codec_dai->probed) {
1242 ret = card->dai_link[i].init(codec); 1443 if (codec_dai->driver->probe) {
1444 ret = codec_dai->driver->probe(codec_dai);
1243 if (ret < 0) { 1445 if (ret < 0) {
1244 printk(KERN_ERR "asoc: failed to init %s\n", 1446 printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
1245 card->dai_link[i].stream_name); 1447 codec_dai->name);
1246 continue; 1448 return ret;
1247 } 1449 }
1248 } 1450 }
1249 if (card->dai_link[i].codec_dai->ac97_control) 1451
1250 ac97 = 1; 1452 /* mark cpu_dai as probed and add to card cpu_dai list */
1453 codec_dai->probed = 1;
1454 list_add(&codec_dai->card_list, &card->dai_dev_list);
1251 } 1455 }
1252 1456
1253 snprintf(codec->card->shortname, sizeof(codec->card->shortname), 1457 /* DAPM dai link stream work */
1254 "%s", card->name); 1458 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1255 snprintf(codec->card->longname, sizeof(codec->card->longname), 1459
1256 "%s (%s)", card->name, codec->name); 1460 /* now that all clients have probed, initialise the DAI link */
1461 if (dai_link->init) {
1462 ret = dai_link->init(rtd);
1463 if (ret < 0) {
1464 printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name);
1465 return ret;
1466 }
1467 }
1257 1468
1258 /* Make sure all DAPM widgets are instantiated */ 1469 /* Make sure all DAPM widgets are instantiated */
1259 snd_soc_dapm_new_widgets(codec); 1470 snd_soc_dapm_new_widgets(codec);
1471 snd_soc_dapm_sync(codec);
1260 1472
1261 ret = snd_card_register(codec->card); 1473 /* register the rtd device */
1474 rtd->dev.release = rtd_release;
1475 rtd->dev.init_name = dai_link->name;
1476 ret = device_register(&rtd->dev);
1262 if (ret < 0) { 1477 if (ret < 0) {
1263 printk(KERN_ERR "asoc: failed to register soundcard for %s\n", 1478 printk(KERN_ERR "asoc: failed to register DAI runtime device %d\n", ret);
1264 codec->name); 1479 return ret;
1265 goto card_err;
1266 } 1480 }
1267 1481
1268 mutex_lock(&codec->mutex); 1482 rtd->dev_registered = 1;
1483 ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time);
1484 if (ret < 0)
1485 printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
1486
1487 /* add DAPM sysfs entries for this codec */
1488 ret = snd_soc_dapm_sys_add(&rtd->dev);
1489 if (ret < 0)
1490 printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entries\n");
1491
1492 /* add codec sysfs entries */
1493 ret = device_create_file(&rtd->dev, &dev_attr_codec_reg);
1494 if (ret < 0)
1495 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1496
1497 /* create the pcm */
1498 ret = soc_new_pcm(rtd, num);
1499 if (ret < 0) {
1500 printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name);
1501 return ret;
1502 }
1503
1504 /* add platform data for AC97 devices */
1505 if (rtd->codec_dai->driver->ac97_control)
1506 snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata);
1507
1508 return 0;
1509}
1510
1269#ifdef CONFIG_SND_SOC_AC97_BUS 1511#ifdef CONFIG_SND_SOC_AC97_BUS
1512static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
1513{
1514 int ret;
1515
1270 /* Only instantiate AC97 if not already done by the adaptor 1516 /* Only instantiate AC97 if not already done by the adaptor
1271 * for the generic AC97 subsystem. 1517 * for the generic AC97 subsystem.
1272 */ 1518 */
1273 if (ac97 && strcmp(codec->name, "AC97") != 0) { 1519 if (rtd->codec_dai->driver->ac97_control && !rtd->codec->ac97_registered) {
1274 ret = soc_ac97_dev_register(codec); 1520 /*
1521 * It is possible that the AC97 device is already registered to
1522 * the device subsystem. This happens when the device is created
1523 * via snd_ac97_mixer(). Currently only SoC codec that does so
1524 * is the generic AC97 glue but others migh emerge.
1525 *
1526 * In those cases we don't try to register the device again.
1527 */
1528 if (!rtd->codec->ac97_created)
1529 return 0;
1530
1531 ret = soc_ac97_dev_register(rtd->codec);
1275 if (ret < 0) { 1532 if (ret < 0) {
1276 printk(KERN_ERR "asoc: AC97 device register failed\n"); 1533 printk(KERN_ERR "asoc: AC97 device register failed\n");
1277 snd_card_free(codec->card); 1534 return ret;
1278 mutex_unlock(&codec->mutex);
1279 goto card_err;
1280 } 1535 }
1536
1537 rtd->codec->ac97_registered = 1;
1538 }
1539 return 0;
1540}
1541
1542static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
1543{
1544 if (codec->ac97_registered) {
1545 soc_ac97_dev_unregister(codec);
1546 codec->ac97_registered = 0;
1281 } 1547 }
1548}
1282#endif 1549#endif
1283 1550
1284 ret = snd_soc_dapm_sys_add(card->socdev->dev); 1551static void snd_soc_instantiate_card(struct snd_soc_card *card)
1285 if (ret < 0) 1552{
1286 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n"); 1553 struct platform_device *pdev = to_platform_device(card->dev);
1554 int ret, i;
1287 1555
1288 ret = device_create_file(card->socdev->dev, &dev_attr_pmdown_time); 1556 mutex_lock(&card->mutex);
1289 if (ret < 0)
1290 printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
1291 1557
1292 ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg); 1558 if (card->instantiated) {
1293 if (ret < 0) 1559 mutex_unlock(&card->mutex);
1294 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); 1560 return;
1561 }
1295 1562
1296 soc_init_codec_debugfs(codec); 1563 /* bind DAIs */
1297 mutex_unlock(&codec->mutex); 1564 for (i = 0; i < card->num_links; i++)
1565 soc_bind_dai_link(card, i);
1298 1566
1299 card->instantiated = 1; 1567 /* bind completed ? */
1568 if (card->num_rtd != card->num_links) {
1569 mutex_unlock(&card->mutex);
1570 return;
1571 }
1300 1572
1301 return; 1573 /* card bind complete so register a sound card */
1574 ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
1575 card->owner, 0, &card->snd_card);
1576 if (ret < 0) {
1577 printk(KERN_ERR "asoc: can't create sound card for card %s\n",
1578 card->name);
1579 mutex_unlock(&card->mutex);
1580 return;
1581 }
1582 card->snd_card->dev = card->dev;
1302 1583
1303card_err: 1584#ifdef CONFIG_PM
1304 if (platform->remove) 1585 /* deferred resume work */
1305 platform->remove(pdev); 1586 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
1587#endif
1306 1588
1307platform_err: 1589 /* initialise the sound card only once */
1308 if (codec_dev->remove) 1590 if (card->probe) {
1309 codec_dev->remove(pdev); 1591 ret = card->probe(pdev);
1592 if (ret < 0)
1593 goto card_probe_error;
1594 }
1310 1595
1311cpu_dai_err: 1596 for (i = 0; i < card->num_links; i++) {
1312 for (i--; i >= 0; i--) { 1597 ret = soc_probe_dai_link(card, i);
1313 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1598 if (ret < 0) {
1314 if (cpu_dai->remove) 1599 pr_err("asoc: failed to instantiate card %s: %d\n",
1315 cpu_dai->remove(pdev, cpu_dai); 1600 card->name, ret);
1601 goto probe_dai_err;
1602 }
1316 } 1603 }
1317 1604
1605 snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
1606 "%s", card->name);
1607 snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
1608 "%s", card->name);
1609
1610 ret = snd_card_register(card->snd_card);
1611 if (ret < 0) {
1612 printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
1613 goto probe_dai_err;
1614 }
1615
1616#ifdef CONFIG_SND_SOC_AC97_BUS
1617 /* register any AC97 codecs */
1618 for (i = 0; i < card->num_rtd; i++) {
1619 ret = soc_register_ac97_dai_link(&card->rtd[i]);
1620 if (ret < 0) {
1621 printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
1622 goto probe_dai_err;
1623 }
1624 }
1625#endif
1626
1627 card->instantiated = 1;
1628 mutex_unlock(&card->mutex);
1629 return;
1630
1631probe_dai_err:
1632 for (i = 0; i < card->num_links; i++)
1633 soc_remove_dai_link(card, i);
1634
1635card_probe_error:
1318 if (card->remove) 1636 if (card->remove)
1319 card->remove(pdev); 1637 card->remove(pdev);
1638
1639 snd_card_free(card->snd_card);
1640
1641 mutex_unlock(&card->mutex);
1320} 1642}
1321 1643
1322/* 1644/*
@@ -1333,15 +1655,15 @@ static void snd_soc_instantiate_cards(void)
1333/* probes a new socdev */ 1655/* probes a new socdev */
1334static int soc_probe(struct platform_device *pdev) 1656static int soc_probe(struct platform_device *pdev)
1335{ 1657{
1658 struct snd_soc_card *card = platform_get_drvdata(pdev);
1336 int ret = 0; 1659 int ret = 0;
1337 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1338 struct snd_soc_card *card = socdev->card;
1339
1340 /* Bodge while we push things out of socdev */
1341 card->socdev = socdev;
1342 1660
1343 /* Bodge while we unpick instantiation */ 1661 /* Bodge while we unpick instantiation */
1344 card->dev = &pdev->dev; 1662 card->dev = &pdev->dev;
1663 INIT_LIST_HEAD(&card->dai_dev_list);
1664 INIT_LIST_HEAD(&card->codec_dev_list);
1665 INIT_LIST_HEAD(&card->platform_dev_list);
1666
1345 ret = snd_soc_register_card(card); 1667 ret = snd_soc_register_card(card);
1346 if (ret != 0) { 1668 if (ret != 0) {
1347 dev_err(&pdev->dev, "Failed to register card\n"); 1669 dev_err(&pdev->dev, "Failed to register card\n");
@@ -1354,50 +1676,49 @@ static int soc_probe(struct platform_device *pdev)
1354/* removes a socdev */ 1676/* removes a socdev */
1355static int soc_remove(struct platform_device *pdev) 1677static int soc_remove(struct platform_device *pdev)
1356{ 1678{
1679 struct snd_soc_card *card = platform_get_drvdata(pdev);
1357 int i; 1680 int i;
1358 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1359 struct snd_soc_card *card = socdev->card;
1360 struct snd_soc_platform *platform = card->platform;
1361 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
1362 1681
1363 if (card->instantiated) { 1682 if (card->instantiated) {
1364 run_delayed_work(&card->delayed_work);
1365
1366 if (platform->remove)
1367 platform->remove(pdev);
1368 1683
1369 if (codec_dev->remove) 1684 /* make sure any delayed work runs */
1370 codec_dev->remove(pdev); 1685 for (i = 0; i < card->num_rtd; i++) {
1371 1686 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
1372 for (i = 0; i < card->num_links; i++) { 1687 run_delayed_work(&rtd->delayed_work);
1373 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
1374 if (cpu_dai->remove)
1375 cpu_dai->remove(pdev, cpu_dai);
1376 } 1688 }
1377 1689
1690 /* remove and free each DAI */
1691 for (i = 0; i < card->num_rtd; i++)
1692 soc_remove_dai_link(card, i);
1693
1694 /* remove the card */
1378 if (card->remove) 1695 if (card->remove)
1379 card->remove(pdev); 1696 card->remove(pdev);
1380 }
1381 1697
1698 kfree(card->rtd);
1699 snd_card_free(card->snd_card);
1700 }
1382 snd_soc_unregister_card(card); 1701 snd_soc_unregister_card(card);
1383
1384 return 0; 1702 return 0;
1385} 1703}
1386 1704
1387static int soc_poweroff(struct device *dev) 1705static int soc_poweroff(struct device *dev)
1388{ 1706{
1389 struct platform_device *pdev = to_platform_device(dev); 1707 struct platform_device *pdev = to_platform_device(dev);
1390 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1708 struct snd_soc_card *card = platform_get_drvdata(pdev);
1391 struct snd_soc_card *card = socdev->card; 1709 int i;
1392 1710
1393 if (!card->instantiated) 1711 if (!card->instantiated)
1394 return 0; 1712 return 0;
1395 1713
1396 /* Flush out pmdown_time work - we actually do want to run it 1714 /* Flush out pmdown_time work - we actually do want to run it
1397 * now, we're shutting down so no imminent restart. */ 1715 * now, we're shutting down so no imminent restart. */
1398 run_delayed_work(&card->delayed_work); 1716 for (i = 0; i < card->num_rtd; i++) {
1717 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
1718 run_delayed_work(&rtd->delayed_work);
1719 }
1399 1720
1400 snd_soc_dapm_shutdown(socdev); 1721 snd_soc_dapm_shutdown(card);
1401 1722
1402 return 0; 1723 return 0;
1403} 1724}
@@ -1420,53 +1741,42 @@ static struct platform_driver soc_driver = {
1420}; 1741};
1421 1742
1422/* create a new pcm */ 1743/* create a new pcm */
1423static int soc_new_pcm(struct snd_soc_device *socdev, 1744static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
1424 struct snd_soc_dai_link *dai_link, int num) 1745{
1425{ 1746 struct snd_soc_codec *codec = rtd->codec;
1426 struct snd_soc_card *card = socdev->card; 1747 struct snd_soc_platform *platform = rtd->platform;
1427 struct snd_soc_codec *codec = card->codec; 1748 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1428 struct snd_soc_platform *platform = card->platform; 1749 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1429 struct snd_soc_dai *codec_dai = dai_link->codec_dai;
1430 struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
1431 struct snd_soc_pcm_runtime *rtd;
1432 struct snd_pcm *pcm; 1750 struct snd_pcm *pcm;
1433 char new_name[64]; 1751 char new_name[64];
1434 int ret = 0, playback = 0, capture = 0; 1752 int ret = 0, playback = 0, capture = 0;
1435 1753
1436 rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
1437 if (rtd == NULL)
1438 return -ENOMEM;
1439
1440 rtd->dai = dai_link;
1441 rtd->socdev = socdev;
1442 codec_dai->codec = card->codec;
1443
1444 /* check client and interface hw capabilities */ 1754 /* check client and interface hw capabilities */
1445 snprintf(new_name, sizeof(new_name), "%s %s-%d", 1755 snprintf(new_name, sizeof(new_name), "%s %s-%d",
1446 dai_link->stream_name, codec_dai->name, num); 1756 rtd->dai_link->stream_name, codec_dai->name, num);
1447 1757
1448 if (codec_dai->playback.channels_min) 1758 if (codec_dai->driver->playback.channels_min)
1449 playback = 1; 1759 playback = 1;
1450 if (codec_dai->capture.channels_min) 1760 if (codec_dai->driver->capture.channels_min)
1451 capture = 1; 1761 capture = 1;
1452 1762
1453 ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback, 1763 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
1454 capture, &pcm); 1764 ret = snd_pcm_new(rtd->card->snd_card, new_name,
1765 num, playback, capture, &pcm);
1455 if (ret < 0) { 1766 if (ret < 0) {
1456 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", 1767 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
1457 codec->name);
1458 kfree(rtd);
1459 return ret; 1768 return ret;
1460 } 1769 }
1461 1770
1462 dai_link->pcm = pcm; 1771 rtd->pcm = pcm;
1463 pcm->private_data = rtd; 1772 pcm->private_data = rtd;
1464 soc_pcm_ops.mmap = platform->pcm_ops->mmap; 1773 soc_pcm_ops.mmap = platform->driver->ops->mmap;
1465 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; 1774 soc_pcm_ops.pointer = platform->driver->ops->pointer;
1466 soc_pcm_ops.copy = platform->pcm_ops->copy; 1775 soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
1467 soc_pcm_ops.silence = platform->pcm_ops->silence; 1776 soc_pcm_ops.copy = platform->driver->ops->copy;
1468 soc_pcm_ops.ack = platform->pcm_ops->ack; 1777 soc_pcm_ops.silence = platform->driver->ops->silence;
1469 soc_pcm_ops.page = platform->pcm_ops->page; 1778 soc_pcm_ops.ack = platform->driver->ops->ack;
1779 soc_pcm_ops.page = platform->driver->ops->page;
1470 1780
1471 if (playback) 1781 if (playback)
1472 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); 1782 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
@@ -1474,14 +1784,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1474 if (capture) 1784 if (capture)
1475 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); 1785 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
1476 1786
1477 ret = platform->pcm_new(codec->card, codec_dai, pcm); 1787 ret = platform->driver->pcm_new(rtd->card->snd_card, codec_dai, pcm);
1478 if (ret < 0) { 1788 if (ret < 0) {
1479 printk(KERN_ERR "asoc: platform pcm constructor failed\n"); 1789 printk(KERN_ERR "asoc: platform pcm constructor failed\n");
1480 kfree(rtd);
1481 return ret; 1790 return ret;
1482 } 1791 }
1483 1792
1484 pcm->private_free = platform->pcm_free; 1793 pcm->private_free = platform->driver->pcm_free;
1485 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, 1794 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
1486 cpu_dai->name); 1795 cpu_dai->name);
1487 return ret; 1796 return ret;
@@ -1497,8 +1806,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1497 */ 1806 */
1498int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) 1807int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
1499{ 1808{
1500 if (codec->volatile_register) 1809 if (codec->driver->volatile_register)
1501 return codec->volatile_register(reg); 1810 return codec->driver->volatile_register(reg);
1502 else 1811 else
1503 return 0; 1812 return 0;
1504} 1813}
@@ -1533,7 +1842,13 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
1533 1842
1534 codec->ac97->bus->ops = ops; 1843 codec->ac97->bus->ops = ops;
1535 codec->ac97->num = num; 1844 codec->ac97->num = num;
1536 codec->dev = &codec->ac97->dev; 1845
1846 /*
1847 * Mark the AC97 device to be created by us. This way we ensure that the
1848 * device will be registered with the device subsystem later on.
1849 */
1850 codec->ac97_created = 1;
1851
1537 mutex_unlock(&codec->mutex); 1852 mutex_unlock(&codec->mutex);
1538 return 0; 1853 return 0;
1539} 1854}
@@ -1548,9 +1863,13 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
1548void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) 1863void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
1549{ 1864{
1550 mutex_lock(&codec->mutex); 1865 mutex_lock(&codec->mutex);
1866#ifdef CONFIG_SND_SOC_AC97_BUS
1867 soc_unregister_ac97_dai_link(codec);
1868#endif
1551 kfree(codec->ac97->bus); 1869 kfree(codec->ac97->bus);
1552 kfree(codec->ac97); 1870 kfree(codec->ac97);
1553 codec->ac97 = NULL; 1871 codec->ac97 = NULL;
1872 codec->ac97_created = 0;
1554 mutex_unlock(&codec->mutex); 1873 mutex_unlock(&codec->mutex);
1555} 1874}
1556EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); 1875EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
@@ -1634,95 +1953,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1634EXPORT_SYMBOL_GPL(snd_soc_test_bits); 1953EXPORT_SYMBOL_GPL(snd_soc_test_bits);
1635 1954
1636/** 1955/**
1637 * snd_soc_new_pcms - create new sound card and pcms
1638 * @socdev: the SoC audio device
1639 * @idx: ALSA card index
1640 * @xid: card identification
1641 *
1642 * Create a new sound card based upon the codec and interface pcms.
1643 *
1644 * Returns 0 for success, else error.
1645 */
1646int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1647{
1648 struct snd_soc_card *card = socdev->card;
1649 struct snd_soc_codec *codec = card->codec;
1650 int ret, i;
1651
1652 mutex_lock(&codec->mutex);
1653
1654 /* register a sound card */
1655 ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card);
1656 if (ret < 0) {
1657 printk(KERN_ERR "asoc: can't create sound card for codec %s\n",
1658 codec->name);
1659 mutex_unlock(&codec->mutex);
1660 return ret;
1661 }
1662
1663 codec->socdev = socdev;
1664 codec->card->dev = socdev->dev;
1665 codec->card->private_data = codec;
1666 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
1667
1668 /* create the pcms */
1669 for (i = 0; i < card->num_links; i++) {
1670 ret = soc_new_pcm(socdev, &card->dai_link[i], i);
1671 if (ret < 0) {
1672 printk(KERN_ERR "asoc: can't create pcm %s\n",
1673 card->dai_link[i].stream_name);
1674 mutex_unlock(&codec->mutex);
1675 return ret;
1676 }
1677 /* Check for codec->ac97 to handle the ac97.c fun */
1678 if (card->dai_link[i].codec_dai->ac97_control && codec->ac97) {
1679 snd_ac97_dev_add_pdata(codec->ac97,
1680 card->dai_link[i].cpu_dai->ac97_pdata);
1681 }
1682 }
1683
1684 mutex_unlock(&codec->mutex);
1685 return ret;
1686}
1687EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1688
1689/**
1690 * snd_soc_free_pcms - free sound card and pcms
1691 * @socdev: the SoC audio device
1692 *
1693 * Frees sound card and pcms associated with the socdev.
1694 * Also unregister the codec if it is an AC97 device.
1695 */
1696void snd_soc_free_pcms(struct snd_soc_device *socdev)
1697{
1698 struct snd_soc_codec *codec = socdev->card->codec;
1699#ifdef CONFIG_SND_SOC_AC97_BUS
1700 struct snd_soc_dai *codec_dai;
1701 int i;
1702#endif
1703
1704 mutex_lock(&codec->mutex);
1705 soc_cleanup_codec_debugfs(codec);
1706#ifdef CONFIG_SND_SOC_AC97_BUS
1707 for (i = 0; i < codec->num_dai; i++) {
1708 codec_dai = &codec->dai[i];
1709 if (codec_dai->ac97_control && codec->ac97 &&
1710 strcmp(codec->name, "AC97") != 0) {
1711 soc_ac97_dev_unregister(codec);
1712 goto free_card;
1713 }
1714 }
1715free_card:
1716#endif
1717
1718 if (codec->card)
1719 snd_card_free(codec->card);
1720 device_remove_file(socdev->dev, &dev_attr_codec_reg);
1721 mutex_unlock(&codec->mutex);
1722}
1723EXPORT_SYMBOL_GPL(snd_soc_free_pcms);
1724
1725/**
1726 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters 1956 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
1727 * @substream: the pcm substream 1957 * @substream: the pcm substream
1728 * @hw: the hardware parameters 1958 * @hw: the hardware parameters
@@ -1783,15 +2013,15 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
1783int snd_soc_add_controls(struct snd_soc_codec *codec, 2013int snd_soc_add_controls(struct snd_soc_codec *codec,
1784 const struct snd_kcontrol_new *controls, int num_controls) 2014 const struct snd_kcontrol_new *controls, int num_controls)
1785{ 2015{
1786 struct snd_card *card = codec->card; 2016 struct snd_card *card = codec->card->snd_card;
1787 int err, i; 2017 int err, i;
1788 2018
1789 for (i = 0; i < num_controls; i++) { 2019 for (i = 0; i < num_controls; i++) {
1790 const struct snd_kcontrol_new *control = &controls[i]; 2020 const struct snd_kcontrol_new *control = &controls[i];
1791 err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); 2021 err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL));
1792 if (err < 0) { 2022 if (err < 0) {
1793 dev_err(codec->dev, "%s: Failed to add %s\n", 2023 dev_err(codec->dev, "%s: Failed to add %s: %d\n",
1794 codec->name, control->name); 2024 codec->name, control->name, err);
1795 return err; 2025 return err;
1796 } 2026 }
1797 } 2027 }
@@ -2338,7 +2568,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2338int snd_soc_limit_volume(struct snd_soc_codec *codec, 2568int snd_soc_limit_volume(struct snd_soc_codec *codec,
2339 const char *name, int max) 2569 const char *name, int max)
2340{ 2570{
2341 struct snd_card *card = codec->card; 2571 struct snd_card *card = codec->card->snd_card;
2342 struct snd_kcontrol *kctl; 2572 struct snd_kcontrol *kctl;
2343 struct soc_mixer_control *mc; 2573 struct soc_mixer_control *mc;
2344 int found = 0; 2574 int found = 0;
@@ -2470,8 +2700,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
2470int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 2700int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
2471 unsigned int freq, int dir) 2701 unsigned int freq, int dir)
2472{ 2702{
2473 if (dai->ops && dai->ops->set_sysclk) 2703 if (dai->driver && dai->driver->ops->set_sysclk)
2474 return dai->ops->set_sysclk(dai, clk_id, freq, dir); 2704 return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
2475 else 2705 else
2476 return -EINVAL; 2706 return -EINVAL;
2477} 2707}
@@ -2490,8 +2720,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
2490int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, 2720int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
2491 int div_id, int div) 2721 int div_id, int div)
2492{ 2722{
2493 if (dai->ops && dai->ops->set_clkdiv) 2723 if (dai->driver && dai->driver->ops->set_clkdiv)
2494 return dai->ops->set_clkdiv(dai, div_id, div); 2724 return dai->driver->ops->set_clkdiv(dai, div_id, div);
2495 else 2725 else
2496 return -EINVAL; 2726 return -EINVAL;
2497} 2727}
@@ -2510,8 +2740,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2510int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, 2740int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
2511 unsigned int freq_in, unsigned int freq_out) 2741 unsigned int freq_in, unsigned int freq_out)
2512{ 2742{
2513 if (dai->ops && dai->ops->set_pll) 2743 if (dai->driver && dai->driver->ops->set_pll)
2514 return dai->ops->set_pll(dai, pll_id, source, 2744 return dai->driver->ops->set_pll(dai, pll_id, source,
2515 freq_in, freq_out); 2745 freq_in, freq_out);
2516 else 2746 else
2517 return -EINVAL; 2747 return -EINVAL;
@@ -2527,8 +2757,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
2527 */ 2757 */
2528int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 2758int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2529{ 2759{
2530 if (dai->ops && dai->ops->set_fmt) 2760 if (dai->driver && dai->driver->ops->set_fmt)
2531 return dai->ops->set_fmt(dai, fmt); 2761 return dai->driver->ops->set_fmt(dai, fmt);
2532 else 2762 else
2533 return -EINVAL; 2763 return -EINVAL;
2534} 2764}
@@ -2548,8 +2778,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
2548int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 2778int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
2549 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) 2779 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
2550{ 2780{
2551 if (dai->ops && dai->ops->set_tdm_slot) 2781 if (dai->driver && dai->driver->ops->set_tdm_slot)
2552 return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask, 2782 return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
2553 slots, slot_width); 2783 slots, slot_width);
2554 else 2784 else
2555 return -EINVAL; 2785 return -EINVAL;
@@ -2572,8 +2802,8 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
2572 unsigned int tx_num, unsigned int *tx_slot, 2802 unsigned int tx_num, unsigned int *tx_slot,
2573 unsigned int rx_num, unsigned int *rx_slot) 2803 unsigned int rx_num, unsigned int *rx_slot)
2574{ 2804{
2575 if (dai->ops && dai->ops->set_channel_map) 2805 if (dai->driver && dai->driver->ops->set_channel_map)
2576 return dai->ops->set_channel_map(dai, tx_num, tx_slot, 2806 return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
2577 rx_num, rx_slot); 2807 rx_num, rx_slot);
2578 else 2808 else
2579 return -EINVAL; 2809 return -EINVAL;
@@ -2589,8 +2819,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
2589 */ 2819 */
2590int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 2820int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
2591{ 2821{
2592 if (dai->ops && dai->ops->set_tristate) 2822 if (dai->driver && dai->driver->ops->set_tristate)
2593 return dai->ops->set_tristate(dai, tristate); 2823 return dai->driver->ops->set_tristate(dai, tristate);
2594 else 2824 else
2595 return -EINVAL; 2825 return -EINVAL;
2596} 2826}
@@ -2605,8 +2835,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
2605 */ 2835 */
2606int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) 2836int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
2607{ 2837{
2608 if (dai->ops && dai->ops->digital_mute) 2838 if (dai->driver && dai->driver->ops->digital_mute)
2609 return dai->ops->digital_mute(dai, mute); 2839 return dai->driver->ops->digital_mute(dai, mute);
2610 else 2840 else
2611 return -EINVAL; 2841 return -EINVAL;
2612} 2842}
@@ -2623,11 +2853,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
2623 */ 2853 */
2624static int snd_soc_register_card(struct snd_soc_card *card) 2854static int snd_soc_register_card(struct snd_soc_card *card)
2625{ 2855{
2856 int i;
2857
2626 if (!card->name || !card->dev) 2858 if (!card->name || !card->dev)
2627 return -EINVAL; 2859 return -EINVAL;
2628 2860
2861 card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links,
2862 GFP_KERNEL);
2863 if (card->rtd == NULL)
2864 return -ENOMEM;
2865
2866 for (i = 0; i < card->num_links; i++)
2867 card->rtd[i].dai_link = &card->dai_link[i];
2868
2629 INIT_LIST_HEAD(&card->list); 2869 INIT_LIST_HEAD(&card->list);
2630 card->instantiated = 0; 2870 card->instantiated = 0;
2871 mutex_init(&card->mutex);
2631 2872
2632 mutex_lock(&client_mutex); 2873 mutex_lock(&client_mutex);
2633 list_add(&card->list, &card_list); 2874 list_add(&card->list, &card_list);
@@ -2653,30 +2894,97 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
2653 mutex_lock(&client_mutex); 2894 mutex_lock(&client_mutex);
2654 list_del(&card->list); 2895 list_del(&card->list);
2655 mutex_unlock(&client_mutex); 2896 mutex_unlock(&client_mutex);
2656
2657 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); 2897 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
2658 2898
2659 return 0; 2899 return 0;
2660} 2900}
2661 2901
2902/*
2903 * Simplify DAI link configuration by removing ".-1" from device names
2904 * and sanitizing names.
2905 */
2906static inline char *fmt_single_name(struct device *dev, int *id)
2907{
2908 char *found, name[NAME_SIZE];
2909 int id1, id2;
2910
2911 if (dev_name(dev) == NULL)
2912 return NULL;
2913
2914 strncpy(name, dev_name(dev), NAME_SIZE);
2915
2916 /* are we a "%s.%d" name (platform and SPI components) */
2917 found = strstr(name, dev->driver->name);
2918 if (found) {
2919 /* get ID */
2920 if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) {
2921
2922 /* discard ID from name if ID == -1 */
2923 if (*id == -1)
2924 found[strlen(dev->driver->name)] = '\0';
2925 }
2926
2927 } else {
2928 /* I2C component devices are named "bus-addr" */
2929 if (sscanf(name, "%x-%x", &id1, &id2) == 2) {
2930 char tmp[NAME_SIZE];
2931
2932 /* create unique ID number from I2C addr and bus */
2933 *id = ((id1 & 0xffff) << 16) + id2;
2934
2935 /* sanitize component name for DAI link creation */
2936 snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name);
2937 strncpy(name, tmp, NAME_SIZE);
2938 } else
2939 *id = 0;
2940 }
2941
2942 return kstrdup(name, GFP_KERNEL);
2943}
2944
2945/*
2946 * Simplify DAI link naming for single devices with multiple DAIs by removing
2947 * any ".-1" and using the DAI name (instead of device name).
2948 */
2949static inline char *fmt_multiple_name(struct device *dev,
2950 struct snd_soc_dai_driver *dai_drv)
2951{
2952 if (dai_drv->name == NULL) {
2953 printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n",
2954 dev_name(dev));
2955 return NULL;
2956 }
2957
2958 return kstrdup(dai_drv->name, GFP_KERNEL);
2959}
2960
2662/** 2961/**
2663 * snd_soc_register_dai - Register a DAI with the ASoC core 2962 * snd_soc_register_dai - Register a DAI with the ASoC core
2664 * 2963 *
2665 * @dai: DAI to register 2964 * @dai: DAI to register
2666 */ 2965 */
2667int snd_soc_register_dai(struct snd_soc_dai *dai) 2966int snd_soc_register_dai(struct device *dev,
2967 struct snd_soc_dai_driver *dai_drv)
2668{ 2968{
2669 if (!dai->name) 2969 struct snd_soc_dai *dai;
2670 return -EINVAL; 2970
2971 dev_dbg(dev, "dai register %s\n", dev_name(dev));
2671 2972
2672 /* The device should become mandatory over time */ 2973 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
2673 if (!dai->dev) 2974 if (dai == NULL)
2674 printk(KERN_WARNING "No device for DAI %s\n", dai->name); 2975 return -ENOMEM;
2675 2976
2676 if (!dai->ops) 2977 /* create DAI component name */
2677 dai->ops = &null_dai_ops; 2978 dai->name = fmt_single_name(dev, &dai->id);
2979 if (dai->name == NULL) {
2980 kfree(dai);
2981 return -ENOMEM;
2982 }
2678 2983
2679 INIT_LIST_HEAD(&dai->list); 2984 dai->dev = dev;
2985 dai->driver = dai_drv;
2986 if (!dai->driver->ops)
2987 dai->driver->ops = &null_dai_ops;
2680 2988
2681 mutex_lock(&client_mutex); 2989 mutex_lock(&client_mutex);
2682 list_add(&dai->list, &dai_list); 2990 list_add(&dai->list, &dai_list);
@@ -2694,13 +3002,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dai);
2694 * 3002 *
2695 * @dai: DAI to unregister 3003 * @dai: DAI to unregister
2696 */ 3004 */
2697void snd_soc_unregister_dai(struct snd_soc_dai *dai) 3005void snd_soc_unregister_dai(struct device *dev)
2698{ 3006{
3007 struct snd_soc_dai *dai;
3008
3009 list_for_each_entry(dai, &dai_list, list) {
3010 if (dev == dai->dev)
3011 goto found;
3012 }
3013 return;
3014
3015found:
2699 mutex_lock(&client_mutex); 3016 mutex_lock(&client_mutex);
2700 list_del(&dai->list); 3017 list_del(&dai->list);
2701 mutex_unlock(&client_mutex); 3018 mutex_unlock(&client_mutex);
2702 3019
2703 pr_debug("Unregistered DAI '%s'\n", dai->name); 3020 pr_debug("Unregistered DAI '%s'\n", dai->name);
3021 kfree(dai->name);
3022 kfree(dai);
2704} 3023}
2705EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); 3024EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
2706 3025
@@ -2710,21 +3029,50 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
2710 * @dai: Array of DAIs to register 3029 * @dai: Array of DAIs to register
2711 * @count: Number of DAIs 3030 * @count: Number of DAIs
2712 */ 3031 */
2713int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count) 3032int snd_soc_register_dais(struct device *dev,
3033 struct snd_soc_dai_driver *dai_drv, size_t count)
2714{ 3034{
2715 int i, ret; 3035 struct snd_soc_dai *dai;
3036 int i, ret = 0;
3037
3038 dev_dbg(dev, "dai register %s #%Zu\n", dev_name(dev), count);
2716 3039
2717 for (i = 0; i < count; i++) { 3040 for (i = 0; i < count; i++) {
2718 ret = snd_soc_register_dai(&dai[i]); 3041
2719 if (ret != 0) 3042 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
3043 if (dai == NULL)
3044 return -ENOMEM;
3045
3046 /* create DAI component name */
3047 dai->name = fmt_multiple_name(dev, &dai_drv[i]);
3048 if (dai->name == NULL) {
3049 kfree(dai);
3050 ret = -EINVAL;
2720 goto err; 3051 goto err;
3052 }
3053
3054 dai->dev = dev;
3055 dai->driver = &dai_drv[i];
3056 if (dai->driver->id)
3057 dai->id = dai->driver->id;
3058 else
3059 dai->id = i;
3060 if (!dai->driver->ops)
3061 dai->driver->ops = &null_dai_ops;
3062
3063 mutex_lock(&client_mutex);
3064 list_add(&dai->list, &dai_list);
3065 mutex_unlock(&client_mutex);
3066
3067 pr_debug("Registered DAI '%s'\n", dai->name);
2721 } 3068 }
2722 3069
3070 snd_soc_instantiate_cards();
2723 return 0; 3071 return 0;
2724 3072
2725err: 3073err:
2726 for (i--; i >= 0; i--) 3074 for (i--; i >= 0; i--)
2727 snd_soc_unregister_dai(&dai[i]); 3075 snd_soc_unregister_dai(dev);
2728 3076
2729 return ret; 3077 return ret;
2730} 3078}
@@ -2736,12 +3084,12 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais);
2736 * @dai: Array of DAIs to unregister 3084 * @dai: Array of DAIs to unregister
2737 * @count: Number of DAIs 3085 * @count: Number of DAIs
2738 */ 3086 */
2739void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count) 3087void snd_soc_unregister_dais(struct device *dev, size_t count)
2740{ 3088{
2741 int i; 3089 int i;
2742 3090
2743 for (i = 0; i < count; i++) 3091 for (i = 0; i < count; i++)
2744 snd_soc_unregister_dai(&dai[i]); 3092 snd_soc_unregister_dai(dev);
2745} 3093}
2746EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); 3094EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
2747 3095
@@ -2750,12 +3098,26 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
2750 * 3098 *
2751 * @platform: platform to register 3099 * @platform: platform to register
2752 */ 3100 */
2753int snd_soc_register_platform(struct snd_soc_platform *platform) 3101int snd_soc_register_platform(struct device *dev,
3102 struct snd_soc_platform_driver *platform_drv)
2754{ 3103{
2755 if (!platform->name) 3104 struct snd_soc_platform *platform;
2756 return -EINVAL; 3105
3106 dev_dbg(dev, "platform register %s\n", dev_name(dev));
2757 3107
2758 INIT_LIST_HEAD(&platform->list); 3108 platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
3109 if (platform == NULL)
3110 return -ENOMEM;
3111
3112 /* create platform component name */
3113 platform->name = fmt_single_name(dev, &platform->id);
3114 if (platform->name == NULL) {
3115 kfree(platform);
3116 return -ENOMEM;
3117 }
3118
3119 platform->dev = dev;
3120 platform->driver = platform_drv;
2759 3121
2760 mutex_lock(&client_mutex); 3122 mutex_lock(&client_mutex);
2761 list_add(&platform->list, &platform_list); 3123 list_add(&platform->list, &platform_list);
@@ -2773,13 +3135,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
2773 * 3135 *
2774 * @platform: platform to unregister 3136 * @platform: platform to unregister
2775 */ 3137 */
2776void snd_soc_unregister_platform(struct snd_soc_platform *platform) 3138void snd_soc_unregister_platform(struct device *dev)
2777{ 3139{
3140 struct snd_soc_platform *platform;
3141
3142 list_for_each_entry(platform, &platform_list, list) {
3143 if (dev == platform->dev)
3144 goto found;
3145 }
3146 return;
3147
3148found:
2778 mutex_lock(&client_mutex); 3149 mutex_lock(&client_mutex);
2779 list_del(&platform->list); 3150 list_del(&platform->list);
2780 mutex_unlock(&client_mutex); 3151 mutex_unlock(&client_mutex);
2781 3152
2782 pr_debug("Unregistered platform '%s'\n", platform->name); 3153 pr_debug("Unregistered platform '%s'\n", platform->name);
3154 kfree(platform->name);
3155 kfree(platform);
2783} 3156}
2784EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); 3157EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2785 3158
@@ -2821,22 +3194,61 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
2821 * 3194 *
2822 * @codec: codec to register 3195 * @codec: codec to register
2823 */ 3196 */
2824int snd_soc_register_codec(struct snd_soc_codec *codec) 3197int snd_soc_register_codec(struct device *dev,
3198 struct snd_soc_codec_driver *codec_drv,
3199 struct snd_soc_dai_driver *dai_drv, int num_dai)
2825{ 3200{
2826 int i; 3201 struct snd_soc_codec *codec;
3202 int ret, i;
2827 3203
2828 if (!codec->name) 3204 dev_dbg(dev, "codec register %s\n", dev_name(dev));
2829 return -EINVAL; 3205
3206 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
3207 if (codec == NULL)
3208 return -ENOMEM;
3209
3210 /* create CODEC component name */
3211 codec->name = fmt_single_name(dev, &codec->id);
3212 if (codec->name == NULL) {
3213 kfree(codec);
3214 return -ENOMEM;
3215 }
2830 3216
2831 /* The device should become mandatory over time */ 3217 /* allocate CODEC register cache */
2832 if (!codec->dev) 3218 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
2833 printk(KERN_WARNING "No device for codec %s\n", codec->name);
2834 3219
2835 INIT_LIST_HEAD(&codec->list); 3220 if (codec_drv->reg_cache_default)
3221 codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
3222 codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL);
3223 else
3224 codec->reg_cache = kzalloc(codec_drv->reg_cache_size *
3225 codec_drv->reg_word_size, GFP_KERNEL);
2836 3226
2837 for (i = 0; i < codec->num_dai; i++) { 3227 if (codec->reg_cache == NULL) {
2838 fixup_codec_formats(&codec->dai[i].playback); 3228 kfree(codec->name);
2839 fixup_codec_formats(&codec->dai[i].capture); 3229 kfree(codec);
3230 return -ENOMEM;
3231 }
3232 }
3233
3234 codec->dev = dev;
3235 codec->driver = codec_drv;
3236 codec->bias_level = SND_SOC_BIAS_OFF;
3237 codec->num_dai = num_dai;
3238 mutex_init(&codec->mutex);
3239 INIT_LIST_HEAD(&codec->dapm_widgets);
3240 INIT_LIST_HEAD(&codec->dapm_paths);
3241
3242 for (i = 0; i < num_dai; i++) {
3243 fixup_codec_formats(&dai_drv[i].playback);
3244 fixup_codec_formats(&dai_drv[i].capture);
3245 }
3246
3247 /* register any DAIs */
3248 if (num_dai) {
3249 ret = snd_soc_register_dais(dev, dai_drv, num_dai);
3250 if (ret < 0)
3251 goto error;
2840 } 3252 }
2841 3253
2842 mutex_lock(&client_mutex); 3254 mutex_lock(&client_mutex);
@@ -2845,8 +3257,17 @@ int snd_soc_register_codec(struct snd_soc_codec *codec)
2845 mutex_unlock(&client_mutex); 3257 mutex_unlock(&client_mutex);
2846 3258
2847 pr_debug("Registered codec '%s'\n", codec->name); 3259 pr_debug("Registered codec '%s'\n", codec->name);
2848
2849 return 0; 3260 return 0;
3261
3262error:
3263 for (i--; i >= 0; i--)
3264 snd_soc_unregister_dai(dev);
3265
3266 if (codec->reg_cache)
3267 kfree(codec->reg_cache);
3268 kfree(codec->name);
3269 kfree(codec);
3270 return ret;
2850} 3271}
2851EXPORT_SYMBOL_GPL(snd_soc_register_codec); 3272EXPORT_SYMBOL_GPL(snd_soc_register_codec);
2852 3273
@@ -2855,13 +3276,32 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec);
2855 * 3276 *
2856 * @codec: codec to unregister 3277 * @codec: codec to unregister
2857 */ 3278 */
2858void snd_soc_unregister_codec(struct snd_soc_codec *codec) 3279void snd_soc_unregister_codec(struct device *dev)
2859{ 3280{
3281 struct snd_soc_codec *codec;
3282 int i;
3283
3284 list_for_each_entry(codec, &codec_list, list) {
3285 if (dev == codec->dev)
3286 goto found;
3287 }
3288 return;
3289
3290found:
3291 if (codec->num_dai)
3292 for (i = 0; i < codec->num_dai; i++)
3293 snd_soc_unregister_dai(dev);
3294
2860 mutex_lock(&client_mutex); 3295 mutex_lock(&client_mutex);
2861 list_del(&codec->list); 3296 list_del(&codec->list);
2862 mutex_unlock(&client_mutex); 3297 mutex_unlock(&client_mutex);
2863 3298
2864 pr_debug("Unregistered codec '%s'\n", codec->name); 3299 pr_debug("Unregistered codec '%s'\n", codec->name);
3300
3301 if (codec->reg_cache)
3302 kfree(codec->reg_cache);
3303 kfree(codec->name);
3304 kfree(codec);
2865} 3305}
2866EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); 3306EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
2867 3307
@@ -2874,10 +3314,23 @@ static int __init snd_soc_init(void)
2874 "ASoC: Failed to create debugfs directory\n"); 3314 "ASoC: Failed to create debugfs directory\n");
2875 debugfs_root = NULL; 3315 debugfs_root = NULL;
2876 } 3316 }
3317
3318 if (!debugfs_create_file("codecs", 0444, debugfs_root, NULL,
3319 &codec_list_fops))
3320 pr_warn("ASoC: Failed to create CODEC list debugfs file\n");
3321
3322 if (!debugfs_create_file("dais", 0444, debugfs_root, NULL,
3323 &dai_list_fops))
3324 pr_warn("ASoC: Failed to create DAI list debugfs file\n");
3325
3326 if (!debugfs_create_file("platforms", 0444, debugfs_root, NULL,
3327 &platform_list_fops))
3328 pr_warn("ASoC: Failed to create platform list debugfs file\n");
2877#endif 3329#endif
2878 3330
2879 return platform_driver_register(&soc_driver); 3331 return platform_driver_register(&soc_driver);
2880} 3332}
3333module_init(snd_soc_init);
2881 3334
2882static void __exit snd_soc_exit(void) 3335static void __exit snd_soc_exit(void)
2883{ 3336{
@@ -2886,8 +3339,6 @@ static void __exit snd_soc_exit(void)
2886#endif 3339#endif
2887 platform_driver_unregister(&soc_driver); 3340 platform_driver_unregister(&soc_driver);
2888} 3341}
2889
2890module_init(snd_soc_init);
2891module_exit(snd_soc_exit); 3342module_exit(snd_soc_exit);
2892 3343
2893/* Module information */ 3344/* Module information */
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 72a53d0a41e9..7d85c6496afa 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -112,43 +112,41 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
112 112
113/** 113/**
114 * snd_soc_dapm_set_bias_level - set the bias level for the system 114 * snd_soc_dapm_set_bias_level - set the bias level for the system
115 * @socdev: audio device 115 * @card: audio device
116 * @level: level to configure 116 * @level: level to configure
117 * 117 *
118 * Configure the bias (power) levels for the SoC audio device. 118 * Configure the bias (power) levels for the SoC audio device.
119 * 119 *
120 * Returns 0 for success else error. 120 * Returns 0 for success else error.
121 */ 121 */
122static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, 122static int snd_soc_dapm_set_bias_level(struct snd_soc_card *card,
123 enum snd_soc_bias_level level) 123 struct snd_soc_codec *codec, enum snd_soc_bias_level level)
124{ 124{
125 struct snd_soc_card *card = socdev->card;
126 struct snd_soc_codec *codec = socdev->card->codec;
127 int ret = 0; 125 int ret = 0;
128 126
129 switch (level) { 127 switch (level) {
130 case SND_SOC_BIAS_ON: 128 case SND_SOC_BIAS_ON:
131 dev_dbg(socdev->dev, "Setting full bias\n"); 129 dev_dbg(codec->dev, "Setting full bias\n");
132 break; 130 break;
133 case SND_SOC_BIAS_PREPARE: 131 case SND_SOC_BIAS_PREPARE:
134 dev_dbg(socdev->dev, "Setting bias prepare\n"); 132 dev_dbg(codec->dev, "Setting bias prepare\n");
135 break; 133 break;
136 case SND_SOC_BIAS_STANDBY: 134 case SND_SOC_BIAS_STANDBY:
137 dev_dbg(socdev->dev, "Setting standby bias\n"); 135 dev_dbg(codec->dev, "Setting standby bias\n");
138 break; 136 break;
139 case SND_SOC_BIAS_OFF: 137 case SND_SOC_BIAS_OFF:
140 dev_dbg(socdev->dev, "Setting bias off\n"); 138 dev_dbg(codec->dev, "Setting bias off\n");
141 break; 139 break;
142 default: 140 default:
143 dev_err(socdev->dev, "Setting invalid bias %d\n", level); 141 dev_err(codec->dev, "Setting invalid bias %d\n", level);
144 return -EINVAL; 142 return -EINVAL;
145 } 143 }
146 144
147 if (card->set_bias_level) 145 if (card && card->set_bias_level)
148 ret = card->set_bias_level(card, level); 146 ret = card->set_bias_level(card, level);
149 if (ret == 0) { 147 if (ret == 0) {
150 if (codec->set_bias_level) 148 if (codec->driver->set_bias_level)
151 ret = codec->set_bias_level(codec, level); 149 ret = codec->driver->set_bias_level(codec, level);
152 else 150 else
153 codec->bias_level = level; 151 codec->bias_level = level;
154 } 152 }
@@ -370,7 +368,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
370 368
371 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, 369 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
372 path->long_name); 370 path->long_name);
373 ret = snd_ctl_add(codec->card, path->kcontrol); 371 ret = snd_ctl_add(codec->card->snd_card, path->kcontrol);
374 if (ret < 0) { 372 if (ret < 0) {
375 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n", 373 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s: %d\n",
376 path->long_name, 374 path->long_name,
@@ -398,7 +396,7 @@ static int dapm_new_mux(struct snd_soc_codec *codec,
398 } 396 }
399 397
400 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); 398 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
401 ret = snd_ctl_add(codec->card, kcontrol); 399 ret = snd_ctl_add(codec->card->snd_card, kcontrol);
402 if (ret < 0) 400 if (ret < 0)
403 goto err; 401 goto err;
404 402
@@ -437,9 +435,9 @@ static inline void dapm_clear_walk(struct snd_soc_codec *codec)
437 */ 435 */
438static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget) 436static int snd_soc_dapm_suspend_check(struct snd_soc_dapm_widget *widget)
439{ 437{
440 struct snd_soc_codec *codec = widget->codec; 438 int level = snd_power_get_state(widget->codec->card->snd_card);
441 439
442 switch (snd_power_get_state(codec->card)) { 440 switch (level) {
443 case SNDRV_CTL_POWER_D3hot: 441 case SNDRV_CTL_POWER_D3hot:
444 case SNDRV_CTL_POWER_D3cold: 442 case SNDRV_CTL_POWER_D3cold:
445 if (widget->ignore_suspend) 443 if (widget->ignore_suspend)
@@ -893,7 +891,7 @@ static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list,
893 */ 891 */
894static int dapm_power_widgets(struct snd_soc_codec *codec, int event) 892static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
895{ 893{
896 struct snd_soc_device *socdev = codec->socdev; 894 struct snd_soc_card *card = codec->card;
897 struct snd_soc_dapm_widget *w; 895 struct snd_soc_dapm_widget *w;
898 LIST_HEAD(up_list); 896 LIST_HEAD(up_list);
899 LIST_HEAD(down_list); 897 LIST_HEAD(down_list);
@@ -966,7 +964,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
966 } 964 }
967 965
968 if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) { 966 if (sys_power && codec->bias_level == SND_SOC_BIAS_OFF) {
969 ret = snd_soc_dapm_set_bias_level(socdev, 967 ret = snd_soc_dapm_set_bias_level(card, codec,
970 SND_SOC_BIAS_STANDBY); 968 SND_SOC_BIAS_STANDBY);
971 if (ret != 0) 969 if (ret != 0)
972 pr_err("Failed to turn on bias: %d\n", ret); 970 pr_err("Failed to turn on bias: %d\n", ret);
@@ -975,8 +973,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
975 /* If we're changing to all on or all off then prepare */ 973 /* If we're changing to all on or all off then prepare */
976 if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) || 974 if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) ||
977 (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { 975 (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) {
978 ret = snd_soc_dapm_set_bias_level(socdev, 976 ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_PREPARE);
979 SND_SOC_BIAS_PREPARE);
980 if (ret != 0) 977 if (ret != 0)
981 pr_err("Failed to prepare bias: %d\n", ret); 978 pr_err("Failed to prepare bias: %d\n", ret);
982 } 979 }
@@ -989,8 +986,7 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
989 986
990 /* If we just powered the last thing off drop to standby bias */ 987 /* If we just powered the last thing off drop to standby bias */
991 if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { 988 if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) {
992 ret = snd_soc_dapm_set_bias_level(socdev, 989 ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_STANDBY);
993 SND_SOC_BIAS_STANDBY);
994 if (ret != 0) 990 if (ret != 0)
995 pr_err("Failed to apply standby bias: %d\n", ret); 991 pr_err("Failed to apply standby bias: %d\n", ret);
996 } 992 }
@@ -998,15 +994,14 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
998 /* If we're in standby and can support bias off then do that */ 994 /* If we're in standby and can support bias off then do that */
999 if (codec->bias_level == SND_SOC_BIAS_STANDBY && 995 if (codec->bias_level == SND_SOC_BIAS_STANDBY &&
1000 codec->idle_bias_off) { 996 codec->idle_bias_off) {
1001 ret = snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); 997 ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF);
1002 if (ret != 0) 998 if (ret != 0)
1003 pr_err("Failed to turn off bias: %d\n", ret); 999 pr_err("Failed to turn off bias: %d\n", ret);
1004 } 1000 }
1005 1001
1006 /* If we just powered up then move to active bias */ 1002 /* If we just powered up then move to active bias */
1007 if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) { 1003 if (codec->bias_level == SND_SOC_BIAS_PREPARE && sys_power) {
1008 ret = snd_soc_dapm_set_bias_level(socdev, 1004 ret = snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_ON);
1009 SND_SOC_BIAS_ON);
1010 if (ret != 0) 1005 if (ret != 0)
1011 pr_err("Failed to apply active bias: %d\n", ret); 1006 pr_err("Failed to apply active bias: %d\n", ret);
1012 } 1007 }
@@ -1189,8 +1184,9 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1189static ssize_t dapm_widget_show(struct device *dev, 1184static ssize_t dapm_widget_show(struct device *dev,
1190 struct device_attribute *attr, char *buf) 1185 struct device_attribute *attr, char *buf)
1191{ 1186{
1192 struct snd_soc_device *devdata = dev_get_drvdata(dev); 1187 struct snd_soc_pcm_runtime *rtd =
1193 struct snd_soc_codec *codec = devdata->card->codec; 1188 container_of(dev, struct snd_soc_pcm_runtime, dev);
1189 struct snd_soc_codec *codec =rtd->codec;
1194 struct snd_soc_dapm_widget *w; 1190 struct snd_soc_dapm_widget *w;
1195 int count = 0; 1191 int count = 0;
1196 char *state = "not set"; 1192 char *state = "not set";
@@ -1999,9 +1995,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
1999 * 1995 *
2000 * Returns 0 for success else error. 1996 * Returns 0 for success else error.
2001 */ 1997 */
2002int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, 1998int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
2003 char *stream, int event) 1999 const char *stream, int event)
2004{ 2000{
2001 struct snd_soc_codec *codec = rtd->codec;
2005 struct snd_soc_dapm_widget *w; 2002 struct snd_soc_dapm_widget *w;
2006 2003
2007 if (stream == NULL) 2004 if (stream == NULL)
@@ -2169,25 +2166,19 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
2169 2166
2170/** 2167/**
2171 * snd_soc_dapm_free - free dapm resources 2168 * snd_soc_dapm_free - free dapm resources
2172 * @socdev: SoC device 2169 * @card: SoC device
2173 * 2170 *
2174 * Free all dapm widgets and resources. 2171 * Free all dapm widgets and resources.
2175 */ 2172 */
2176void snd_soc_dapm_free(struct snd_soc_device *socdev) 2173void snd_soc_dapm_free(struct snd_soc_codec *codec)
2177{ 2174{
2178 struct snd_soc_codec *codec = socdev->card->codec; 2175 snd_soc_dapm_sys_remove(codec->dev);
2179
2180 snd_soc_dapm_sys_remove(socdev->dev);
2181 dapm_free_widgets(codec); 2176 dapm_free_widgets(codec);
2182} 2177}
2183EXPORT_SYMBOL_GPL(snd_soc_dapm_free); 2178EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
2184 2179
2185/* 2180static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec)
2186 * snd_soc_dapm_shutdown - callback for system shutdown
2187 */
2188void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
2189{ 2181{
2190 struct snd_soc_codec *codec = socdev->card->codec;
2191 struct snd_soc_dapm_widget *w; 2182 struct snd_soc_dapm_widget *w;
2192 LIST_HEAD(down_list); 2183 LIST_HEAD(down_list);
2193 int powerdown = 0; 2184 int powerdown = 0;
@@ -2204,12 +2195,23 @@ void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
2204 * standby. 2195 * standby.
2205 */ 2196 */
2206 if (powerdown) { 2197 if (powerdown) {
2207 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE); 2198 snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_PREPARE);
2208 dapm_seq_run(codec, &down_list, 0, dapm_down_seq); 2199 dapm_seq_run(codec, &down_list, 0, dapm_down_seq);
2209 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY); 2200 snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_STANDBY);
2210 } 2201 }
2202}
2203
2204/*
2205 * snd_soc_dapm_shutdown - callback for system shutdown
2206 */
2207void snd_soc_dapm_shutdown(struct snd_soc_card *card)
2208{
2209 struct snd_soc_codec *codec;
2210
2211 list_for_each_entry(codec, &card->codec_dev_list, list)
2212 soc_dapm_shutdown_codec(codec);
2211 2213
2212 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); 2214 snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF);
2213} 2215}
2214 2216
2215/* Module information */ 2217/* Module information */
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 29159e1781d0..8a0a9205b1e7 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -32,14 +32,14 @@
32 * Returns zero if successful, or a negative error code on failure. 32 * Returns zero if successful, or a negative error code on failure.
33 * On success jack will be initialised. 33 * On success jack will be initialised.
34 */ 34 */
35int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type, 35int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
36 struct snd_soc_jack *jack) 36 struct snd_soc_jack *jack)
37{ 37{
38 jack->card = card; 38 jack->codec = codec;
39 INIT_LIST_HEAD(&jack->pins); 39 INIT_LIST_HEAD(&jack->pins);
40 BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); 40 BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier);
41 41
42 return snd_jack_new(card->codec->card, id, type, &jack->jack); 42 return snd_jack_new(codec->card->snd_card, id, type, &jack->jack);
43} 43}
44EXPORT_SYMBOL_GPL(snd_soc_jack_new); 44EXPORT_SYMBOL_GPL(snd_soc_jack_new);
45 45
@@ -67,7 +67,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
67 if (!jack) 67 if (!jack)
68 return; 68 return;
69 69
70 codec = jack->card->codec; 70 codec = jack->codec;
71 71
72 mutex_lock(&codec->mutex); 72 mutex_lock(&codec->mutex);
73 73
@@ -188,9 +188,6 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
188 int enable; 188 int enable;
189 int report; 189 int report;
190 190
191 if (gpio->debounce_time > 0)
192 mdelay(gpio->debounce_time);
193
194 enable = gpio_get_value(gpio->gpio); 191 enable = gpio_get_value(gpio->gpio);
195 if (gpio->invert) 192 if (gpio->invert)
196 enable = !enable; 193 enable = !enable;
@@ -211,7 +208,8 @@ static irqreturn_t gpio_handler(int irq, void *data)
211{ 208{
212 struct snd_soc_jack_gpio *gpio = data; 209 struct snd_soc_jack_gpio *gpio = data;
213 210
214 schedule_work(&gpio->work); 211 schedule_delayed_work(&gpio->work,
212 msecs_to_jiffies(gpio->debounce_time));
215 213
216 return IRQ_HANDLED; 214 return IRQ_HANDLED;
217} 215}
@@ -221,7 +219,7 @@ static void gpio_work(struct work_struct *work)
221{ 219{
222 struct snd_soc_jack_gpio *gpio; 220 struct snd_soc_jack_gpio *gpio;
223 221
224 gpio = container_of(work, struct snd_soc_jack_gpio, work); 222 gpio = container_of(work, struct snd_soc_jack_gpio, work.work);
225 snd_soc_jack_gpio_detect(gpio); 223 snd_soc_jack_gpio_detect(gpio);
226} 224}
227 225
@@ -262,13 +260,13 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
262 if (ret) 260 if (ret)
263 goto err; 261 goto err;
264 262
265 INIT_WORK(&gpios[i].work, gpio_work); 263 INIT_DELAYED_WORK(&gpios[i].work, gpio_work);
266 gpios[i].jack = jack; 264 gpios[i].jack = jack;
267 265
268 ret = request_irq(gpio_to_irq(gpios[i].gpio), 266 ret = request_irq(gpio_to_irq(gpios[i].gpio),
269 gpio_handler, 267 gpio_handler,
270 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 268 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
271 jack->card->dev->driver->name, 269 jack->codec->dev->driver->name,
272 &gpios[i]); 270 &gpios[i]);
273 if (ret) 271 if (ret)
274 goto err; 272 goto err;
@@ -312,6 +310,7 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
312 gpio_unexport(gpios[i].gpio); 310 gpio_unexport(gpios[i].gpio);
313#endif 311#endif
314 free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]); 312 free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]);
313 cancel_delayed_work_sync(&gpios[i].work);
315 gpio_free(gpios[i].gpio); 314 gpio_free(gpios[i].gpio);
316 gpios[i].jack = NULL; 315 gpios[i].jack = NULL;
317 } 316 }
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index 0ec20b68e8cb..743d07b82c06 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -36,13 +36,11 @@
36 36
37static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq); 37static DECLARE_WAIT_QUEUE_HEAD(ac97_waitq);
38 38
39/* REVISIT: How to find txx9aclc_soc_device from snd_ac97? */ 39/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
40static struct txx9aclc_soc_device *txx9aclc_soc_dev; 40static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
41 41
42static int txx9aclc_regready(struct txx9aclc_soc_device *dev) 42static int txx9aclc_regready(struct txx9aclc_plat_drvdata *drvdata)
43{ 43{
44 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
45
46 return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY; 44 return __raw_readl(drvdata->base + ACINTSTS) & ACINT_REGACCRDY;
47} 45}
48 46
@@ -50,8 +48,7 @@ static int txx9aclc_regready(struct txx9aclc_soc_device *dev)
50static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97, 48static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
51 unsigned short reg) 49 unsigned short reg)
52{ 50{
53 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; 51 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
54 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
55 void __iomem *base = drvdata->base; 52 void __iomem *base = drvdata->base;
56 u32 dat; 53 u32 dat;
57 54
@@ -61,15 +58,15 @@ static unsigned short txx9aclc_ac97_read(struct snd_ac97 *ac97,
61 dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ; 58 dat = (reg << ACREGACC_REG_SHIFT) | ACREGACC_READ;
62 __raw_writel(dat, base + ACREGACC); 59 __raw_writel(dat, base + ACREGACC);
63 __raw_writel(ACINT_REGACCRDY, base + ACINTEN); 60 __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
64 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { 61 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
65 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); 62 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
66 dev_err(dev->soc_dev.dev, "ac97 read timeout (reg %#x)\n", reg); 63 printk(KERN_ERR "ac97 read timeout (reg %#x)\n", reg);
67 dat = 0xffff; 64 dat = 0xffff;
68 goto done; 65 goto done;
69 } 66 }
70 dat = __raw_readl(base + ACREGACC); 67 dat = __raw_readl(base + ACREGACC);
71 if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) { 68 if (((dat >> ACREGACC_REG_SHIFT) & 0xff) != reg) {
72 dev_err(dev->soc_dev.dev, "reg mismatch %x with %x\n", 69 printk(KERN_ERR "reg mismatch %x with %x\n",
73 dat, reg); 70 dat, reg);
74 dat = 0xffff; 71 dat = 0xffff;
75 goto done; 72 goto done;
@@ -84,16 +81,15 @@ done:
84static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, 81static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
85 unsigned short val) 82 unsigned short val)
86{ 83{
87 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; 84 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
88 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
89 void __iomem *base = drvdata->base; 85 void __iomem *base = drvdata->base;
90 86
91 __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) | 87 __raw_writel(((reg | (ac97->num << 7)) << ACREGACC_REG_SHIFT) |
92 (val << ACREGACC_DAT_SHIFT), 88 (val << ACREGACC_DAT_SHIFT),
93 base + ACREGACC); 89 base + ACREGACC);
94 __raw_writel(ACINT_REGACCRDY, base + ACINTEN); 90 __raw_writel(ACINT_REGACCRDY, base + ACINTEN);
95 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(dev), HZ)) { 91 if (!wait_event_timeout(ac97_waitq, txx9aclc_regready(txx9aclc_drvdata), HZ)) {
96 dev_err(dev->soc_dev.dev, 92 printk(KERN_ERR
97 "ac97 write timeout (reg %#x)\n", reg); 93 "ac97 write timeout (reg %#x)\n", reg);
98 } 94 }
99 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS); 95 __raw_writel(ACINT_REGACCRDY, base + ACINTDIS);
@@ -101,8 +97,7 @@ static void txx9aclc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
101 97
102static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) 98static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97)
103{ 99{
104 struct txx9aclc_soc_device *dev = txx9aclc_soc_dev; 100 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
105 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
106 void __iomem *base = drvdata->base; 101 void __iomem *base = drvdata->base;
107 u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY; 102 u32 ready = ACINT_CODECRDY(ac97->num) | ACINT_REGACCRDY;
108 103
@@ -141,31 +136,23 @@ static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id)
141 return IRQ_HANDLED; 136 return IRQ_HANDLED;
142} 137}
143 138
144static int txx9aclc_ac97_probe(struct platform_device *pdev, 139static int txx9aclc_ac97_probe(struct snd_soc_dai *dai)
145 struct snd_soc_dai *dai)
146{ 140{
147 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 141 txx9aclc_drvdata = snd_soc_dai_get_drvdata(dai);
148 struct txx9aclc_soc_device *dev =
149 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
150
151 dev->aclc_pdev = to_platform_device(dai->dev);
152 txx9aclc_soc_dev = dev;
153 return 0; 142 return 0;
154} 143}
155 144
156static void txx9aclc_ac97_remove(struct platform_device *pdev, 145static int txx9aclc_ac97_remove(struct snd_soc_dai *dai)
157 struct snd_soc_dai *dai)
158{ 146{
159 struct platform_device *aclc_pdev = to_platform_device(dai->dev); 147 struct txx9aclc_plat_drvdata *drvdata = snd_soc_dai_get_drvdata(dai);
160 struct txx9aclc_plat_drvdata *drvdata = platform_get_drvdata(aclc_pdev);
161 148
162 /* disable AC-link */ 149 /* disable AC-link */
163 __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS); 150 __raw_writel(ACCTL_ENLINK, drvdata->base + ACCTLDIS);
164 txx9aclc_soc_dev = NULL; 151 txx9aclc_drvdata = NULL;
152 return 0;
165} 153}
166 154
167struct snd_soc_dai txx9aclc_ac97_dai = { 155static struct snd_soc_dai_driver txx9aclc_ac97_dai = {
168 .name = "txx9aclc_ac97",
169 .ac97_control = 1, 156 .ac97_control = 1,
170 .probe = txx9aclc_ac97_probe, 157 .probe = txx9aclc_ac97_probe,
171 .remove = txx9aclc_ac97_remove, 158 .remove = txx9aclc_ac97_remove,
@@ -182,7 +169,6 @@ struct snd_soc_dai txx9aclc_ac97_dai = {
182 .channels_max = 2, 169 .channels_max = 2,
183 }, 170 },
184}; 171};
185EXPORT_SYMBOL_GPL(txx9aclc_ac97_dai);
186 172
187static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev) 173static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
188{ 174{
@@ -219,13 +205,12 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
219 if (err < 0) 205 if (err < 0)
220 return err; 206 return err;
221 207
222 txx9aclc_ac97_dai.dev = &pdev->dev; 208 return snd_soc_register_dai(&pdev->dev, &txx9aclc_ac97_dai);
223 return snd_soc_register_dai(&txx9aclc_ac97_dai);
224} 209}
225 210
226static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev) 211static int __devexit txx9aclc_ac97_dev_remove(struct platform_device *pdev)
227{ 212{
228 snd_soc_unregister_dai(&txx9aclc_ac97_dai); 213 snd_soc_unregister_dai(&pdev->dev);
229 return 0; 214 return 0;
230} 215}
231 216
diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c
index 95b17f731aec..6770e7166be4 100644
--- a/sound/soc/txx9/txx9aclc-generic.c
+++ b/sound/soc/txx9/txx9aclc-generic.c
@@ -19,54 +19,44 @@
19#include <sound/core.h> 19#include <sound/core.h>
20#include <sound/pcm.h> 20#include <sound/pcm.h>
21#include <sound/soc.h> 21#include <sound/soc.h>
22#include "../codecs/ac97.h"
23#include "txx9aclc.h" 22#include "txx9aclc.h"
24 23
25static struct snd_soc_dai_link txx9aclc_generic_dai = { 24static struct snd_soc_dai_link txx9aclc_generic_dai = {
26 .name = "AC97", 25 .name = "AC97",
27 .stream_name = "AC97 HiFi", 26 .stream_name = "AC97 HiFi",
28 .cpu_dai = &txx9aclc_ac97_dai, 27 .cpu_dai_name = "txx9aclc-ac97",
29 .codec_dai = &ac97_dai, 28 .codec_dai_name = "ac97-hifi",
29 .platform_name = "txx9aclc-pcm-audio",
30 .codec_name = "ac97-codec",
30}; 31};
31 32
32static struct snd_soc_card txx9aclc_generic_card = { 33static struct snd_soc_card txx9aclc_generic_card = {
33 .name = "Generic TXx9 ACLC Audio", 34 .name = "Generic TXx9 ACLC Audio",
34 .platform = &txx9aclc_soc_platform,
35 .dai_link = &txx9aclc_generic_dai, 35 .dai_link = &txx9aclc_generic_dai,
36 .num_links = 1, 36 .num_links = 1,
37}; 37};
38 38
39static struct txx9aclc_soc_device txx9aclc_generic_soc_device = { 39static struct platform_device *soc_pdev;
40 .soc_dev = {
41 .card = &txx9aclc_generic_card,
42 .codec_dev = &soc_codec_dev_ac97,
43 },
44};
45 40
46static int __init txx9aclc_generic_probe(struct platform_device *pdev) 41static int __init txx9aclc_generic_probe(struct platform_device *pdev)
47{ 42{
48 struct txx9aclc_soc_device *dev = &txx9aclc_generic_soc_device;
49 struct platform_device *soc_pdev;
50 int ret; 43 int ret;
51 44
52 soc_pdev = platform_device_alloc("soc-audio", -1); 45 soc_pdev = platform_device_alloc("soc-audio", -1);
53 if (!soc_pdev) 46 if (!soc_pdev)
54 return -ENOMEM; 47 return -ENOMEM;
55 platform_set_drvdata(soc_pdev, &dev->soc_dev); 48 platform_set_drvdata(soc_pdev, &txx9aclc_generic_card);
56 dev->soc_dev.dev = &soc_pdev->dev;
57 ret = platform_device_add(soc_pdev); 49 ret = platform_device_add(soc_pdev);
58 if (ret) { 50 if (ret) {
59 platform_device_put(soc_pdev); 51 platform_device_put(soc_pdev);
60 return ret; 52 return ret;
61 } 53 }
62 platform_set_drvdata(pdev, soc_pdev); 54
63 return 0; 55 return 0;
64} 56}
65 57
66static int __exit txx9aclc_generic_remove(struct platform_device *pdev) 58static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
67{ 59{
68 struct platform_device *soc_pdev = platform_get_drvdata(pdev);
69
70 platform_device_unregister(soc_pdev); 60 platform_device_unregister(soc_pdev);
71 return 0; 61 return 0;
72} 62}
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index 0e3452303ea6..f4aa4e03c888 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -22,6 +22,16 @@
22#include <sound/soc.h> 22#include <sound/soc.h>
23#include "txx9aclc.h" 23#include "txx9aclc.h"
24 24
25static struct txx9aclc_soc_device {
26 struct txx9aclc_dmadata dmadata[2];
27} txx9aclc_soc_device;
28
29/* REVISIT: How to find txx9aclc_drvdata from snd_ac97? */
30static struct txx9aclc_plat_drvdata *txx9aclc_drvdata;
31
32static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
33 struct txx9aclc_dmadata *dmadata);
34
25static const struct snd_pcm_hardware txx9aclc_pcm_hardware = { 35static const struct snd_pcm_hardware txx9aclc_pcm_hardware = {
26 /* 36 /*
27 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID 37 * REVISIT: SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID
@@ -46,7 +56,6 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,
46 struct snd_pcm_hw_params *params) 56 struct snd_pcm_hw_params *params)
47{ 57{
48 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); 58 struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
49 struct snd_soc_device *socdev = rtd->socdev;
50 struct snd_pcm_runtime *runtime = substream->runtime; 59 struct snd_pcm_runtime *runtime = substream->runtime;
51 struct txx9aclc_dmadata *dmadata = runtime->private_data; 60 struct txx9aclc_dmadata *dmadata = runtime->private_data;
52 int ret; 61 int ret;
@@ -55,13 +64,13 @@ static int txx9aclc_pcm_hw_params(struct snd_pcm_substream *substream,
55 if (ret < 0) 64 if (ret < 0)
56 return ret; 65 return ret;
57 66
58 dev_dbg(socdev->dev, 67 dev_dbg(rtd->platform->dev,
59 "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd " 68 "runtime->dma_area = %#lx dma_addr = %#lx dma_bytes = %zd "
60 "runtime->min_align %ld\n", 69 "runtime->min_align %ld\n",
61 (unsigned long)runtime->dma_area, 70 (unsigned long)runtime->dma_area,
62 (unsigned long)runtime->dma_addr, runtime->dma_bytes, 71 (unsigned long)runtime->dma_addr, runtime->dma_bytes,
63 runtime->min_align); 72 runtime->min_align);
64 dev_dbg(socdev->dev, 73 dev_dbg(rtd->platform->dev,
65 "periods %d period_bytes %d stream %d\n", 74 "periods %d period_bytes %d stream %d\n",
66 params_periods(params), params_period_bytes(params), 75 params_periods(params), params_period_bytes(params),
67 substream->stream); 76 substream->stream);
@@ -152,11 +161,7 @@ static void txx9aclc_dma_tasklet(unsigned long data)
152 161
153 spin_lock_irqsave(&dmadata->dma_lock, flags); 162 spin_lock_irqsave(&dmadata->dma_lock, flags);
154 if (dmadata->frag_count < 0) { 163 if (dmadata->frag_count < 0) {
155 struct txx9aclc_soc_device *dev = 164 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
156 container_of(dmadata, struct txx9aclc_soc_device,
157 dmadata[substream->stream]);
158 struct txx9aclc_plat_drvdata *drvdata =
159 txx9aclc_get_plat_drvdata(dev);
160 void __iomem *base = drvdata->base; 165 void __iomem *base = drvdata->base;
161 166
162 spin_unlock_irqrestore(&dmadata->dma_lock, flags); 167 spin_unlock_irqrestore(&dmadata->dma_lock, flags);
@@ -202,10 +207,7 @@ static void txx9aclc_dma_tasklet(unsigned long data)
202static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 207static int txx9aclc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
203{ 208{
204 struct txx9aclc_dmadata *dmadata = substream->runtime->private_data; 209 struct txx9aclc_dmadata *dmadata = substream->runtime->private_data;
205 struct snd_soc_pcm_runtime *rtd = substream->private_data; 210 struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata;
206 struct txx9aclc_soc_device *dev =
207 container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev);
208 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
209 void __iomem *base = drvdata->base; 211 void __iomem *base = drvdata->base;
210 unsigned long flags; 212 unsigned long flags;
211 int ret = 0; 213 int ret = 0;
@@ -244,9 +246,7 @@ txx9aclc_pcm_pointer(struct snd_pcm_substream *substream)
244 246
245static int txx9aclc_pcm_open(struct snd_pcm_substream *substream) 247static int txx9aclc_pcm_open(struct snd_pcm_substream *substream)
246{ 248{
247 struct snd_soc_pcm_runtime *rtd = substream->private_data; 249 struct txx9aclc_soc_device *dev = &txx9aclc_soc_device;
248 struct txx9aclc_soc_device *dev =
249 container_of(rtd->socdev, struct txx9aclc_soc_device, soc_dev);
250 struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream]; 250 struct txx9aclc_dmadata *dmadata = &dev->dmadata[substream->stream];
251 int ret; 251 int ret;
252 252
@@ -291,8 +291,38 @@ static void txx9aclc_pcm_free_dma_buffers(struct snd_pcm *pcm)
291static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, 291static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
292 struct snd_pcm *pcm) 292 struct snd_pcm *pcm)
293{ 293{
294 struct platform_device *pdev = to_platform_device(dai->platform->dev);
295 struct txx9aclc_soc_device *dev;
296 struct resource *r;
297 int i;
298 int ret;
299
300 /* at this point onwards the AC97 component has probed and this will be valid */
301 dev = snd_soc_dai_get_drvdata(dai);
302
303 dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
304 dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
305 for (i = 0; i < 2; i++) {
306 r = platform_get_resource(pdev, IORESOURCE_DMA, i);
307 if (!r) {
308 ret = -EBUSY;
309 goto exit;
310 }
311 dev->dmadata[i].dma_res = r;
312 ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
313 if (ret)
314 goto exit;
315 }
294 return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 316 return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
295 card->dev, 64 * 1024, 4 * 1024 * 1024); 317 card->dev, 64 * 1024, 4 * 1024 * 1024);
318
319exit:
320 for (i = 0; i < 2; i++) {
321 if (dev->dmadata[i].dma_chan)
322 dma_release_channel(dev->dmadata[i].dma_chan);
323 dev->dmadata[i].dma_chan = NULL;
324 }
325 return ret;
296} 326}
297 327
298static bool filter(struct dma_chan *chan, void *param) 328static bool filter(struct dma_chan *chan, void *param)
@@ -314,7 +344,7 @@ static bool filter(struct dma_chan *chan, void *param)
314static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev, 344static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
315 struct txx9aclc_dmadata *dmadata) 345 struct txx9aclc_dmadata *dmadata)
316{ 346{
317 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev); 347 struct txx9aclc_plat_drvdata *drvdata =txx9aclc_drvdata;
318 struct txx9dmac_slave *ds = &dmadata->dma_slave; 348 struct txx9dmac_slave *ds = &dmadata->dma_slave;
319 dma_cap_mask_t mask; 349 dma_cap_mask_t mask;
320 350
@@ -334,7 +364,7 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
334 dma_cap_set(DMA_SLAVE, mask); 364 dma_cap_set(DMA_SLAVE, mask);
335 dmadata->dma_chan = dma_request_channel(mask, filter, dmadata); 365 dmadata->dma_chan = dma_request_channel(mask, filter, dmadata);
336 if (!dmadata->dma_chan) { 366 if (!dmadata->dma_chan) {
337 dev_err(dev->soc_dev.dev, 367 printk(KERN_ERR
338 "DMA channel for %s is not available\n", 368 "DMA channel for %s is not available\n",
339 dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ? 369 dmadata->stream == SNDRV_PCM_STREAM_PLAYBACK ?
340 "playback" : "capture"); 370 "playback" : "capture");
@@ -345,45 +375,16 @@ static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,
345 return 0; 375 return 0;
346} 376}
347 377
348static int txx9aclc_pcm_probe(struct platform_device *pdev) 378static int txx9aclc_pcm_probe(struct snd_soc_platform *platform)
349{ 379{
350 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 380 snd_soc_platform_set_drvdata(platform, &txx9aclc_soc_device);
351 struct txx9aclc_soc_device *dev =
352 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
353 struct resource *r;
354 int i;
355 int ret;
356
357 dev->dmadata[0].stream = SNDRV_PCM_STREAM_PLAYBACK;
358 dev->dmadata[1].stream = SNDRV_PCM_STREAM_CAPTURE;
359 for (i = 0; i < 2; i++) {
360 r = platform_get_resource(dev->aclc_pdev, IORESOURCE_DMA, i);
361 if (!r) {
362 ret = -EBUSY;
363 goto exit;
364 }
365 dev->dmadata[i].dma_res = r;
366 ret = txx9aclc_dma_init(dev, &dev->dmadata[i]);
367 if (ret)
368 goto exit;
369 }
370 return 0; 381 return 0;
371
372exit:
373 for (i = 0; i < 2; i++) {
374 if (dev->dmadata[i].dma_chan)
375 dma_release_channel(dev->dmadata[i].dma_chan);
376 dev->dmadata[i].dma_chan = NULL;
377 }
378 return ret;
379} 382}
380 383
381static int txx9aclc_pcm_remove(struct platform_device *pdev) 384static int txx9aclc_pcm_remove(struct snd_soc_platform *platform)
382{ 385{
383 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 386 struct txx9aclc_soc_device *dev = snd_soc_platform_get_drvdata(platform);
384 struct txx9aclc_soc_device *dev = 387 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_drvdata;
385 container_of(socdev, struct txx9aclc_soc_device, soc_dev);
386 struct txx9aclc_plat_drvdata *drvdata = txx9aclc_get_plat_drvdata(dev);
387 void __iomem *base = drvdata->base; 388 void __iomem *base = drvdata->base;
388 int i; 389 int i;
389 390
@@ -406,28 +407,46 @@ static int txx9aclc_pcm_remove(struct platform_device *pdev)
406 return 0; 407 return 0;
407} 408}
408 409
409struct snd_soc_platform txx9aclc_soc_platform = { 410static struct snd_soc_platform_driver txx9aclc_soc_platform = {
410 .name = "txx9aclc-audio",
411 .probe = txx9aclc_pcm_probe, 411 .probe = txx9aclc_pcm_probe,
412 .remove = txx9aclc_pcm_remove, 412 .remove = txx9aclc_pcm_remove,
413 .pcm_ops = &txx9aclc_pcm_ops, 413 .ops = &txx9aclc_pcm_ops,
414 .pcm_new = txx9aclc_pcm_new, 414 .pcm_new = txx9aclc_pcm_new,
415 .pcm_free = txx9aclc_pcm_free_dma_buffers, 415 .pcm_free = txx9aclc_pcm_free_dma_buffers,
416}; 416};
417EXPORT_SYMBOL_GPL(txx9aclc_soc_platform);
418 417
419static int __init txx9aclc_soc_platform_init(void) 418static int __devinit txx9aclc_soc_platform_probe(struct platform_device *pdev)
420{ 419{
421 return snd_soc_register_platform(&txx9aclc_soc_platform); 420 return snd_soc_register_platform(&pdev->dev, &txx9aclc_soc_platform);
422} 421}
423 422
424static void __exit txx9aclc_soc_platform_exit(void) 423static int __devexit txx9aclc_soc_platform_remove(struct platform_device *pdev)
425{ 424{
426 snd_soc_unregister_platform(&txx9aclc_soc_platform); 425 snd_soc_unregister_platform(&pdev->dev);
426 return 0;
427} 427}
428 428
429module_init(txx9aclc_soc_platform_init); 429static struct platform_driver txx9aclc_pcm_driver = {
430module_exit(txx9aclc_soc_platform_exit); 430 .driver = {
431 .name = "txx9aclc-pcm-audio",
432 .owner = THIS_MODULE,
433 },
434
435 .probe = txx9aclc_soc_platform_probe,
436 .remove = __devexit_p(txx9aclc_soc_platform_remove),
437};
438
439static int __init snd_txx9aclc_pcm_init(void)
440{
441 return platform_driver_register(&txx9aclc_pcm_driver);
442}
443module_init(snd_txx9aclc_pcm_init);
444
445static void __exit snd_txx9aclc_pcm_exit(void)
446{
447 platform_driver_unregister(&txx9aclc_pcm_driver);
448}
449module_exit(snd_txx9aclc_pcm_exit);
431 450
432MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>"); 451MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
433MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver"); 452MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
diff --git a/sound/soc/txx9/txx9aclc.h b/sound/soc/txx9/txx9aclc.h
index 6769aab41b33..9c2de84fec3b 100644
--- a/sound/soc/txx9/txx9aclc.h
+++ b/sound/soc/txx9/txx9aclc.h
@@ -65,19 +65,10 @@ struct txx9aclc_plat_drvdata {
65 u64 physbase; 65 u64 physbase;
66}; 66};
67 67
68struct txx9aclc_soc_device {
69 struct snd_soc_device soc_dev;
70 struct platform_device *aclc_pdev; /* for ioresources, drvdata */
71 struct txx9aclc_dmadata dmadata[2];
72};
73
74static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata( 68static inline struct txx9aclc_plat_drvdata *txx9aclc_get_plat_drvdata(
75 struct txx9aclc_soc_device *sdev) 69 struct snd_soc_dai *dai)
76{ 70{
77 return platform_get_drvdata(sdev->aclc_pdev); 71 return dev_get_drvdata(dai->dev);
78} 72}
79 73
80extern struct snd_soc_platform txx9aclc_soc_platform;
81extern struct snd_soc_dai txx9aclc_ac97_dai;
82
83#endif /* __TXX9ACLC_H */ 74#endif /* __TXX9ACLC_H */
diff --git a/sound/synth/emux/emux_hwdep.c b/sound/synth/emux/emux_hwdep.c
index ff0b2a8fd25b..5ae1eae9f6db 100644
--- a/sound/synth/emux/emux_hwdep.c
+++ b/sound/synth/emux/emux_hwdep.c
@@ -128,6 +128,9 @@ snd_emux_init_hwdep(struct snd_emux *emu)
128 strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME); 128 strcpy(hw->name, SNDRV_EMUX_HWDEP_NAME);
129 hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE; 129 hw->iface = SNDRV_HWDEP_IFACE_EMUX_WAVETABLE;
130 hw->ops.ioctl = snd_emux_hwdep_ioctl; 130 hw->ops.ioctl = snd_emux_hwdep_ioctl;
131 /* The ioctl parameter types are compatible between 32- and
132 * 64-bit architectures, so use the same function. */
133 hw->ops.ioctl_compat = snd_emux_hwdep_ioctl;
131 hw->exclusive = 1; 134 hw->exclusive = 1;
132 hw->private_data = emu; 135 hw->private_data = emu;
133 if ((err = snd_card_register(emu->card)) < 0) 136 if ((err = snd_card_register(emu->card)) < 0)
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 44d6d2ec964f..112984f4080f 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -65,6 +65,7 @@ config SND_USB_CAIAQ
65 * Native Instruments Guitar Rig Session I/O 65 * Native Instruments Guitar Rig Session I/O
66 * Native Instruments Guitar Rig mobile 66 * Native Instruments Guitar Rig mobile
67 * Native Instruments Traktor Kontrol X1 67 * Native Instruments Traktor Kontrol X1
68 * Native Instruments Traktor Kontrol S4
68 69
69 To compile this driver as a module, choose M here: the module 70 To compile this driver as a module, choose M here: the module
70 will be called snd-usb-caiaq. 71 will be called snd-usb-caiaq.
@@ -82,6 +83,7 @@ config SND_USB_CAIAQ_INPUT
82 * Native Instruments Kore Controller 83 * Native Instruments Kore Controller
83 * Native Instruments Kore Controller 2 84 * Native Instruments Kore Controller 2
84 * Native Instruments Audio Kontrol 1 85 * Native Instruments Audio Kontrol 1
86 * Native Instruments Traktor Kontrol S4
85 87
86config SND_USB_US122L 88config SND_USB_US122L
87 tristate "Tascam US-122L USB driver" 89 tristate "Tascam US-122L USB driver"
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 4328cad6c3a2..68b97477577b 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -111,7 +111,7 @@ static int stream_start(struct snd_usb_caiaqdev *dev)
111 memset(dev->sub_capture, 0, sizeof(dev->sub_capture)); 111 memset(dev->sub_capture, 0, sizeof(dev->sub_capture));
112 dev->input_panic = 0; 112 dev->input_panic = 0;
113 dev->output_panic = 0; 113 dev->output_panic = 0;
114 dev->first_packet = 1; 114 dev->first_packet = 4;
115 dev->streaming = 1; 115 dev->streaming = 1;
116 dev->warned = 0; 116 dev->warned = 0;
117 117
@@ -169,7 +169,7 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
169} 169}
170 170
171static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub, 171static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
172 struct snd_pcm_hw_params *hw_params) 172 struct snd_pcm_hw_params *hw_params)
173{ 173{
174 debug("%s(%p)\n", __func__, sub); 174 debug("%s(%p)\n", __func__, sub);
175 return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params)); 175 return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
@@ -189,7 +189,7 @@ static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
189#endif 189#endif
190 190
191static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100, 191static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
192 48000, 64000, 88200, 96000, 176400, 192000 }; 192 48000, 64000, 88200, 96000, 176400, 192000 };
193 193
194static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream) 194static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
195{ 195{
@@ -201,12 +201,39 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
201 debug("%s(%p)\n", __func__, substream); 201 debug("%s(%p)\n", __func__, substream);
202 202
203 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 203 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
204 dev->period_out_count[index] = BYTES_PER_SAMPLE + 1; 204 int out_pos;
205 dev->audio_out_buf_pos[index] = BYTES_PER_SAMPLE + 1; 205
206 switch (dev->spec.data_alignment) {
207 case 0:
208 case 2:
209 out_pos = BYTES_PER_SAMPLE + 1;
210 break;
211 case 3:
212 default:
213 out_pos = 0;
214 break;
215 }
216
217 dev->period_out_count[index] = out_pos;
218 dev->audio_out_buf_pos[index] = out_pos;
206 } else { 219 } else {
207 int in_pos = (dev->spec.data_alignment == 2) ? 0 : 2; 220 int in_pos;
208 dev->period_in_count[index] = BYTES_PER_SAMPLE + in_pos; 221
209 dev->audio_in_buf_pos[index] = BYTES_PER_SAMPLE + in_pos; 222 switch (dev->spec.data_alignment) {
223 case 0:
224 in_pos = BYTES_PER_SAMPLE + 2;
225 break;
226 case 2:
227 in_pos = BYTES_PER_SAMPLE;
228 break;
229 case 3:
230 default:
231 in_pos = 0;
232 break;
233 }
234
235 dev->period_in_count[index] = in_pos;
236 dev->audio_in_buf_pos[index] = in_pos;
210 } 237 }
211 238
212 if (dev->streaming) 239 if (dev->streaming)
@@ -221,7 +248,7 @@ static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
221 snd_pcm_limit_hw_rates(runtime); 248 snd_pcm_limit_hw_rates(runtime);
222 249
223 bytes_per_sample = BYTES_PER_SAMPLE; 250 bytes_per_sample = BYTES_PER_SAMPLE;
224 if (dev->spec.data_alignment == 2) 251 if (dev->spec.data_alignment >= 2)
225 bytes_per_sample++; 252 bytes_per_sample++;
226 253
227 bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE) 254 bpp = ((runtime->rate / 8000) + CLOCK_DRIFT_TOLERANCE)
@@ -253,6 +280,8 @@ static int snd_usb_caiaq_pcm_trigger(struct snd_pcm_substream *sub, int cmd)
253{ 280{
254 struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub); 281 struct snd_usb_caiaqdev *dev = snd_pcm_substream_chip(sub);
255 282
283 debug("%s(%p) cmd %d\n", __func__, sub, cmd);
284
256 switch (cmd) { 285 switch (cmd) {
257 case SNDRV_PCM_TRIGGER_START: 286 case SNDRV_PCM_TRIGGER_START:
258 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 287 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
@@ -402,6 +431,61 @@ static void read_in_urb_mode2(struct snd_usb_caiaqdev *dev,
402 } 431 }
403} 432}
404 433
434static void read_in_urb_mode3(struct snd_usb_caiaqdev *dev,
435 const struct urb *urb,
436 const struct usb_iso_packet_descriptor *iso)
437{
438 unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
439 int stream, i;
440
441 /* paranoia check */
442 if (iso->actual_length % (BYTES_PER_SAMPLE_USB * CHANNELS_PER_STREAM))
443 return;
444
445 for (i = 0; i < iso->actual_length;) {
446 for (stream = 0; stream < dev->n_streams; stream++) {
447 struct snd_pcm_substream *sub = dev->sub_capture[stream];
448 char *audio_buf = NULL;
449 int c, n, sz = 0;
450
451 if (sub && !dev->input_panic) {
452 struct snd_pcm_runtime *rt = sub->runtime;
453 audio_buf = rt->dma_area;
454 sz = frames_to_bytes(rt, rt->buffer_size);
455 }
456
457 for (c = 0; c < CHANNELS_PER_STREAM; c++) {
458 /* 3 audio data bytes, followed by 1 check byte */
459 if (audio_buf) {
460 for (n = 0; n < BYTES_PER_SAMPLE; n++) {
461 audio_buf[dev->audio_in_buf_pos[stream]++] = usb_buf[i+n];
462
463 if (dev->audio_in_buf_pos[stream] == sz)
464 dev->audio_in_buf_pos[stream] = 0;
465 }
466
467 dev->period_in_count[stream] += BYTES_PER_SAMPLE;
468 }
469
470 i += BYTES_PER_SAMPLE;
471
472 if (usb_buf[i] != ((stream << 1) | c) &&
473 !dev->first_packet) {
474 if (!dev->input_panic)
475 printk(" EXPECTED: %02x got %02x, c %d, stream %d, i %d\n",
476 ((stream << 1) | c), usb_buf[i], c, stream, i);
477 dev->input_panic = 1;
478 }
479
480 i++;
481 }
482 }
483 }
484
485 if (dev->first_packet > 0)
486 dev->first_packet--;
487}
488
405static void read_in_urb(struct snd_usb_caiaqdev *dev, 489static void read_in_urb(struct snd_usb_caiaqdev *dev,
406 const struct urb *urb, 490 const struct urb *urb,
407 const struct usb_iso_packet_descriptor *iso) 491 const struct usb_iso_packet_descriptor *iso)
@@ -419,6 +503,9 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
419 case 2: 503 case 2:
420 read_in_urb_mode2(dev, urb, iso); 504 read_in_urb_mode2(dev, urb, iso);
421 break; 505 break;
506 case 3:
507 read_in_urb_mode3(dev, urb, iso);
508 break;
422 } 509 }
423 510
424 if ((dev->input_panic || dev->output_panic) && !dev->warned) { 511 if ((dev->input_panic || dev->output_panic) && !dev->warned) {
@@ -429,9 +516,9 @@ static void read_in_urb(struct snd_usb_caiaqdev *dev,
429 } 516 }
430} 517}
431 518
432static void fill_out_urb(struct snd_usb_caiaqdev *dev, 519static void fill_out_urb_mode_0(struct snd_usb_caiaqdev *dev,
433 struct urb *urb, 520 struct urb *urb,
434 const struct usb_iso_packet_descriptor *iso) 521 const struct usb_iso_packet_descriptor *iso)
435{ 522{
436 unsigned char *usb_buf = urb->transfer_buffer + iso->offset; 523 unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
437 struct snd_pcm_substream *sub; 524 struct snd_pcm_substream *sub;
@@ -457,9 +544,67 @@ static void fill_out_urb(struct snd_usb_caiaqdev *dev,
457 /* fill in the check bytes */ 544 /* fill in the check bytes */
458 if (dev->spec.data_alignment == 2 && 545 if (dev->spec.data_alignment == 2 &&
459 i % (dev->n_streams * BYTES_PER_SAMPLE_USB) == 546 i % (dev->n_streams * BYTES_PER_SAMPLE_USB) ==
460 (dev->n_streams * CHANNELS_PER_STREAM)) 547 (dev->n_streams * CHANNELS_PER_STREAM))
461 for (stream = 0; stream < dev->n_streams; stream++, i++) 548 for (stream = 0; stream < dev->n_streams; stream++, i++)
462 usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i); 549 usb_buf[i] = MAKE_CHECKBYTE(dev, stream, i);
550 }
551}
552
553static void fill_out_urb_mode_3(struct snd_usb_caiaqdev *dev,
554 struct urb *urb,
555 const struct usb_iso_packet_descriptor *iso)
556{
557 unsigned char *usb_buf = urb->transfer_buffer + iso->offset;
558 int stream, i;
559
560 for (i = 0; i < iso->length;) {
561 for (stream = 0; stream < dev->n_streams; stream++) {
562 struct snd_pcm_substream *sub = dev->sub_playback[stream];
563 char *audio_buf = NULL;
564 int c, n, sz = 0;
565
566 if (sub) {
567 struct snd_pcm_runtime *rt = sub->runtime;
568 audio_buf = rt->dma_area;
569 sz = frames_to_bytes(rt, rt->buffer_size);
570 }
571
572 for (c = 0; c < CHANNELS_PER_STREAM; c++) {
573 for (n = 0; n < BYTES_PER_SAMPLE; n++) {
574 if (audio_buf) {
575 usb_buf[i+n] = audio_buf[dev->audio_out_buf_pos[stream]++];
576
577 if (dev->audio_out_buf_pos[stream] == sz)
578 dev->audio_out_buf_pos[stream] = 0;
579 } else {
580 usb_buf[i+n] = 0;
581 }
582 }
583
584 if (audio_buf)
585 dev->period_out_count[stream] += BYTES_PER_SAMPLE;
586
587 i += BYTES_PER_SAMPLE;
588
589 /* fill in the check byte pattern */
590 usb_buf[i++] = (stream << 1) | c;
591 }
592 }
593 }
594}
595
596static inline void fill_out_urb(struct snd_usb_caiaqdev *dev,
597 struct urb *urb,
598 const struct usb_iso_packet_descriptor *iso)
599{
600 switch (dev->spec.data_alignment) {
601 case 0:
602 case 2:
603 fill_out_urb_mode_0(dev, urb, iso);
604 break;
605 case 3:
606 fill_out_urb_mode_3(dev, urb, iso);
607 break;
463 } 608 }
464} 609}
465 610
diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c
index 91c804cd2782..00e5d0a469e1 100644
--- a/sound/usb/caiaq/control.c
+++ b/sound/usb/caiaq/control.c
@@ -55,6 +55,10 @@ static int control_info(struct snd_kcontrol *kcontrol,
55 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): 55 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
56 maxval = 127; 56 maxval = 127;
57 break; 57 break;
58
59 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
60 maxval = 31;
61 break;
58 } 62 }
59 63
60 if (is_intval) { 64 if (is_intval) {
@@ -93,6 +97,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
93 struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol); 97 struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
94 struct snd_usb_caiaqdev *dev = caiaqdev(chip->card); 98 struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
95 int pos = kcontrol->private_value; 99 int pos = kcontrol->private_value;
100 int v = ucontrol->value.integer.value[0];
96 unsigned char cmd = EP1_CMD_WRITE_IO; 101 unsigned char cmd = EP1_CMD_WRITE_IO;
97 102
98 if (dev->chip.usb_id == 103 if (dev->chip.usb_id ==
@@ -100,12 +105,27 @@ static int control_put(struct snd_kcontrol *kcontrol,
100 cmd = EP1_CMD_DIMM_LEDS; 105 cmd = EP1_CMD_DIMM_LEDS;
101 106
102 if (pos & CNT_INTVAL) { 107 if (pos & CNT_INTVAL) {
103 dev->control_state[pos & ~CNT_INTVAL] 108 int i = pos & ~CNT_INTVAL;
104 = ucontrol->value.integer.value[0]; 109
105 snd_usb_caiaq_send_command(dev, cmd, 110 dev->control_state[i] = v;
106 dev->control_state, sizeof(dev->control_state)); 111
112 if (dev->chip.usb_id ==
113 USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4)) {
114 int actual_len;
115
116 dev->ep8_out_buf[0] = i;
117 dev->ep8_out_buf[1] = v;
118
119 usb_bulk_msg(dev->chip.dev,
120 usb_sndbulkpipe(dev->chip.dev, 8),
121 dev->ep8_out_buf, sizeof(dev->ep8_out_buf),
122 &actual_len, 200);
123 } else {
124 snd_usb_caiaq_send_command(dev, cmd,
125 dev->control_state, sizeof(dev->control_state));
126 }
107 } else { 127 } else {
108 if (ucontrol->value.integer.value[0]) 128 if (v)
109 dev->control_state[pos / 8] |= 1 << (pos % 8); 129 dev->control_state[pos / 8] |= 1 << (pos % 8);
110 else 130 else
111 dev->control_state[pos / 8] &= ~(1 << (pos % 8)); 131 dev->control_state[pos / 8] &= ~(1 << (pos % 8));
@@ -296,6 +316,179 @@ static struct caiaq_controller kontrolx1_controller[] = {
296 { "LED Deck B: SYNC", 8 | CNT_INTVAL }, 316 { "LED Deck B: SYNC", 8 | CNT_INTVAL },
297}; 317};
298 318
319static struct caiaq_controller kontrols4_controller[] = {
320 { "LED: Master: Quant", 10 | CNT_INTVAL },
321 { "LED: Master: Headphone", 11 | CNT_INTVAL },
322 { "LED: Master: Master", 12 | CNT_INTVAL },
323 { "LED: Master: Snap", 14 | CNT_INTVAL },
324 { "LED: Master: Warning", 15 | CNT_INTVAL },
325 { "LED: Master: Master button", 112 | CNT_INTVAL },
326 { "LED: Master: Snap button", 113 | CNT_INTVAL },
327 { "LED: Master: Rec", 118 | CNT_INTVAL },
328 { "LED: Master: Size", 119 | CNT_INTVAL },
329 { "LED: Master: Quant button", 120 | CNT_INTVAL },
330 { "LED: Master: Browser button", 121 | CNT_INTVAL },
331 { "LED: Master: Play button", 126 | CNT_INTVAL },
332 { "LED: Master: Undo button", 127 | CNT_INTVAL },
333
334 { "LED: Channel A: >", 4 | CNT_INTVAL },
335 { "LED: Channel A: <", 5 | CNT_INTVAL },
336 { "LED: Channel A: Meter 1", 97 | CNT_INTVAL },
337 { "LED: Channel A: Meter 2", 98 | CNT_INTVAL },
338 { "LED: Channel A: Meter 3", 99 | CNT_INTVAL },
339 { "LED: Channel A: Meter 4", 100 | CNT_INTVAL },
340 { "LED: Channel A: Meter 5", 101 | CNT_INTVAL },
341 { "LED: Channel A: Meter 6", 102 | CNT_INTVAL },
342 { "LED: Channel A: Meter clip", 103 | CNT_INTVAL },
343 { "LED: Channel A: Active", 114 | CNT_INTVAL },
344 { "LED: Channel A: Cue", 116 | CNT_INTVAL },
345 { "LED: Channel A: FX1", 149 | CNT_INTVAL },
346 { "LED: Channel A: FX2", 148 | CNT_INTVAL },
347
348 { "LED: Channel B: >", 2 | CNT_INTVAL },
349 { "LED: Channel B: <", 3 | CNT_INTVAL },
350 { "LED: Channel B: Meter 1", 89 | CNT_INTVAL },
351 { "LED: Channel B: Meter 2", 90 | CNT_INTVAL },
352 { "LED: Channel B: Meter 3", 91 | CNT_INTVAL },
353 { "LED: Channel B: Meter 4", 92 | CNT_INTVAL },
354 { "LED: Channel B: Meter 5", 93 | CNT_INTVAL },
355 { "LED: Channel B: Meter 6", 94 | CNT_INTVAL },
356 { "LED: Channel B: Meter clip", 95 | CNT_INTVAL },
357 { "LED: Channel B: Active", 122 | CNT_INTVAL },
358 { "LED: Channel B: Cue", 125 | CNT_INTVAL },
359 { "LED: Channel B: FX1", 147 | CNT_INTVAL },
360 { "LED: Channel B: FX2", 146 | CNT_INTVAL },
361
362 { "LED: Channel C: >", 6 | CNT_INTVAL },
363 { "LED: Channel C: <", 7 | CNT_INTVAL },
364 { "LED: Channel C: Meter 1", 105 | CNT_INTVAL },
365 { "LED: Channel C: Meter 2", 106 | CNT_INTVAL },
366 { "LED: Channel C: Meter 3", 107 | CNT_INTVAL },
367 { "LED: Channel C: Meter 4", 108 | CNT_INTVAL },
368 { "LED: Channel C: Meter 5", 109 | CNT_INTVAL },
369 { "LED: Channel C: Meter 6", 110 | CNT_INTVAL },
370 { "LED: Channel C: Meter clip", 111 | CNT_INTVAL },
371 { "LED: Channel C: Active", 115 | CNT_INTVAL },
372 { "LED: Channel C: Cue", 117 | CNT_INTVAL },
373 { "LED: Channel C: FX1", 151 | CNT_INTVAL },
374 { "LED: Channel C: FX2", 150 | CNT_INTVAL },
375
376 { "LED: Channel D: >", 0 | CNT_INTVAL },
377 { "LED: Channel D: <", 1 | CNT_INTVAL },
378 { "LED: Channel D: Meter 1", 81 | CNT_INTVAL },
379 { "LED: Channel D: Meter 2", 82 | CNT_INTVAL },
380 { "LED: Channel D: Meter 3", 83 | CNT_INTVAL },
381 { "LED: Channel D: Meter 4", 84 | CNT_INTVAL },
382 { "LED: Channel D: Meter 5", 85 | CNT_INTVAL },
383 { "LED: Channel D: Meter 6", 86 | CNT_INTVAL },
384 { "LED: Channel D: Meter clip", 87 | CNT_INTVAL },
385 { "LED: Channel D: Active", 123 | CNT_INTVAL },
386 { "LED: Channel D: Cue", 124 | CNT_INTVAL },
387 { "LED: Channel D: FX1", 145 | CNT_INTVAL },
388 { "LED: Channel D: FX2", 144 | CNT_INTVAL },
389
390 { "LED: Deck A: 1 (blue)", 22 | CNT_INTVAL },
391 { "LED: Deck A: 1 (green)", 23 | CNT_INTVAL },
392 { "LED: Deck A: 2 (blue)", 20 | CNT_INTVAL },
393 { "LED: Deck A: 2 (green)", 21 | CNT_INTVAL },
394 { "LED: Deck A: 3 (blue)", 18 | CNT_INTVAL },
395 { "LED: Deck A: 3 (green)", 19 | CNT_INTVAL },
396 { "LED: Deck A: 4 (blue)", 16 | CNT_INTVAL },
397 { "LED: Deck A: 4 (green)", 17 | CNT_INTVAL },
398 { "LED: Deck A: Load", 44 | CNT_INTVAL },
399 { "LED: Deck A: Deck C button", 45 | CNT_INTVAL },
400 { "LED: Deck A: In", 47 | CNT_INTVAL },
401 { "LED: Deck A: Out", 46 | CNT_INTVAL },
402 { "LED: Deck A: Shift", 24 | CNT_INTVAL },
403 { "LED: Deck A: Sync", 27 | CNT_INTVAL },
404 { "LED: Deck A: Cue", 26 | CNT_INTVAL },
405 { "LED: Deck A: Play", 25 | CNT_INTVAL },
406 { "LED: Deck A: Tempo up", 33 | CNT_INTVAL },
407 { "LED: Deck A: Tempo down", 32 | CNT_INTVAL },
408 { "LED: Deck A: Master", 34 | CNT_INTVAL },
409 { "LED: Deck A: Keylock", 35 | CNT_INTVAL },
410 { "LED: Deck A: Deck A", 37 | CNT_INTVAL },
411 { "LED: Deck A: Deck C", 36 | CNT_INTVAL },
412 { "LED: Deck A: Samples", 38 | CNT_INTVAL },
413 { "LED: Deck A: On Air", 39 | CNT_INTVAL },
414 { "LED: Deck A: Sample 1", 31 | CNT_INTVAL },
415 { "LED: Deck A: Sample 2", 30 | CNT_INTVAL },
416 { "LED: Deck A: Sample 3", 29 | CNT_INTVAL },
417 { "LED: Deck A: Sample 4", 28 | CNT_INTVAL },
418 { "LED: Deck A: Digit 1 - A", 55 | CNT_INTVAL },
419 { "LED: Deck A: Digit 1 - B", 54 | CNT_INTVAL },
420 { "LED: Deck A: Digit 1 - C", 53 | CNT_INTVAL },
421 { "LED: Deck A: Digit 1 - D", 52 | CNT_INTVAL },
422 { "LED: Deck A: Digit 1 - E", 51 | CNT_INTVAL },
423 { "LED: Deck A: Digit 1 - F", 50 | CNT_INTVAL },
424 { "LED: Deck A: Digit 1 - G", 49 | CNT_INTVAL },
425 { "LED: Deck A: Digit 1 - dot", 48 | CNT_INTVAL },
426 { "LED: Deck A: Digit 2 - A", 63 | CNT_INTVAL },
427 { "LED: Deck A: Digit 2 - B", 62 | CNT_INTVAL },
428 { "LED: Deck A: Digit 2 - C", 61 | CNT_INTVAL },
429 { "LED: Deck A: Digit 2 - D", 60 | CNT_INTVAL },
430 { "LED: Deck A: Digit 2 - E", 59 | CNT_INTVAL },
431 { "LED: Deck A: Digit 2 - F", 58 | CNT_INTVAL },
432 { "LED: Deck A: Digit 2 - G", 57 | CNT_INTVAL },
433 { "LED: Deck A: Digit 2 - dot", 56 | CNT_INTVAL },
434
435 { "LED: Deck B: 1 (blue)", 78 | CNT_INTVAL },
436 { "LED: Deck B: 1 (green)", 79 | CNT_INTVAL },
437 { "LED: Deck B: 2 (blue)", 76 | CNT_INTVAL },
438 { "LED: Deck B: 2 (green)", 77 | CNT_INTVAL },
439 { "LED: Deck B: 3 (blue)", 74 | CNT_INTVAL },
440 { "LED: Deck B: 3 (green)", 75 | CNT_INTVAL },
441 { "LED: Deck B: 4 (blue)", 72 | CNT_INTVAL },
442 { "LED: Deck B: 4 (green)", 73 | CNT_INTVAL },
443 { "LED: Deck B: Load", 180 | CNT_INTVAL },
444 { "LED: Deck B: Deck D button", 181 | CNT_INTVAL },
445 { "LED: Deck B: In", 183 | CNT_INTVAL },
446 { "LED: Deck B: Out", 182 | CNT_INTVAL },
447 { "LED: Deck B: Shift", 64 | CNT_INTVAL },
448 { "LED: Deck B: Sync", 67 | CNT_INTVAL },
449 { "LED: Deck B: Cue", 66 | CNT_INTVAL },
450 { "LED: Deck B: Play", 65 | CNT_INTVAL },
451 { "LED: Deck B: Tempo up", 185 | CNT_INTVAL },
452 { "LED: Deck B: Tempo down", 184 | CNT_INTVAL },
453 { "LED: Deck B: Master", 186 | CNT_INTVAL },
454 { "LED: Deck B: Keylock", 187 | CNT_INTVAL },
455 { "LED: Deck B: Deck B", 189 | CNT_INTVAL },
456 { "LED: Deck B: Deck D", 188 | CNT_INTVAL },
457 { "LED: Deck B: Samples", 190 | CNT_INTVAL },
458 { "LED: Deck B: On Air", 191 | CNT_INTVAL },
459 { "LED: Deck B: Sample 1", 71 | CNT_INTVAL },
460 { "LED: Deck B: Sample 2", 70 | CNT_INTVAL },
461 { "LED: Deck B: Sample 3", 69 | CNT_INTVAL },
462 { "LED: Deck B: Sample 4", 68 | CNT_INTVAL },
463 { "LED: Deck B: Digit 1 - A", 175 | CNT_INTVAL },
464 { "LED: Deck B: Digit 1 - B", 174 | CNT_INTVAL },
465 { "LED: Deck B: Digit 1 - C", 173 | CNT_INTVAL },
466 { "LED: Deck B: Digit 1 - D", 172 | CNT_INTVAL },
467 { "LED: Deck B: Digit 1 - E", 171 | CNT_INTVAL },
468 { "LED: Deck B: Digit 1 - F", 170 | CNT_INTVAL },
469 { "LED: Deck B: Digit 1 - G", 169 | CNT_INTVAL },
470 { "LED: Deck B: Digit 1 - dot", 168 | CNT_INTVAL },
471 { "LED: Deck B: Digit 2 - A", 167 | CNT_INTVAL },
472 { "LED: Deck B: Digit 2 - B", 166 | CNT_INTVAL },
473 { "LED: Deck B: Digit 2 - C", 165 | CNT_INTVAL },
474 { "LED: Deck B: Digit 2 - D", 164 | CNT_INTVAL },
475 { "LED: Deck B: Digit 2 - E", 163 | CNT_INTVAL },
476 { "LED: Deck B: Digit 2 - F", 162 | CNT_INTVAL },
477 { "LED: Deck B: Digit 2 - G", 161 | CNT_INTVAL },
478 { "LED: Deck B: Digit 2 - dot", 160 | CNT_INTVAL },
479
480 { "LED: FX1: dry/wet", 153 | CNT_INTVAL },
481 { "LED: FX1: 1", 154 | CNT_INTVAL },
482 { "LED: FX1: 2", 155 | CNT_INTVAL },
483 { "LED: FX1: 3", 156 | CNT_INTVAL },
484 { "LED: FX1: Mode", 157 | CNT_INTVAL },
485 { "LED: FX2: dry/wet", 129 | CNT_INTVAL },
486 { "LED: FX2: 1", 130 | CNT_INTVAL },
487 { "LED: FX2: 2", 131 | CNT_INTVAL },
488 { "LED: FX2: 3", 132 | CNT_INTVAL },
489 { "LED: FX2: Mode", 133 | CNT_INTVAL },
490};
491
299static int __devinit add_controls(struct caiaq_controller *c, int num, 492static int __devinit add_controls(struct caiaq_controller *c, int num,
300 struct snd_usb_caiaqdev *dev) 493 struct snd_usb_caiaqdev *dev)
301{ 494{
@@ -354,6 +547,11 @@ int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
354 ret = add_controls(kontrolx1_controller, 547 ret = add_controls(kontrolx1_controller,
355 ARRAY_SIZE(kontrolx1_controller), dev); 548 ARRAY_SIZE(kontrolx1_controller), dev);
356 break; 549 break;
550
551 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
552 ret = add_controls(kontrols4_controller,
553 ARRAY_SIZE(kontrols4_controller), dev);
554 break;
357 } 555 }
358 556
359 return ret; 557 return ret;
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index cdfb856bddd2..6480c3283c05 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -36,7 +36,7 @@
36#include "input.h" 36#include "input.h"
37 37
38MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); 38MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
39MODULE_DESCRIPTION("caiaq USB audio, version 1.3.21"); 39MODULE_DESCRIPTION("caiaq USB audio");
40MODULE_LICENSE("GPL"); 40MODULE_LICENSE("GPL");
41MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," 41MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
42 "{Native Instruments, RigKontrol3}," 42 "{Native Instruments, RigKontrol3},"
@@ -48,7 +48,8 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
48 "{Native Instruments, Audio 8 DJ}," 48 "{Native Instruments, Audio 8 DJ},"
49 "{Native Instruments, Session I/O}," 49 "{Native Instruments, Session I/O},"
50 "{Native Instruments, GuitarRig mobile}" 50 "{Native Instruments, GuitarRig mobile}"
51 "{Native Instruments, Traktor Kontrol X1}"); 51 "{Native Instruments, Traktor Kontrol X1}"
52 "{Native Instruments, Traktor Kontrol S4}");
52 53
53static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */ 54static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
54static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */ 55static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
@@ -134,6 +135,11 @@ static struct usb_device_id snd_usb_id_table[] = {
134 .idVendor = USB_VID_NATIVEINSTRUMENTS, 135 .idVendor = USB_VID_NATIVEINSTRUMENTS,
135 .idProduct = USB_PID_TRAKTORKONTROLX1 136 .idProduct = USB_PID_TRAKTORKONTROLX1
136 }, 137 },
138 {
139 .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
140 .idVendor = USB_VID_NATIVEINSTRUMENTS,
141 .idProduct = USB_PID_TRAKTORKONTROLS4
142 },
137 { /* terminator */ } 143 { /* terminator */ }
138}; 144};
139 145
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index f1117ecc84fd..e3d8a3efb35b 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -16,6 +16,7 @@
16#define USB_PID_SESSIONIO 0x1915 16#define USB_PID_SESSIONIO 0x1915
17#define USB_PID_GUITARRIGMOBILE 0x0d8d 17#define USB_PID_GUITARRIGMOBILE 0x0d8d
18#define USB_PID_TRAKTORKONTROLX1 0x2305 18#define USB_PID_TRAKTORKONTROLX1 0x2305
19#define USB_PID_TRAKTORKONTROLS4 0xbaff
19 20
20#define EP1_BUFSIZE 64 21#define EP1_BUFSIZE 64
21#define EP4_BUFSIZE 512 22#define EP4_BUFSIZE 512
@@ -99,13 +100,14 @@ struct snd_usb_caiaqdev {
99 struct snd_pcm_substream *sub_capture[MAX_STREAMS]; 100 struct snd_pcm_substream *sub_capture[MAX_STREAMS];
100 101
101 /* Controls */ 102 /* Controls */
102 unsigned char control_state[64]; 103 unsigned char control_state[256];
104 unsigned char ep8_out_buf[2];
103 105
104 /* Linux input */ 106 /* Linux input */
105#ifdef CONFIG_SND_USB_CAIAQ_INPUT 107#ifdef CONFIG_SND_USB_CAIAQ_INPUT
106 struct input_dev *input_dev; 108 struct input_dev *input_dev;
107 char phys[64]; /* physical device path */ 109 char phys[64]; /* physical device path */
108 unsigned short keycode[64]; 110 unsigned short keycode[128];
109 struct urb *ep4_in_urb; 111 struct urb *ep4_in_urb;
110 unsigned char ep4_in_buf[EP4_BUFSIZE]; 112 unsigned char ep4_in_buf[EP4_BUFSIZE];
111#endif 113#endif
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index dcb620796d9e..4432ef7a70a9 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -67,7 +67,12 @@ static unsigned short keycode_kore[] = {
67 KEY_BRL_DOT5 67 KEY_BRL_DOT5
68}; 68};
69 69
70#define KONTROLX1_INPUTS 40 70#define KONTROLX1_INPUTS (40)
71#define KONTROLS4_BUTTONS (12 * 8)
72#define KONTROLS4_AXIS (46)
73
74#define KONTROLS4_BUTTON(X) ((X) + BTN_MISC)
75#define KONTROLS4_ABS(X) ((X) + ABS_HAT0X)
71 76
72#define DEG90 (range / 2) 77#define DEG90 (range / 2)
73#define DEG180 (range) 78#define DEG180 (range)
@@ -139,6 +144,13 @@ static unsigned int decode_erp(unsigned char a, unsigned char b)
139#undef HIGH_PEAK 144#undef HIGH_PEAK
140#undef LOW_PEAK 145#undef LOW_PEAK
141 146
147static inline void snd_caiaq_input_report_abs(struct snd_usb_caiaqdev *dev,
148 int axis, const unsigned char *buf,
149 int offset)
150{
151 input_report_abs(dev->input_dev, axis,
152 (buf[offset * 2] << 8) | buf[offset * 2 + 1]);
153}
142 154
143static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev, 155static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
144 const unsigned char *buf, 156 const unsigned char *buf,
@@ -148,36 +160,30 @@ static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
148 160
149 switch (dev->chip.usb_id) { 161 switch (dev->chip.usb_id) {
150 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): 162 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
151 input_report_abs(input_dev, ABS_X, (buf[4] << 8) | buf[5]); 163 snd_caiaq_input_report_abs(dev, ABS_X, buf, 2);
152 input_report_abs(input_dev, ABS_Y, (buf[0] << 8) | buf[1]); 164 snd_caiaq_input_report_abs(dev, ABS_Y, buf, 0);
153 input_report_abs(input_dev, ABS_Z, (buf[2] << 8) | buf[3]); 165 snd_caiaq_input_report_abs(dev, ABS_Z, buf, 1);
154 input_sync(input_dev);
155 break; 166 break;
156 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): 167 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
157 input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]);
158 input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]);
159 input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
160 input_sync(input_dev);
161 break;
162 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): 168 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
163 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): 169 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
164 input_report_abs(input_dev, ABS_X, (buf[0] << 8) | buf[1]); 170 snd_caiaq_input_report_abs(dev, ABS_X, buf, 0);
165 input_report_abs(input_dev, ABS_Y, (buf[2] << 8) | buf[3]); 171 snd_caiaq_input_report_abs(dev, ABS_Y, buf, 1);
166 input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]); 172 snd_caiaq_input_report_abs(dev, ABS_Z, buf, 2);
167 input_sync(input_dev);
168 break; 173 break;
169 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): 174 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
170 input_report_abs(input_dev, ABS_HAT0X, (buf[8] << 8) | buf[9]); 175 snd_caiaq_input_report_abs(dev, ABS_HAT0X, buf, 4);
171 input_report_abs(input_dev, ABS_HAT0Y, (buf[4] << 8) | buf[5]); 176 snd_caiaq_input_report_abs(dev, ABS_HAT0Y, buf, 2);
172 input_report_abs(input_dev, ABS_HAT1X, (buf[12] << 8) | buf[13]); 177 snd_caiaq_input_report_abs(dev, ABS_HAT1X, buf, 6);
173 input_report_abs(input_dev, ABS_HAT1Y, (buf[2] << 8) | buf[3]); 178 snd_caiaq_input_report_abs(dev, ABS_HAT1Y, buf, 1);
174 input_report_abs(input_dev, ABS_HAT2X, (buf[14] << 8) | buf[15]); 179 snd_caiaq_input_report_abs(dev, ABS_HAT2X, buf, 7);
175 input_report_abs(input_dev, ABS_HAT2Y, (buf[0] << 8) | buf[1]); 180 snd_caiaq_input_report_abs(dev, ABS_HAT2Y, buf, 0);
176 input_report_abs(input_dev, ABS_HAT3X, (buf[10] << 8) | buf[11]); 181 snd_caiaq_input_report_abs(dev, ABS_HAT3X, buf, 5);
177 input_report_abs(input_dev, ABS_HAT3Y, (buf[6] << 8) | buf[7]); 182 snd_caiaq_input_report_abs(dev, ABS_HAT3Y, buf, 3);
178 input_sync(input_dev);
179 break; 183 break;
180 } 184 }
185
186 input_sync(input_dev);
181} 187}
182 188
183static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev, 189static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
@@ -250,6 +256,150 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
250 input_sync(input_dev); 256 input_sync(input_dev);
251} 257}
252 258
259#define TKS4_MSGBLOCK_SIZE 16
260
261static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
262 const unsigned char *buf,
263 unsigned int len)
264{
265 while (len) {
266 unsigned int i, block_id = (buf[0] << 8) | buf[1];
267
268 switch (block_id) {
269 case 0:
270 /* buttons */
271 for (i = 0; i < KONTROLS4_BUTTONS; i++)
272 input_report_key(dev->input_dev, KONTROLS4_BUTTON(i),
273 (buf[4 + (i / 8)] >> (i % 8)) & 1);
274 break;
275
276 case 1:
277 /* left wheel */
278 input_report_abs(dev->input_dev, KONTROLS4_ABS(36), buf[9] | ((buf[8] & 0x3) << 8));
279 /* right wheel */
280 input_report_abs(dev->input_dev, KONTROLS4_ABS(37), buf[13] | ((buf[12] & 0x3) << 8));
281
282 /* rotary encoders */
283 input_report_abs(dev->input_dev, KONTROLS4_ABS(38), buf[3] & 0xf);
284 input_report_abs(dev->input_dev, KONTROLS4_ABS(39), buf[4] >> 4);
285 input_report_abs(dev->input_dev, KONTROLS4_ABS(40), buf[4] & 0xf);
286 input_report_abs(dev->input_dev, KONTROLS4_ABS(41), buf[5] >> 4);
287 input_report_abs(dev->input_dev, KONTROLS4_ABS(42), buf[5] & 0xf);
288 input_report_abs(dev->input_dev, KONTROLS4_ABS(43), buf[6] >> 4);
289 input_report_abs(dev->input_dev, KONTROLS4_ABS(44), buf[6] & 0xf);
290 input_report_abs(dev->input_dev, KONTROLS4_ABS(45), buf[7] >> 4);
291 input_report_abs(dev->input_dev, KONTROLS4_ABS(46), buf[7] & 0xf);
292
293 break;
294 case 2:
295 /* Volume Fader Channel D */
296 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(0), buf, 1);
297 /* Volume Fader Channel B */
298 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(1), buf, 2);
299 /* Volume Fader Channel A */
300 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(2), buf, 3);
301 /* Volume Fader Channel C */
302 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(3), buf, 4);
303 /* Loop Volume */
304 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(4), buf, 6);
305 /* Crossfader */
306 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(7), buf, 7);
307
308 break;
309
310 case 3:
311 /* Tempo Fader R */
312 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(6), buf, 3);
313 /* Tempo Fader L */
314 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(5), buf, 4);
315 /* Mic Volume */
316 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(8), buf, 6);
317 /* Cue Mix */
318 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(9), buf, 7);
319
320 break;
321
322 case 4:
323 /* Wheel distance sensor L */
324 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(10), buf, 1);
325 /* Wheel distance sensor R */
326 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(11), buf, 2);
327 /* Channel D EQ - Filter */
328 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(12), buf, 3);
329 /* Channel D EQ - Low */
330 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(13), buf, 4);
331 /* Channel D EQ - Mid */
332 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(14), buf, 5);
333 /* Channel D EQ - Hi */
334 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(15), buf, 6);
335 /* FX2 - dry/wet */
336 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(16), buf, 7);
337
338 break;
339
340 case 5:
341 /* FX2 - 1 */
342 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(17), buf, 1);
343 /* FX2 - 2 */
344 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(18), buf, 2);
345 /* FX2 - 3 */
346 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(19), buf, 3);
347 /* Channel B EQ - Filter */
348 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(20), buf, 4);
349 /* Channel B EQ - Low */
350 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(21), buf, 5);
351 /* Channel B EQ - Mid */
352 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(22), buf, 6);
353 /* Channel B EQ - Hi */
354 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(23), buf, 7);
355
356 break;
357
358 case 6:
359 /* Channel A EQ - Filter */
360 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(24), buf, 1);
361 /* Channel A EQ - Low */
362 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(25), buf, 2);
363 /* Channel A EQ - Mid */
364 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(26), buf, 3);
365 /* Channel A EQ - Hi */
366 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(27), buf, 4);
367 /* Channel C EQ - Filter */
368 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(28), buf, 5);
369 /* Channel C EQ - Low */
370 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(29), buf, 6);
371 /* Channel C EQ - Mid */
372 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(30), buf, 7);
373
374 break;
375
376 case 7:
377 /* Channel C EQ - Hi */
378 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(31), buf, 1);
379 /* FX1 - wet/dry */
380 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(32), buf, 2);
381 /* FX1 - 1 */
382 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(33), buf, 3);
383 /* FX1 - 2 */
384 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(34), buf, 4);
385 /* FX1 - 3 */
386 snd_caiaq_input_report_abs(dev, KONTROLS4_ABS(35), buf, 5);
387
388 break;
389
390 default:
391 debug("%s(): bogus block (id %d)\n",
392 __func__, block_id);
393 return;
394 }
395
396 len -= TKS4_MSGBLOCK_SIZE;
397 buf += TKS4_MSGBLOCK_SIZE;
398 }
399
400 input_sync(dev->input_dev);
401}
402
253static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb) 403static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
254{ 404{
255 struct snd_usb_caiaqdev *dev = urb->context; 405 struct snd_usb_caiaqdev *dev = urb->context;
@@ -259,11 +409,11 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
259 if (urb->status || !dev || urb != dev->ep4_in_urb) 409 if (urb->status || !dev || urb != dev->ep4_in_urb)
260 return; 410 return;
261 411
262 if (urb->actual_length < 24)
263 goto requeue;
264
265 switch (dev->chip.usb_id) { 412 switch (dev->chip.usb_id) {
266 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): 413 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
414 if (urb->actual_length < 24)
415 goto requeue;
416
267 if (buf[0] & 0x3) 417 if (buf[0] & 0x3)
268 snd_caiaq_input_read_io(dev, buf + 1, 7); 418 snd_caiaq_input_read_io(dev, buf + 1, 7);
269 419
@@ -271,6 +421,10 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
271 snd_caiaq_input_read_analog(dev, buf + 8, 16); 421 snd_caiaq_input_read_analog(dev, buf + 8, 16);
272 422
273 break; 423 break;
424
425 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
426 snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length);
427 break;
274 } 428 }
275 429
276requeue: 430requeue:
@@ -289,6 +443,7 @@ static int snd_usb_caiaq_input_open(struct input_dev *idev)
289 443
290 switch (dev->chip.usb_id) { 444 switch (dev->chip.usb_id) {
291 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): 445 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
446 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
292 if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0) 447 if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
293 return -EIO; 448 return -EIO;
294 break; 449 break;
@@ -306,6 +461,7 @@ static void snd_usb_caiaq_input_close(struct input_dev *idev)
306 461
307 switch (dev->chip.usb_id) { 462 switch (dev->chip.usb_id) {
308 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): 463 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
464 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
309 usb_kill_urb(dev->ep4_in_urb); 465 usb_kill_urb(dev->ep4_in_urb);
310 break; 466 break;
311 } 467 }
@@ -456,6 +612,46 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
456 snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5); 612 snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
457 613
458 break; 614 break;
615
616 case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
617 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
618 BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLS4_BUTTONS);
619 for (i = 0; i < KONTROLS4_BUTTONS; i++)
620 dev->keycode[i] = KONTROLS4_BUTTON(i);
621 input->keycodemax = KONTROLS4_BUTTONS;
622
623 for (i = 0; i < KONTROLS4_AXIS; i++) {
624 int axis = KONTROLS4_ABS(i);
625 input->absbit[BIT_WORD(axis)] |= BIT_MASK(axis);
626 }
627
628 /* 36 analog potentiometers and faders */
629 for (i = 0; i < 36; i++)
630 input_set_abs_params(input, KONTROLS4_ABS(i), 0, 0xfff, 0, 10);
631
632 /* 2 encoder wheels */
633 input_set_abs_params(input, KONTROLS4_ABS(36), 0, 0x3ff, 0, 1);
634 input_set_abs_params(input, KONTROLS4_ABS(37), 0, 0x3ff, 0, 1);
635
636 /* 9 rotary encoders */
637 for (i = 0; i < 9; i++)
638 input_set_abs_params(input, KONTROLS4_ABS(38+i), 0, 0xf, 0, 1);
639
640 dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
641 if (!dev->ep4_in_urb) {
642 ret = -ENOMEM;
643 goto exit_free_idev;
644 }
645
646 usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
647 usb_rcvbulkpipe(usb_dev, 0x4),
648 dev->ep4_in_buf, EP4_BUFSIZE,
649 snd_usb_caiaq_ep4_reply_dispatch, dev);
650
651 snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
652
653 break;
654
459 default: 655 default:
460 /* no input methods supported on this device */ 656 /* no input methods supported on this device */
461 goto exit_free_idev; 657 goto exit_free_idev;
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 4eabafa5b037..800f7cb4f251 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -300,9 +300,13 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
300 300
301 *rchip = NULL; 301 *rchip = NULL;
302 302
303 if (snd_usb_get_speed(dev) != USB_SPEED_LOW && 303 switch (snd_usb_get_speed(dev)) {
304 snd_usb_get_speed(dev) != USB_SPEED_FULL && 304 case USB_SPEED_LOW:
305 snd_usb_get_speed(dev) != USB_SPEED_HIGH) { 305 case USB_SPEED_FULL:
306 case USB_SPEED_HIGH:
307 case USB_SPEED_SUPER:
308 break;
309 default:
306 snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev)); 310 snd_printk(KERN_ERR "unknown device speed %d\n", snd_usb_get_speed(dev));
307 return -ENXIO; 311 return -ENXIO;
308 } 312 }
@@ -378,11 +382,22 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
378 if (len < sizeof(card->longname)) 382 if (len < sizeof(card->longname))
379 usb_make_path(dev, card->longname + len, sizeof(card->longname) - len); 383 usb_make_path(dev, card->longname + len, sizeof(card->longname) - len);
380 384
381 strlcat(card->longname, 385 switch (snd_usb_get_speed(dev)) {
382 snd_usb_get_speed(dev) == USB_SPEED_LOW ? ", low speed" : 386 case USB_SPEED_LOW:
383 snd_usb_get_speed(dev) == USB_SPEED_FULL ? ", full speed" : 387 strlcat(card->longname, ", low speed", sizeof(card->longname));
384 ", high speed", 388 break;
385 sizeof(card->longname)); 389 case USB_SPEED_FULL:
390 strlcat(card->longname, ", full speed", sizeof(card->longname));
391 break;
392 case USB_SPEED_HIGH:
393 strlcat(card->longname, ", high speed", sizeof(card->longname));
394 break;
395 case USB_SPEED_SUPER:
396 strlcat(card->longname, ", super speed", sizeof(card->longname));
397 break;
398 default:
399 break;
400 }
386 401
387 snd_usb_audio_create_proc(chip); 402 snd_usb_audio_create_proc(chip);
388 403
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index ef0a07e34844..b0ef9f501896 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -405,8 +405,6 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
405 break; 405 break;
406 case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */ 406 case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
407 case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ 407 case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
408 case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra 8 */
409 case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
410 /* doesn't set the sample rate attribute, but supports it */ 408 /* doesn't set the sample rate attribute, but supports it */
411 fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; 409 fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
412 break; 410 break;
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index d48d6f8f6ac9..f280c1903c25 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -103,11 +103,16 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
103unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip, 103unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
104 struct usb_host_interface *alts) 104 struct usb_host_interface *alts)
105{ 105{
106 if (snd_usb_get_speed(chip->dev) == USB_SPEED_HIGH && 106 switch (snd_usb_get_speed(chip->dev)) {
107 get_endpoint(alts, 0)->bInterval >= 1 && 107 case USB_SPEED_HIGH:
108 get_endpoint(alts, 0)->bInterval <= 4) 108 case USB_SPEED_SUPER:
109 return get_endpoint(alts, 0)->bInterval - 1; 109 if (get_endpoint(alts, 0)->bInterval >= 1 &&
110 else 110 get_endpoint(alts, 0)->bInterval <= 4)
111 return 0; 111 return get_endpoint(alts, 0)->bInterval - 1;
112 break;
113 default:
114 break;
115 }
116 return 0;
112} 117}
113 118
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index b9c2bc65f51a..25bce7e5b1af 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -784,7 +784,7 @@ static struct usb_protocol_ops snd_usbmidi_novation_ops = {
784}; 784};
785 785
786/* 786/*
787 * "raw" protocol: used by the MOTU FastLane. 787 * "raw" protocol: just move raw MIDI bytes from/to the endpoint
788 */ 788 */
789 789
790static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep, 790static void snd_usbmidi_raw_input(struct snd_usb_midi_in_endpoint* ep,
@@ -834,7 +834,14 @@ static void snd_usbmidi_us122l_output(struct snd_usb_midi_out_endpoint *ep,
834 834
835 if (!ep->ports[0].active) 835 if (!ep->ports[0].active)
836 return; 836 return;
837 count = snd_usb_get_speed(ep->umidi->dev) == USB_SPEED_HIGH ? 1 : 2; 837 switch (snd_usb_get_speed(ep->umidi->dev)) {
838 case USB_SPEED_HIGH:
839 case USB_SPEED_SUPER:
840 count = 1;
841 break;
842 default:
843 count = 2;
844 }
838 count = snd_rawmidi_transmit(ep->ports[0].substream, 845 count = snd_rawmidi_transmit(ep->ports[0].substream,
839 urb->transfer_buffer, 846 urb->transfer_buffer,
840 count); 847 count);
@@ -2115,7 +2122,7 @@ int snd_usbmidi_create(struct snd_card *card,
2115 umidi->usb_protocol_ops = &snd_usbmidi_novation_ops; 2122 umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
2116 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); 2123 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
2117 break; 2124 break;
2118 case QUIRK_MIDI_FASTLANE: 2125 case QUIRK_MIDI_RAW_BYTES:
2119 umidi->usb_protocol_ops = &snd_usbmidi_raw_ops; 2126 umidi->usb_protocol_ops = &snd_usbmidi_raw_ops;
2120 /* 2127 /*
2121 * Interface 1 contains isochronous endpoints, but with the same 2128 * Interface 1 contains isochronous endpoints, but with the same
@@ -2126,7 +2133,8 @@ int snd_usbmidi_create(struct snd_card *card,
2126 * interface 0, so we have to make sure that the USB core looks 2133 * interface 0, so we have to make sure that the USB core looks
2127 * again at interface 0 by calling usb_set_interface() on it. 2134 * again at interface 0 by calling usb_set_interface() on it.
2128 */ 2135 */
2129 usb_set_interface(umidi->dev, 0, 0); 2136 if (umidi->usb_id == USB_ID(0x07fd, 0x0001)) /* MOTU Fastlane */
2137 usb_set_interface(umidi->dev, 0, 0);
2130 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints); 2138 err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
2131 break; 2139 break;
2132 case QUIRK_MIDI_EMAGIC: 2140 case QUIRK_MIDI_EMAGIC:
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 3ed3901369ce..f2d74d654b3c 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -759,8 +759,6 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
759 */ 759 */
760static int get_min_max(struct usb_mixer_elem_info *cval, int default_min) 760static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
761{ 761{
762 struct snd_usb_audio *chip = cval->mixer->chip;
763
764 /* for failsafe */ 762 /* for failsafe */
765 cval->min = default_min; 763 cval->min = default_min;
766 cval->max = cval->min + 1; 764 cval->max = cval->min + 1;
@@ -783,7 +781,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
783 if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 || 781 if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
784 get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) { 782 get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
785 snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", 783 snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
786 cval->id, snd_usb_ctrl_intf(chip), cval->control, cval->id); 784 cval->id, snd_usb_ctrl_intf(cval->mixer->chip), cval->control, cval->id);
787 return -EINVAL; 785 return -EINVAL;
788 } 786 }
789 if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) { 787 if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -1642,9 +1640,10 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl
1642 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1640 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1643 uinfo->count = 1; 1641 uinfo->count = 1;
1644 uinfo->value.enumerated.items = cval->max; 1642 uinfo->value.enumerated.items = cval->max;
1645 if ((int)uinfo->value.enumerated.item >= cval->max) 1643 if (uinfo->value.enumerated.item >= cval->max)
1646 uinfo->value.enumerated.item = cval->max - 1; 1644 uinfo->value.enumerated.item = cval->max - 1;
1647 strcpy(uinfo->value.enumerated.name, itemlist[uinfo->value.enumerated.item]); 1645 strlcpy(uinfo->value.enumerated.name, itemlist[uinfo->value.enumerated.item],
1646 sizeof(uinfo->value.enumerated.name));
1648 return 0; 1647 return 0;
1649} 1648}
1650 1649
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index e7df1e5e3f2e..7dae05d8783e 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -60,6 +60,7 @@ static const struct rc_config {
60 { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ 60 { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */
61 { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ 61 { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */
62 { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ 62 { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */
63 { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi */
63 { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ 64 { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */
64}; 65};
65 66
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 3b5135c93062..f49756c1b837 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -466,7 +466,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
466 return 0; 466 return 0;
467 } 467 }
468 /* check whether the period time is >= the data packet interval */ 468 /* check whether the period time is >= the data packet interval */
469 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) { 469 if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
470 ptime = 125 * (1 << fp->datainterval); 470 ptime = 125 * (1 << fp->datainterval);
471 if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { 471 if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
472 hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); 472 hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max);
@@ -734,7 +734,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
734 } 734 }
735 735
736 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; 736 param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
737 if (snd_usb_get_speed(subs->dev) != USB_SPEED_HIGH) 737 if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
738 /* full speed devices have fixed data packet interval */ 738 /* full speed devices have fixed data packet interval */
739 ptmin = 1000; 739 ptmin = 1000;
740 if (ptmin == 1000) 740 if (ptmin == 1000)
diff --git a/sound/usb/proc.c b/sound/usb/proc.c
index f5e3f356b95f..3c650ab3c91d 100644
--- a/sound/usb/proc.c
+++ b/sound/usb/proc.c
@@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
107 } 107 }
108 snd_iprintf(buffer, "\n"); 108 snd_iprintf(buffer, "\n");
109 } 109 }
110 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) 110 if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
111 snd_iprintf(buffer, " Data packet interval: %d us\n", 111 snd_iprintf(buffer, " Data packet interval: %d us\n",
112 125 * (1 << fp->datainterval)); 112 125 * (1 << fp->datainterval));
113 // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); 113 // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize);
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 2e8003f98fca..ad7079d1676c 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -240,9 +240,21 @@ YAMAHA_DEVICE(0x104f, NULL),
240YAMAHA_DEVICE(0x1050, NULL), 240YAMAHA_DEVICE(0x1050, NULL),
241YAMAHA_DEVICE(0x1051, NULL), 241YAMAHA_DEVICE(0x1051, NULL),
242YAMAHA_DEVICE(0x1052, NULL), 242YAMAHA_DEVICE(0x1052, NULL),
243YAMAHA_INTERFACE(0x1053, 0, NULL),
244YAMAHA_INTERFACE(0x1054, 0, NULL),
245YAMAHA_DEVICE(0x1055, NULL),
246YAMAHA_DEVICE(0x1056, NULL),
247YAMAHA_DEVICE(0x1057, NULL),
248YAMAHA_DEVICE(0x1058, NULL),
249YAMAHA_DEVICE(0x1059, NULL),
250YAMAHA_DEVICE(0x105a, NULL),
251YAMAHA_DEVICE(0x105b, NULL),
252YAMAHA_DEVICE(0x105c, NULL),
253YAMAHA_DEVICE(0x105d, NULL),
243YAMAHA_DEVICE(0x2000, "DGP-7"), 254YAMAHA_DEVICE(0x2000, "DGP-7"),
244YAMAHA_DEVICE(0x2001, "DGP-5"), 255YAMAHA_DEVICE(0x2001, "DGP-5"),
245YAMAHA_DEVICE(0x2002, NULL), 256YAMAHA_DEVICE(0x2002, NULL),
257YAMAHA_DEVICE(0x2003, NULL),
246YAMAHA_DEVICE(0x5000, "CS1D"), 258YAMAHA_DEVICE(0x5000, "CS1D"),
247YAMAHA_DEVICE(0x5001, "DSP1D"), 259YAMAHA_DEVICE(0x5001, "DSP1D"),
248YAMAHA_DEVICE(0x5002, "DME32"), 260YAMAHA_DEVICE(0x5002, "DME32"),
@@ -1136,11 +1148,34 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1136 } 1148 }
1137}, 1149},
1138{ 1150{
1151 /* has ID 0x0066 when not in "Advanced Driver" mode */
1152 USB_DEVICE(0x0582, 0x0064),
1153 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1154 /* .vendor_name = "EDIROL", */
1155 /* .product_name = "PCR-1", */
1156 .ifnum = QUIRK_ANY_INTERFACE,
1157 .type = QUIRK_COMPOSITE,
1158 .data = (const struct snd_usb_audio_quirk[]) {
1159 {
1160 .ifnum = 1,
1161 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1162 },
1163 {
1164 .ifnum = 2,
1165 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1166 },
1167 {
1168 .ifnum = -1
1169 }
1170 }
1171 }
1172},
1173{
1139 /* has ID 0x0067 when not in "Advanced Driver" mode */ 1174 /* has ID 0x0067 when not in "Advanced Driver" mode */
1140 USB_DEVICE(0x0582, 0x0065), 1175 USB_DEVICE(0x0582, 0x0065),
1141 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { 1176 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1142 .vendor_name = "EDIROL", 1177 /* .vendor_name = "EDIROL", */
1143 .product_name = "PCR-1", 1178 /* .product_name = "PCR-1", */
1144 .ifnum = 0, 1179 .ifnum = 0,
1145 .type = QUIRK_MIDI_FIXED_ENDPOINT, 1180 .type = QUIRK_MIDI_FIXED_ENDPOINT,
1146 .data = & (const struct snd_usb_midi_endpoint_info) { 1181 .data = & (const struct snd_usb_midi_endpoint_info) {
@@ -1525,6 +1560,50 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1525 } 1560 }
1526 } 1561 }
1527}, 1562},
1563{
1564 /* has ID 0x0110 when not in Advanced Driver mode */
1565 USB_DEVICE_VENDOR_SPEC(0x0582, 0x010f),
1566 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1567 /* .vendor_name = "Roland", */
1568 /* .product_name = "A-PRO", */
1569 .ifnum = 1,
1570 .type = QUIRK_MIDI_FIXED_ENDPOINT,
1571 .data = & (const struct snd_usb_midi_endpoint_info) {
1572 .out_cables = 0x0003,
1573 .in_cables = 0x0007
1574 }
1575 }
1576},
1577{
1578 USB_DEVICE(0x0582, 0x0113),
1579 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1580 /* .vendor_name = "BOSS", */
1581 /* .product_name = "ME-25", */
1582 .ifnum = QUIRK_ANY_INTERFACE,
1583 .type = QUIRK_COMPOSITE,
1584 .data = (const struct snd_usb_audio_quirk[]) {
1585 {
1586 .ifnum = 0,
1587 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1588 },
1589 {
1590 .ifnum = 1,
1591 .type = QUIRK_AUDIO_STANDARD_INTERFACE
1592 },
1593 {
1594 .ifnum = 2,
1595 .type = QUIRK_MIDI_FIXED_ENDPOINT,
1596 .data = & (const struct snd_usb_midi_endpoint_info) {
1597 .out_cables = 0x0001,
1598 .in_cables = 0x0001
1599 }
1600 },
1601 {
1602 .ifnum = -1
1603 }
1604 }
1605 }
1606},
1528 1607
1529/* Guillemot devices */ 1608/* Guillemot devices */
1530{ 1609{
@@ -1830,7 +1909,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1830 USB_DEVICE(0x0763, 0x2080), 1909 USB_DEVICE(0x0763, 0x2080),
1831 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { 1910 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1832 /* .vendor_name = "M-Audio", */ 1911 /* .vendor_name = "M-Audio", */
1833 /* .product_name = "Fast Track Ultra 8", */ 1912 /* .product_name = "Fast Track Ultra", */
1834 .ifnum = QUIRK_ANY_INTERFACE, 1913 .ifnum = QUIRK_ANY_INTERFACE,
1835 .type = QUIRK_COMPOSITE, 1914 .type = QUIRK_COMPOSITE,
1836 .data = & (const struct snd_usb_audio_quirk[]) { 1915 .data = & (const struct snd_usb_audio_quirk[]) {
@@ -1840,11 +1919,51 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1840 }, 1919 },
1841 { 1920 {
1842 .ifnum = 1, 1921 .ifnum = 1,
1843 .type = QUIRK_AUDIO_STANDARD_INTERFACE 1922 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
1923 .data = & (const struct audioformat) {
1924 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
1925 .channels = 8,
1926 .iface = 1,
1927 .altsetting = 1,
1928 .altset_idx = 1,
1929 .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
1930 .endpoint = 0x01,
1931 .ep_attr = 0x09,
1932 .rates = SNDRV_PCM_RATE_44100 |
1933 SNDRV_PCM_RATE_48000 |
1934 SNDRV_PCM_RATE_88200 |
1935 SNDRV_PCM_RATE_96000,
1936 .rate_min = 44100,
1937 .rate_max = 96000,
1938 .nr_rates = 4,
1939 .rate_table = (unsigned int[]) {
1940 44100, 48000, 88200, 96000
1941 }
1942 }
1844 }, 1943 },
1845 { 1944 {
1846 .ifnum = 2, 1945 .ifnum = 2,
1847 .type = QUIRK_AUDIO_STANDARD_INTERFACE 1946 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
1947 .data = & (const struct audioformat) {
1948 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
1949 .channels = 8,
1950 .iface = 2,
1951 .altsetting = 1,
1952 .altset_idx = 1,
1953 .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
1954 .endpoint = 0x81,
1955 .ep_attr = 0x05,
1956 .rates = SNDRV_PCM_RATE_44100 |
1957 SNDRV_PCM_RATE_48000 |
1958 SNDRV_PCM_RATE_88200 |
1959 SNDRV_PCM_RATE_96000,
1960 .rate_min = 44100,
1961 .rate_max = 96000,
1962 .nr_rates = 4,
1963 .rate_table = (unsigned int[]) {
1964 44100, 48000, 88200, 96000
1965 }
1966 }
1848 }, 1967 },
1849 /* interface 3 (MIDI) is standard compliant */ 1968 /* interface 3 (MIDI) is standard compliant */
1850 { 1969 {
@@ -1867,11 +1986,51 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1867 }, 1986 },
1868 { 1987 {
1869 .ifnum = 1, 1988 .ifnum = 1,
1870 .type = QUIRK_AUDIO_STANDARD_INTERFACE 1989 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
1990 .data = & (const struct audioformat) {
1991 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
1992 .channels = 8,
1993 .iface = 1,
1994 .altsetting = 1,
1995 .altset_idx = 1,
1996 .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
1997 .endpoint = 0x01,
1998 .ep_attr = 0x09,
1999 .rates = SNDRV_PCM_RATE_44100 |
2000 SNDRV_PCM_RATE_48000 |
2001 SNDRV_PCM_RATE_88200 |
2002 SNDRV_PCM_RATE_96000,
2003 .rate_min = 44100,
2004 .rate_max = 96000,
2005 .nr_rates = 4,
2006 .rate_table = (unsigned int[]) {
2007 44100, 48000, 88200, 96000
2008 }
2009 }
1871 }, 2010 },
1872 { 2011 {
1873 .ifnum = 2, 2012 .ifnum = 2,
1874 .type = QUIRK_AUDIO_STANDARD_INTERFACE 2013 .type = QUIRK_AUDIO_FIXED_ENDPOINT,
2014 .data = & (const struct audioformat) {
2015 .formats = SNDRV_PCM_FMTBIT_S24_3LE,
2016 .channels = 8,
2017 .iface = 2,
2018 .altsetting = 1,
2019 .altset_idx = 1,
2020 .attributes = UAC_EP_CS_ATTR_SAMPLE_RATE,
2021 .endpoint = 0x81,
2022 .ep_attr = 0x05,
2023 .rates = SNDRV_PCM_RATE_44100 |
2024 SNDRV_PCM_RATE_48000 |
2025 SNDRV_PCM_RATE_88200 |
2026 SNDRV_PCM_RATE_96000,
2027 .rate_min = 44100,
2028 .rate_max = 96000,
2029 .nr_rates = 4,
2030 .rate_table = (unsigned int[]) {
2031 44100, 48000, 88200, 96000
2032 }
2033 }
1875 }, 2034 },
1876 /* interface 3 (MIDI) is standard compliant */ 2035 /* interface 3 (MIDI) is standard compliant */
1877 { 2036 {
@@ -1919,7 +2078,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1919 .data = & (const struct snd_usb_audio_quirk[]) { 2078 .data = & (const struct snd_usb_audio_quirk[]) {
1920 { 2079 {
1921 .ifnum = 0, 2080 .ifnum = 0,
1922 .type = QUIRK_MIDI_FASTLANE 2081 .type = QUIRK_MIDI_RAW_BYTES
1923 }, 2082 },
1924 { 2083 {
1925 .ifnum = 1, 2084 .ifnum = 1,
@@ -2068,6 +2227,15 @@ YAMAHA_DEVICE(0x7010, "UB99"),
2068 } 2227 }
2069}, 2228},
2070{ 2229{
2230 USB_DEVICE(0x1235, 0x000e),
2231 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
2232 /* .vendor_name = "Novation", */
2233 /* .product_name = "Launchpad", */
2234 .ifnum = 0,
2235 .type = QUIRK_MIDI_RAW_BYTES
2236 }
2237},
2238{
2071 USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661), 2239 USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
2072 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { 2240 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
2073 .vendor_name = "Novation", 2241 .vendor_name = "Novation",
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 9a9da09586a5..cf8bf088394b 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -287,7 +287,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
287 [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk, 287 [QUIRK_MIDI_YAMAHA] = create_any_midi_quirk,
288 [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk, 288 [QUIRK_MIDI_MIDIMAN] = create_any_midi_quirk,
289 [QUIRK_MIDI_NOVATION] = create_any_midi_quirk, 289 [QUIRK_MIDI_NOVATION] = create_any_midi_quirk,
290 [QUIRK_MIDI_FASTLANE] = create_any_midi_quirk, 290 [QUIRK_MIDI_RAW_BYTES] = create_any_midi_quirk,
291 [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk, 291 [QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
292 [QUIRK_MIDI_CME] = create_any_midi_quirk, 292 [QUIRK_MIDI_CME] = create_any_midi_quirk,
293 [QUIRK_MIDI_AKAI] = create_any_midi_quirk, 293 [QUIRK_MIDI_AKAI] = create_any_midi_quirk,
diff --git a/sound/usb/urb.c b/sound/usb/urb.c
index de607d4411ac..8deeaad10f10 100644
--- a/sound/usb/urb.c
+++ b/sound/usb/urb.c
@@ -244,7 +244,7 @@ int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
244 else 244 else
245 subs->curpacksize = maxsize; 245 subs->curpacksize = maxsize;
246 246
247 if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH) 247 if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
248 packs_per_ms = 8 >> subs->datainterval; 248 packs_per_ms = 8 >> subs->datainterval;
249 else 249 else
250 packs_per_ms = 1; 250 packs_per_ms = 1;
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 24d3319cc34d..db3eb21627ee 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -70,7 +70,7 @@ enum quirk_type {
70 QUIRK_MIDI_YAMAHA, 70 QUIRK_MIDI_YAMAHA,
71 QUIRK_MIDI_MIDIMAN, 71 QUIRK_MIDI_MIDIMAN,
72 QUIRK_MIDI_NOVATION, 72 QUIRK_MIDI_NOVATION,
73 QUIRK_MIDI_FASTLANE, 73 QUIRK_MIDI_RAW_BYTES,
74 QUIRK_MIDI_EMAGIC, 74 QUIRK_MIDI_EMAGIC,
75 QUIRK_MIDI_CME, 75 QUIRK_MIDI_CME,
76 QUIRK_MIDI_AKAI, 76 QUIRK_MIDI_AKAI,
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index 2a528e56afd5..287ef73b1237 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -36,9 +36,9 @@
36 plain usx2y alsa mode is able to achieve 64frames, 4periods, but only at the 36 plain usx2y alsa mode is able to achieve 64frames, 4periods, but only at the
37 cost of easier triggered i.e. aeolus xruns (128 or 256frames, 37 cost of easier triggered i.e. aeolus xruns (128 or 256frames,
38 2periods works but is useless cause of crackling). 38 2periods works but is useless cause of crackling).
39 39
40 This is a first "proof of concept" implementation. 40 This is a first "proof of concept" implementation.
41 Later, funcionalities should migrate to more apropriate places: 41 Later, functionalities should migrate to more apropriate places:
42 Userland: 42 Userland:
43 - The jackd could mmap its float-pcm buffers directly from alsa-lib. 43 - The jackd could mmap its float-pcm buffers directly from alsa-lib.
44 - alsa-lib could provide power of 2 period sized shaping combined with int/float 44 - alsa-lib could provide power of 2 period sized shaping combined with int/float
@@ -54,7 +54,7 @@
54#include <linux/gfp.h> 54#include <linux/gfp.h>
55#include "usbusx2yaudio.c" 55#include "usbusx2yaudio.c"
56 56
57#if defined(USX2Y_NRPACKS_VARIABLE) || (!defined(USX2Y_NRPACKS_VARIABLE) && USX2Y_NRPACKS == 1) 57#if defined(USX2Y_NRPACKS_VARIABLE) || USX2Y_NRPACKS == 1
58 58
59#include <sound/hwdep.h> 59#include <sound/hwdep.h>
60 60