aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-10-25 04:00:30 -0400
committerTakashi Iwai <tiwai@suse.de>2010-10-25 04:00:30 -0400
commitaa5c14d5c0d3e4c587db4a1b220b9c86415c538f (patch)
tree0114637e8be2b38176e7e91e6cea3501b22cb66a
parent79fc84c7e0d2fe89c4e82f3a26fd8b0d13c31703 (diff)
parentb11bdb5254ff17cb63e4ae5088b73fdcd2cc2602 (diff)
Merge branch 'topic/asoc' into for-linus
Conflicts: arch/powerpc/platforms/85xx/p1022_ds.c
-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/max98088.h50
-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/tlv320aic3x.h43
-rw-r--r--include/sound/wm8962.h32
-rw-r--r--include/video/sh_mobile_hdmi.h16
-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.c27
-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
380 files changed, 31455 insertions, 16117 deletions
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 5dded5884133..f5f81f9719bd 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 9a5eb87425fc..11ce4b24befd 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 6b3984964cc5..3c6530475710 100644
--- a/arch/arm/mach-omap2/board-zoom-peripherals.c
+++ b/arch/arm/mach-omap2/board-zoom-peripherals.c
@@ -24,6 +24,8 @@
24#include <plat/common.h> 24#include <plat/common.h>
25#include <plat/usb.h> 25#include <plat/usb.h>
26 26
27#include <mach/board-zoom.h>
28
27#include "mux.h" 29#include "mux.h"
28#include "hsmmc.h" 30#include "hsmmc.h"
29 31
@@ -188,6 +190,11 @@ static int zoom_twl_gpio_setup(struct device *dev,
188 return 0; 190 return 0;
189} 191}
190 192
193/* EXTMUTE callback function */
194void zoom2_set_hs_extmute(int mute)
195{
196 gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute);
197}
191 198
192static int zoom_batt_table[] = { 199static int zoom_batt_table[] = {
193/* 0 C*/ 200/* 0 C*/
@@ -257,6 +264,11 @@ static struct i2c_board_info __initdata zoom_i2c_boardinfo[] = {
257 264
258static int __init omap_i2c_init(void) 265static int __init omap_i2c_init(void)
259{ 266{
267 if (machine_is_omap_zoom2()) {
268 zoom_audio_data.ramp_delay_value = 3; /* 161 ms */
269 zoom_audio_data.hs_extmute = 1;
270 zoom_audio_data.set_hs_extmute = zoom2_set_hs_extmute;
271 }
260 omap_register_i2c_bus(1, 2400, zoom_i2c_boardinfo, 272 omap_register_i2c_bus(1, 2400, zoom_i2c_boardinfo,
261 ARRAY_SIZE(zoom_i2c_boardinfo)); 273 ARRAY_SIZE(zoom_i2c_boardinfo));
262 omap_register_i2c_bus(2, 400, NULL, 0); 274 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 3ad9ecf7f5e2..00c8f835649f 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 2dbb265bedd4..512ae4696a6c 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>
@@ -847,6 +885,7 @@ static int __init omap2_init_devices(void)
847 * in alphabetical order so they're easier to sort through. 885 * in alphabetical order so they're easier to sort through.
848 */ 886 */
849 omap_hsmmc_reset(); 887 omap_hsmmc_reset();
888 omap_init_audio();
850 omap_init_camera(); 889 omap_init_camera();
851 omap_init_mbox(); 890 omap_init_mbox();
852 omap_init_mcspi(); 891 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 65447dc736c2..6d845446ce26 100644
--- a/arch/arm/mach-pxa/devices.c
+++ b/arch/arm/mach-pxa/devices.c
@@ -354,6 +354,31 @@ struct platform_device pxa_device_i2s = {
354 .num_resources = ARRAY_SIZE(pxai2s_resources), 354 .num_resources = ARRAY_SIZE(pxai2s_resources),
355}; 355};
356 356
357struct platform_device pxa_device_asoc_ssp1 = {
358 .name = "pxa-ssp-dai",
359 .id = 0,
360};
361
362struct platform_device pxa_device_asoc_ssp2= {
363 .name = "pxa-ssp-dai",
364 .id = 1,
365};
366
367struct platform_device pxa_device_asoc_ssp3 = {
368 .name = "pxa-ssp-dai",
369 .id = 2,
370};
371
372struct platform_device pxa_device_asoc_ssp4 = {
373 .name = "pxa-ssp-dai",
374 .id = 3,
375};
376
377struct platform_device pxa_device_asoc_platform = {
378 .name = "pxa-pcm-audio",
379 .id = -1,
380};
381
357static u64 pxaficp_dmamask = ~(u32)0; 382static u64 pxaficp_dmamask = ~(u32)0;
358 383
359struct platform_device pxa_device_ficp = { 384struct platform_device pxa_device_ficp = {
diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h
index 50353ea49ba4..491a27a92735 100644
--- a/arch/arm/mach-pxa/devices.h
+++ b/arch/arm/mach-pxa/devices.h
@@ -38,4 +38,10 @@ extern struct platform_device pxa3xx_device_i2c_power;
38 38
39extern struct platform_device pxa3xx_device_gcu; 39extern struct platform_device pxa3xx_device_gcu;
40 40
41extern struct platform_device pxa_device_asoc_platform;
42extern struct platform_device pxa_device_asoc_ssp1;
43extern struct platform_device pxa_device_asoc_ssp2;
44extern struct platform_device pxa_device_asoc_ssp3;
45extern struct platform_device pxa_device_asoc_ssp4;
46
41void __init pxa_register_device(struct platform_device *dev, void *data); 47void __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 fa0014847c71..90974e6fae6a 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -610,6 +610,11 @@ static struct platform_device *devices[] __initdata = {
610 &pxa27x_device_udc, 610 &pxa27x_device_udc,
611 &pxa_device_pmu, 611 &pxa_device_pmu,
612 &pxa_device_i2s, 612 &pxa_device_i2s,
613 &pxa_device_asoc_ssp1,
614 &pxa_device_asoc_ssp2,
615 &pxa_device_asoc_ssp3,
616 &pxa_device_asoc_ssp4,
617 &pxa_device_asoc_platform,
613 &sa1100_device_rtc, 618 &sa1100_device_rtc,
614 &pxa_device_rtc, 619 &pxa_device_rtc,
615 &pxa27x_device_ssp1, 620 &pxa27x_device_ssp1,
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index c479cbecf784..5ba9d99a1bf6 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 d498219fff1b..ecbddd377cb8 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 85f6f23a510f..a9fecd615de4 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 34e00902ce86..e15afdf12343 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 8b31fdfefc98..935cdc204f93 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/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/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/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/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 4948a79f86a0..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
@@ -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 36170be15aa7..d6c79fa56d12 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;
@@ -161,7 +161,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
161static int siu_pcm_rd_set(struct siu_port *port_info, 161static int siu_pcm_rd_set(struct siu_port *port_info,
162 dma_addr_t buff, size_t size) 162 dma_addr_t buff, size_t size)
163{ 163{
164 struct siu_info *info = siu_i2s_dai.private_data; 164 struct siu_info *info = siu_i2s_data;
165 u32 __iomem *base = info->reg; 165 u32 __iomem *base = info->reg;
166 struct siu_stream *siu_stream = &port_info->capture; 166 struct siu_stream *siu_stream = &port_info->capture;
167 struct snd_pcm_substream *substream = siu_stream->substream; 167 struct snd_pcm_substream *substream = siu_stream->substream;
@@ -270,7 +270,7 @@ static int siu_pcm_stmread_start(struct siu_port *port_info)
270 270
271static int siu_pcm_stmread_stop(struct siu_port *port_info) 271static int siu_pcm_stmread_stop(struct siu_port *port_info)
272{ 272{
273 struct siu_info *info = siu_i2s_dai.private_data; 273 struct siu_info *info = siu_i2s_data;
274 u32 __iomem *base = info->reg; 274 u32 __iomem *base = info->reg;
275 struct siu_stream *siu_stream = &port_info->capture; 275 struct siu_stream *siu_stream = &port_info->capture;
276 struct device *dev = siu_stream->substream->pcm->card->dev; 276 struct device *dev = siu_stream->substream->pcm->card->dev;
@@ -294,7 +294,7 @@ static int siu_pcm_stmread_stop(struct siu_port *port_info)
294static int siu_pcm_hw_params(struct snd_pcm_substream *ss, 294static int siu_pcm_hw_params(struct snd_pcm_substream *ss,
295 struct snd_pcm_hw_params *hw_params) 295 struct snd_pcm_hw_params *hw_params)
296{ 296{
297 struct siu_info *info = siu_i2s_dai.private_data; 297 struct siu_info *info = siu_i2s_data;
298 struct device *dev = ss->pcm->card->dev; 298 struct device *dev = ss->pcm->card->dev;
299 int ret; 299 int ret;
300 300
@@ -309,7 +309,7 @@ static int siu_pcm_hw_params(struct snd_pcm_substream *ss,
309 309
310static int siu_pcm_hw_free(struct snd_pcm_substream *ss) 310static int siu_pcm_hw_free(struct snd_pcm_substream *ss)
311{ 311{
312 struct siu_info *info = siu_i2s_dai.private_data; 312 struct siu_info *info = siu_i2s_data;
313 struct siu_port *port_info = siu_port_info(ss); 313 struct siu_port *port_info = siu_port_info(ss);
314 struct device *dev = ss->pcm->card->dev; 314 struct device *dev = ss->pcm->card->dev;
315 struct siu_stream *siu_stream; 315 struct siu_stream *siu_stream;
@@ -340,11 +340,12 @@ static bool filter(struct dma_chan *chan, void *slave)
340static int siu_pcm_open(struct snd_pcm_substream *ss) 340static int siu_pcm_open(struct snd_pcm_substream *ss)
341{ 341{
342 /* Playback / Capture */ 342 /* Playback / Capture */
343 struct siu_info *info = siu_i2s_dai.private_data; 343 struct snd_soc_pcm_runtime *rtd = ss->private_data;
344 struct siu_platform *pdata = rtd->platform->dev->platform_data;
345 struct siu_info *info = siu_i2s_data;
344 struct siu_port *port_info = siu_port_info(ss); 346 struct siu_port *port_info = siu_port_info(ss);
345 struct siu_stream *siu_stream; 347 struct siu_stream *siu_stream;
346 u32 port = info->port_id; 348 u32 port = info->port_id;
347 struct siu_platform *pdata = siu_i2s_dai.dev->platform_data;
348 struct device *dev = ss->pcm->card->dev; 349 struct device *dev = ss->pcm->card->dev;
349 dma_cap_mask_t mask; 350 dma_cap_mask_t mask;
350 struct sh_dmae_slave *param; 351 struct sh_dmae_slave *param;
@@ -381,7 +382,7 @@ static int siu_pcm_open(struct snd_pcm_substream *ss)
381 382
382static int siu_pcm_close(struct snd_pcm_substream *ss) 383static int siu_pcm_close(struct snd_pcm_substream *ss)
383{ 384{
384 struct siu_info *info = siu_i2s_dai.private_data; 385 struct siu_info *info = siu_i2s_data;
385 struct device *dev = ss->pcm->card->dev; 386 struct device *dev = ss->pcm->card->dev;
386 struct siu_port *port_info = siu_port_info(ss); 387 struct siu_port *port_info = siu_port_info(ss);
387 struct siu_stream *siu_stream; 388 struct siu_stream *siu_stream;
@@ -403,7 +404,7 @@ static int siu_pcm_close(struct snd_pcm_substream *ss)
403 404
404static int siu_pcm_prepare(struct snd_pcm_substream *ss) 405static int siu_pcm_prepare(struct snd_pcm_substream *ss)
405{ 406{
406 struct siu_info *info = siu_i2s_dai.private_data; 407 struct siu_info *info = siu_i2s_data;
407 struct siu_port *port_info = siu_port_info(ss); 408 struct siu_port *port_info = siu_port_info(ss);
408 struct device *dev = ss->pcm->card->dev; 409 struct device *dev = ss->pcm->card->dev;
409 struct snd_pcm_runtime *rt = ss->runtime; 410 struct snd_pcm_runtime *rt = ss->runtime;
@@ -449,7 +450,7 @@ static int siu_pcm_prepare(struct snd_pcm_substream *ss)
449 450
450static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd) 451static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
451{ 452{
452 struct siu_info *info = siu_i2s_dai.private_data; 453 struct siu_info *info = siu_i2s_data;
453 struct device *dev = ss->pcm->card->dev; 454 struct device *dev = ss->pcm->card->dev;
454 struct siu_port *port_info = siu_port_info(ss); 455 struct siu_port *port_info = siu_port_info(ss);
455 int ret; 456 int ret;
@@ -492,7 +493,7 @@ static int siu_pcm_trigger(struct snd_pcm_substream *ss, int cmd)
492static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss) 493static snd_pcm_uframes_t siu_pcm_pointer_dma(struct snd_pcm_substream *ss)
493{ 494{
494 struct device *dev = ss->pcm->card->dev; 495 struct device *dev = ss->pcm->card->dev;
495 struct siu_info *info = siu_i2s_dai.private_data; 496 struct siu_info *info = siu_i2s_data;
496 u32 __iomem *base = info->reg; 497 u32 __iomem *base = info->reg;
497 struct siu_port *port_info = siu_port_info(ss); 498 struct siu_port *port_info = siu_port_info(ss);
498 struct snd_pcm_runtime *rt = ss->runtime; 499 struct snd_pcm_runtime *rt = ss->runtime;
@@ -528,7 +529,7 @@ static int siu_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
528 struct snd_pcm *pcm) 529 struct snd_pcm *pcm)
529{ 530{
530 /* card->dev == socdev->dev, see snd_soc_new_pcms() */ 531 /* card->dev == socdev->dev, see snd_soc_new_pcms() */
531 struct siu_info *info = siu_i2s_dai.private_data; 532 struct siu_info *info = siu_i2s_data;
532 struct platform_device *pdev = to_platform_device(card->dev); 533 struct platform_device *pdev = to_platform_device(card->dev);
533 int ret; 534 int ret;
534 int i; 535 int i;
@@ -605,9 +606,8 @@ static struct snd_pcm_ops siu_pcm_ops = {
605 .pointer = siu_pcm_pointer_dma, 606 .pointer = siu_pcm_pointer_dma,
606}; 607};
607 608
608struct snd_soc_platform siu_platform = { 609struct snd_soc_platform_driver siu_platform = {
609 .name = "siu-audio", 610 .ops = &siu_pcm_ops,
610 .pcm_ops = &siu_pcm_ops,
611 .pcm_new = siu_pcm_new, 611 .pcm_new = siu_pcm_new,
612 .pcm_free = siu_pcm_free, 612 .pcm_free = siu_pcm_free,
613}; 613};
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 acc91daa1c55..70d9a7394b2b 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
@@ -227,16 +234,7 @@ static const struct file_operations codec_reg_fops = {
227 234
228static void soc_init_codec_debugfs(struct snd_soc_codec *codec) 235static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
229{ 236{
230 char codec_root[128]; 237 codec->debugfs_codec_root = debugfs_create_dir(codec->name ,
231
232 if (codec->dev)
233 snprintf(codec_root, sizeof(codec_root),
234 "%s.%s", codec->name, dev_name(codec->dev));
235 else
236 snprintf(codec_root, sizeof(codec_root),
237 "%s", codec->name);
238
239 codec->debugfs_codec_root = debugfs_create_dir(codec_root,
240 debugfs_root); 238 debugfs_root);
241 if (!codec->debugfs_codec_root) { 239 if (!codec->debugfs_codec_root) {
242 printk(KERN_WARNING 240 printk(KERN_WARNING
@@ -272,6 +270,106 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
272 debugfs_remove_recursive(codec->debugfs_codec_root); 270 debugfs_remove_recursive(codec->debugfs_codec_root);
273} 271}
274 272
273static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
274 size_t count, loff_t *ppos)
275{
276 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
277 ssize_t len, ret = 0;
278 struct snd_soc_codec *codec;
279
280 if (!buf)
281 return -ENOMEM;
282
283 list_for_each_entry(codec, &codec_list, list) {
284 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
285 codec->name);
286 if (len >= 0)
287 ret += len;
288 if (ret > PAGE_SIZE) {
289 ret = PAGE_SIZE;
290 break;
291 }
292 }
293
294 if (ret >= 0)
295 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
296
297 kfree(buf);
298
299 return ret;
300}
301
302static const struct file_operations codec_list_fops = {
303 .read = codec_list_read_file,
304 .llseek = default_llseek,/* read accesses f_pos */
305};
306
307static ssize_t dai_list_read_file(struct file *file, char __user *user_buf,
308 size_t count, loff_t *ppos)
309{
310 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
311 ssize_t len, ret = 0;
312 struct snd_soc_dai *dai;
313
314 if (!buf)
315 return -ENOMEM;
316
317 list_for_each_entry(dai, &dai_list, list) {
318 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n", dai->name);
319 if (len >= 0)
320 ret += len;
321 if (ret > PAGE_SIZE) {
322 ret = PAGE_SIZE;
323 break;
324 }
325 }
326
327 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
328
329 kfree(buf);
330
331 return ret;
332}
333
334static const struct file_operations dai_list_fops = {
335 .read = dai_list_read_file,
336 .llseek = default_llseek,/* read accesses f_pos */
337};
338
339static ssize_t platform_list_read_file(struct file *file,
340 char __user *user_buf,
341 size_t count, loff_t *ppos)
342{
343 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
344 ssize_t len, ret = 0;
345 struct snd_soc_platform *platform;
346
347 if (!buf)
348 return -ENOMEM;
349
350 list_for_each_entry(platform, &platform_list, list) {
351 len = snprintf(buf + ret, PAGE_SIZE - ret, "%s\n",
352 platform->name);
353 if (len >= 0)
354 ret += len;
355 if (ret > PAGE_SIZE) {
356 ret = PAGE_SIZE;
357 break;
358 }
359 }
360
361 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
362
363 kfree(buf);
364
365 return ret;
366}
367
368static const struct file_operations platform_list_fops = {
369 .read = platform_list_read_file,
370 .llseek = default_llseek,/* read accesses f_pos */
371};
372
275#else 373#else
276 374
277static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) 375static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
@@ -305,7 +403,7 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
305 codec->ac97->dev.release = soc_ac97_device_release; 403 codec->ac97->dev.release = soc_ac97_device_release;
306 404
307 dev_set_name(&codec->ac97->dev, "%d-%d:%s", 405 dev_set_name(&codec->ac97->dev, "%d-%d:%s",
308 codec->card->number, 0, codec->name); 406 codec->card->snd_card->number, 0, codec->name);
309 err = device_register(&codec->ac97->dev); 407 err = device_register(&codec->ac97->dev);
310 if (err < 0) { 408 if (err < 0) {
311 snd_printk(KERN_ERR "Can't register ac97 bus\n"); 409 snd_printk(KERN_ERR "Can't register ac97 bus\n");
@@ -319,24 +417,21 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
319static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream) 417static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
320{ 418{
321 struct snd_soc_pcm_runtime *rtd = substream->private_data; 419 struct snd_soc_pcm_runtime *rtd = substream->private_data;
322 struct snd_soc_device *socdev = rtd->socdev; 420 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
323 struct snd_soc_card *card = socdev->card; 421 struct snd_soc_dai *codec_dai = rtd->codec_dai;
324 struct snd_soc_dai_link *machine = rtd->dai;
325 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
326 struct snd_soc_dai *codec_dai = machine->codec_dai;
327 int ret; 422 int ret;
328 423
329 if (codec_dai->symmetric_rates || cpu_dai->symmetric_rates || 424 if (codec_dai->driver->symmetric_rates || cpu_dai->driver->symmetric_rates ||
330 machine->symmetric_rates) { 425 rtd->dai_link->symmetric_rates) {
331 dev_dbg(card->dev, "Symmetry forces %dHz rate\n", 426 dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n",
332 machine->rate); 427 rtd->rate);
333 428
334 ret = snd_pcm_hw_constraint_minmax(substream->runtime, 429 ret = snd_pcm_hw_constraint_minmax(substream->runtime,
335 SNDRV_PCM_HW_PARAM_RATE, 430 SNDRV_PCM_HW_PARAM_RATE,
336 machine->rate, 431 rtd->rate,
337 machine->rate); 432 rtd->rate);
338 if (ret < 0) { 433 if (ret < 0) {
339 dev_err(card->dev, 434 dev_err(&rtd->dev,
340 "Unable to apply rate symmetry constraint: %d\n", ret); 435 "Unable to apply rate symmetry constraint: %d\n", ret);
341 return ret; 436 return ret;
342 } 437 }
@@ -353,20 +448,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
353static int soc_pcm_open(struct snd_pcm_substream *substream) 448static int soc_pcm_open(struct snd_pcm_substream *substream)
354{ 449{
355 struct snd_soc_pcm_runtime *rtd = substream->private_data; 450 struct snd_soc_pcm_runtime *rtd = substream->private_data;
356 struct snd_soc_device *socdev = rtd->socdev;
357 struct snd_soc_card *card = socdev->card;
358 struct snd_pcm_runtime *runtime = substream->runtime; 451 struct snd_pcm_runtime *runtime = substream->runtime;
359 struct snd_soc_dai_link *machine = rtd->dai; 452 struct snd_soc_platform *platform = rtd->platform;
360 struct snd_soc_platform *platform = card->platform; 453 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
361 struct snd_soc_dai *cpu_dai = machine->cpu_dai; 454 struct snd_soc_dai *codec_dai = rtd->codec_dai;
362 struct snd_soc_dai *codec_dai = machine->codec_dai; 455 struct snd_soc_dai_driver *cpu_dai_drv = cpu_dai->driver;
456 struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
363 int ret = 0; 457 int ret = 0;
364 458
365 mutex_lock(&pcm_mutex); 459 mutex_lock(&pcm_mutex);
366 460
367 /* startup the audio subsystem */ 461 /* startup the audio subsystem */
368 if (cpu_dai->ops->startup) { 462 if (cpu_dai->driver->ops->startup) {
369 ret = cpu_dai->ops->startup(substream, cpu_dai); 463 ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
370 if (ret < 0) { 464 if (ret < 0) {
371 printk(KERN_ERR "asoc: can't open interface %s\n", 465 printk(KERN_ERR "asoc: can't open interface %s\n",
372 cpu_dai->name); 466 cpu_dai->name);
@@ -374,16 +468,16 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
374 } 468 }
375 } 469 }
376 470
377 if (platform->pcm_ops->open) { 471 if (platform->driver->ops->open) {
378 ret = platform->pcm_ops->open(substream); 472 ret = platform->driver->ops->open(substream);
379 if (ret < 0) { 473 if (ret < 0) {
380 printk(KERN_ERR "asoc: can't open platform %s\n", platform->name); 474 printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
381 goto platform_err; 475 goto platform_err;
382 } 476 }
383 } 477 }
384 478
385 if (codec_dai->ops->startup) { 479 if (codec_dai->driver->ops->startup) {
386 ret = codec_dai->ops->startup(substream, codec_dai); 480 ret = codec_dai->driver->ops->startup(substream, codec_dai);
387 if (ret < 0) { 481 if (ret < 0) {
388 printk(KERN_ERR "asoc: can't open codec %s\n", 482 printk(KERN_ERR "asoc: can't open codec %s\n",
389 codec_dai->name); 483 codec_dai->name);
@@ -391,10 +485,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
391 } 485 }
392 } 486 }
393 487
394 if (machine->ops && machine->ops->startup) { 488 if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
395 ret = machine->ops->startup(substream); 489 ret = rtd->dai_link->ops->startup(substream);
396 if (ret < 0) { 490 if (ret < 0) {
397 printk(KERN_ERR "asoc: %s startup failed\n", machine->name); 491 printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
398 goto machine_err; 492 goto machine_err;
399 } 493 }
400 } 494 }
@@ -402,50 +496,50 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
402 /* Check that the codec and cpu DAI's are compatible */ 496 /* Check that the codec and cpu DAI's are compatible */
403 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 497 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
404 runtime->hw.rate_min = 498 runtime->hw.rate_min =
405 max(codec_dai->playback.rate_min, 499 max(codec_dai_drv->playback.rate_min,
406 cpu_dai->playback.rate_min); 500 cpu_dai_drv->playback.rate_min);
407 runtime->hw.rate_max = 501 runtime->hw.rate_max =
408 min(codec_dai->playback.rate_max, 502 min(codec_dai_drv->playback.rate_max,
409 cpu_dai->playback.rate_max); 503 cpu_dai_drv->playback.rate_max);
410 runtime->hw.channels_min = 504 runtime->hw.channels_min =
411 max(codec_dai->playback.channels_min, 505 max(codec_dai_drv->playback.channels_min,
412 cpu_dai->playback.channels_min); 506 cpu_dai_drv->playback.channels_min);
413 runtime->hw.channels_max = 507 runtime->hw.channels_max =
414 min(codec_dai->playback.channels_max, 508 min(codec_dai_drv->playback.channels_max,
415 cpu_dai->playback.channels_max); 509 cpu_dai_drv->playback.channels_max);
416 runtime->hw.formats = 510 runtime->hw.formats =
417 codec_dai->playback.formats & cpu_dai->playback.formats; 511 codec_dai_drv->playback.formats & cpu_dai_drv->playback.formats;
418 runtime->hw.rates = 512 runtime->hw.rates =
419 codec_dai->playback.rates & cpu_dai->playback.rates; 513 codec_dai_drv->playback.rates & cpu_dai_drv->playback.rates;
420 if (codec_dai->playback.rates 514 if (codec_dai_drv->playback.rates
421 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) 515 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
422 runtime->hw.rates |= cpu_dai->playback.rates; 516 runtime->hw.rates |= cpu_dai_drv->playback.rates;
423 if (cpu_dai->playback.rates 517 if (cpu_dai_drv->playback.rates
424 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) 518 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
425 runtime->hw.rates |= codec_dai->playback.rates; 519 runtime->hw.rates |= codec_dai_drv->playback.rates;
426 } else { 520 } else {
427 runtime->hw.rate_min = 521 runtime->hw.rate_min =
428 max(codec_dai->capture.rate_min, 522 max(codec_dai_drv->capture.rate_min,
429 cpu_dai->capture.rate_min); 523 cpu_dai_drv->capture.rate_min);
430 runtime->hw.rate_max = 524 runtime->hw.rate_max =
431 min(codec_dai->capture.rate_max, 525 min(codec_dai_drv->capture.rate_max,
432 cpu_dai->capture.rate_max); 526 cpu_dai_drv->capture.rate_max);
433 runtime->hw.channels_min = 527 runtime->hw.channels_min =
434 max(codec_dai->capture.channels_min, 528 max(codec_dai_drv->capture.channels_min,
435 cpu_dai->capture.channels_min); 529 cpu_dai_drv->capture.channels_min);
436 runtime->hw.channels_max = 530 runtime->hw.channels_max =
437 min(codec_dai->capture.channels_max, 531 min(codec_dai_drv->capture.channels_max,
438 cpu_dai->capture.channels_max); 532 cpu_dai_drv->capture.channels_max);
439 runtime->hw.formats = 533 runtime->hw.formats =
440 codec_dai->capture.formats & cpu_dai->capture.formats; 534 codec_dai_drv->capture.formats & cpu_dai_drv->capture.formats;
441 runtime->hw.rates = 535 runtime->hw.rates =
442 codec_dai->capture.rates & cpu_dai->capture.rates; 536 codec_dai_drv->capture.rates & cpu_dai_drv->capture.rates;
443 if (codec_dai->capture.rates 537 if (codec_dai_drv->capture.rates
444 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) 538 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
445 runtime->hw.rates |= cpu_dai->capture.rates; 539 runtime->hw.rates |= cpu_dai_drv->capture.rates;
446 if (cpu_dai->capture.rates 540 if (cpu_dai_drv->capture.rates
447 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS)) 541 & (SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_CONTINUOUS))
448 runtime->hw.rates |= codec_dai->capture.rates; 542 runtime->hw.rates |= codec_dai_drv->capture.rates;
449 } 543 }
450 544
451 snd_pcm_limit_hw_rates(runtime); 545 snd_pcm_limit_hw_rates(runtime);
@@ -461,7 +555,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
461 } 555 }
462 if (!runtime->hw.channels_min || !runtime->hw.channels_max) { 556 if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
463 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", 557 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
464 codec_dai->name, cpu_dai->name); 558 codec_dai->name, cpu_dai->name);
465 goto config_err; 559 goto config_err;
466 } 560 }
467 561
@@ -472,7 +566,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
472 goto config_err; 566 goto config_err;
473 } 567 }
474 568
475 pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); 569 pr_debug("asoc: %s <-> %s info:\n",
570 codec_dai->name, cpu_dai->name);
476 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); 571 pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
477 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, 572 pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
478 runtime->hw.channels_max); 573 runtime->hw.channels_max);
@@ -480,33 +575,33 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
480 runtime->hw.rate_max); 575 runtime->hw.rate_max);
481 576
482 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 577 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
483 cpu_dai->playback.active++; 578 cpu_dai->playback_active++;
484 codec_dai->playback.active++; 579 codec_dai->playback_active++;
485 } else { 580 } else {
486 cpu_dai->capture.active++; 581 cpu_dai->capture_active++;
487 codec_dai->capture.active++; 582 codec_dai->capture_active++;
488 } 583 }
489 cpu_dai->active++; 584 cpu_dai->active++;
490 codec_dai->active++; 585 codec_dai->active++;
491 card->codec->active++; 586 rtd->codec->active++;
492 mutex_unlock(&pcm_mutex); 587 mutex_unlock(&pcm_mutex);
493 return 0; 588 return 0;
494 589
495config_err: 590config_err:
496 if (machine->ops && machine->ops->shutdown) 591 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
497 machine->ops->shutdown(substream); 592 rtd->dai_link->ops->shutdown(substream);
498 593
499machine_err: 594machine_err:
500 if (codec_dai->ops->shutdown) 595 if (codec_dai->driver->ops->shutdown)
501 codec_dai->ops->shutdown(substream, codec_dai); 596 codec_dai->driver->ops->shutdown(substream, codec_dai);
502 597
503codec_dai_err: 598codec_dai_err:
504 if (platform->pcm_ops->close) 599 if (platform->driver->ops->close)
505 platform->pcm_ops->close(substream); 600 platform->driver->ops->close(substream);
506 601
507platform_err: 602platform_err:
508 if (cpu_dai->ops->shutdown) 603 if (cpu_dai->driver->ops->shutdown)
509 cpu_dai->ops->shutdown(substream, cpu_dai); 604 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
510out: 605out:
511 mutex_unlock(&pcm_mutex); 606 mutex_unlock(&pcm_mutex);
512 return ret; 607 return ret;
@@ -519,29 +614,25 @@ out:
519 */ 614 */
520static void close_delayed_work(struct work_struct *work) 615static void close_delayed_work(struct work_struct *work)
521{ 616{
522 struct snd_soc_card *card = container_of(work, struct snd_soc_card, 617 struct snd_soc_pcm_runtime *rtd =
523 delayed_work.work); 618 container_of(work, struct snd_soc_pcm_runtime, delayed_work.work);
524 struct snd_soc_codec *codec = card->codec; 619 struct snd_soc_dai *codec_dai = rtd->codec_dai;
525 struct snd_soc_dai *codec_dai;
526 int i;
527 620
528 mutex_lock(&pcm_mutex); 621 mutex_lock(&pcm_mutex);
529 for (i = 0; i < codec->num_dai; i++) { 622
530 codec_dai = &codec->dai[i]; 623 pr_debug("pop wq checking: %s status: %s waiting: %s\n",
531 624 codec_dai->driver->playback.stream_name,
532 pr_debug("pop wq checking: %s status: %s waiting: %s\n", 625 codec_dai->playback_active ? "active" : "inactive",
533 codec_dai->playback.stream_name, 626 codec_dai->pop_wait ? "yes" : "no");
534 codec_dai->playback.active ? "active" : "inactive", 627
535 codec_dai->pop_wait ? "yes" : "no"); 628 /* are we waiting on this codec DAI stream */
536 629 if (codec_dai->pop_wait == 1) {
537 /* are we waiting on this codec DAI stream */ 630 codec_dai->pop_wait = 0;
538 if (codec_dai->pop_wait == 1) { 631 snd_soc_dapm_stream_event(rtd,
539 codec_dai->pop_wait = 0; 632 codec_dai->driver->playback.stream_name,
540 snd_soc_dapm_stream_event(codec, 633 SND_SOC_DAPM_STREAM_STOP);
541 codec_dai->playback.stream_name,
542 SND_SOC_DAPM_STREAM_STOP);
543 }
544 } 634 }
635
545 mutex_unlock(&pcm_mutex); 636 mutex_unlock(&pcm_mutex);
546} 637}
547 638
@@ -553,22 +644,19 @@ static void close_delayed_work(struct work_struct *work)
553static int soc_codec_close(struct snd_pcm_substream *substream) 644static int soc_codec_close(struct snd_pcm_substream *substream)
554{ 645{
555 struct snd_soc_pcm_runtime *rtd = substream->private_data; 646 struct snd_soc_pcm_runtime *rtd = substream->private_data;
556 struct snd_soc_device *socdev = rtd->socdev; 647 struct snd_soc_platform *platform = rtd->platform;
557 struct snd_soc_card *card = socdev->card; 648 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
558 struct snd_soc_dai_link *machine = rtd->dai; 649 struct snd_soc_dai *codec_dai = rtd->codec_dai;
559 struct snd_soc_platform *platform = card->platform; 650 struct snd_soc_codec *codec = rtd->codec;
560 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
561 struct snd_soc_dai *codec_dai = machine->codec_dai;
562 struct snd_soc_codec *codec = card->codec;
563 651
564 mutex_lock(&pcm_mutex); 652 mutex_lock(&pcm_mutex);
565 653
566 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 654 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
567 cpu_dai->playback.active--; 655 cpu_dai->playback_active--;
568 codec_dai->playback.active--; 656 codec_dai->playback_active--;
569 } else { 657 } else {
570 cpu_dai->capture.active--; 658 cpu_dai->capture_active--;
571 codec_dai->capture.active--; 659 codec_dai->capture_active--;
572 } 660 }
573 661
574 cpu_dai->active--; 662 cpu_dai->active--;
@@ -581,27 +669,28 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
581 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 669 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
582 snd_soc_dai_digital_mute(codec_dai, 1); 670 snd_soc_dai_digital_mute(codec_dai, 1);
583 671
584 if (cpu_dai->ops->shutdown) 672 if (cpu_dai->driver->ops->shutdown)
585 cpu_dai->ops->shutdown(substream, cpu_dai); 673 cpu_dai->driver->ops->shutdown(substream, cpu_dai);
586 674
587 if (codec_dai->ops->shutdown) 675 if (codec_dai->driver->ops->shutdown)
588 codec_dai->ops->shutdown(substream, codec_dai); 676 codec_dai->driver->ops->shutdown(substream, codec_dai);
589 677
590 if (machine->ops && machine->ops->shutdown) 678 if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
591 machine->ops->shutdown(substream); 679 rtd->dai_link->ops->shutdown(substream);
592 680
593 if (platform->pcm_ops->close) 681 if (platform->driver->ops->close)
594 platform->pcm_ops->close(substream); 682 platform->driver->ops->close(substream);
683 cpu_dai->runtime = NULL;
595 684
596 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 685 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
597 /* start delayed pop wq here for playback streams */ 686 /* start delayed pop wq here for playback streams */
598 codec_dai->pop_wait = 1; 687 codec_dai->pop_wait = 1;
599 schedule_delayed_work(&card->delayed_work, 688 schedule_delayed_work(&rtd->delayed_work,
600 msecs_to_jiffies(card->pmdown_time)); 689 msecs_to_jiffies(rtd->pmdown_time));
601 } else { 690 } else {
602 /* capture streams can be powered down now */ 691 /* capture streams can be powered down now */
603 snd_soc_dapm_stream_event(codec, 692 snd_soc_dapm_stream_event(rtd,
604 codec_dai->capture.stream_name, 693 codec_dai->driver->capture.stream_name,
605 SND_SOC_DAPM_STREAM_STOP); 694 SND_SOC_DAPM_STREAM_STOP);
606 } 695 }
607 696
@@ -617,43 +706,39 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
617static int soc_pcm_prepare(struct snd_pcm_substream *substream) 706static int soc_pcm_prepare(struct snd_pcm_substream *substream)
618{ 707{
619 struct snd_soc_pcm_runtime *rtd = substream->private_data; 708 struct snd_soc_pcm_runtime *rtd = substream->private_data;
620 struct snd_soc_device *socdev = rtd->socdev; 709 struct snd_soc_platform *platform = rtd->platform;
621 struct snd_soc_card *card = socdev->card; 710 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
622 struct snd_soc_dai_link *machine = rtd->dai; 711 struct snd_soc_dai *codec_dai = rtd->codec_dai;
623 struct snd_soc_platform *platform = card->platform;
624 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
625 struct snd_soc_dai *codec_dai = machine->codec_dai;
626 struct snd_soc_codec *codec = card->codec;
627 int ret = 0; 712 int ret = 0;
628 713
629 mutex_lock(&pcm_mutex); 714 mutex_lock(&pcm_mutex);
630 715
631 if (machine->ops && machine->ops->prepare) { 716 if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
632 ret = machine->ops->prepare(substream); 717 ret = rtd->dai_link->ops->prepare(substream);
633 if (ret < 0) { 718 if (ret < 0) {
634 printk(KERN_ERR "asoc: machine prepare error\n"); 719 printk(KERN_ERR "asoc: machine prepare error\n");
635 goto out; 720 goto out;
636 } 721 }
637 } 722 }
638 723
639 if (platform->pcm_ops->prepare) { 724 if (platform->driver->ops->prepare) {
640 ret = platform->pcm_ops->prepare(substream); 725 ret = platform->driver->ops->prepare(substream);
641 if (ret < 0) { 726 if (ret < 0) {
642 printk(KERN_ERR "asoc: platform prepare error\n"); 727 printk(KERN_ERR "asoc: platform prepare error\n");
643 goto out; 728 goto out;
644 } 729 }
645 } 730 }
646 731
647 if (codec_dai->ops->prepare) { 732 if (codec_dai->driver->ops->prepare) {
648 ret = codec_dai->ops->prepare(substream, codec_dai); 733 ret = codec_dai->driver->ops->prepare(substream, codec_dai);
649 if (ret < 0) { 734 if (ret < 0) {
650 printk(KERN_ERR "asoc: codec DAI prepare error\n"); 735 printk(KERN_ERR "asoc: codec DAI prepare error\n");
651 goto out; 736 goto out;
652 } 737 }
653 } 738 }
654 739
655 if (cpu_dai->ops->prepare) { 740 if (cpu_dai->driver->ops->prepare) {
656 ret = cpu_dai->ops->prepare(substream, cpu_dai); 741 ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
657 if (ret < 0) { 742 if (ret < 0) {
658 printk(KERN_ERR "asoc: cpu DAI prepare error\n"); 743 printk(KERN_ERR "asoc: cpu DAI prepare error\n");
659 goto out; 744 goto out;
@@ -664,16 +749,16 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
664 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 749 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
665 codec_dai->pop_wait) { 750 codec_dai->pop_wait) {
666 codec_dai->pop_wait = 0; 751 codec_dai->pop_wait = 0;
667 cancel_delayed_work(&card->delayed_work); 752 cancel_delayed_work(&rtd->delayed_work);
668 } 753 }
669 754
670 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 755 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
671 snd_soc_dapm_stream_event(codec, 756 snd_soc_dapm_stream_event(rtd,
672 codec_dai->playback.stream_name, 757 codec_dai->driver->playback.stream_name,
673 SND_SOC_DAPM_STREAM_START); 758 SND_SOC_DAPM_STREAM_START);
674 else 759 else
675 snd_soc_dapm_stream_event(codec, 760 snd_soc_dapm_stream_event(rtd,
676 codec_dai->capture.stream_name, 761 codec_dai->driver->capture.stream_name,
677 SND_SOC_DAPM_STREAM_START); 762 SND_SOC_DAPM_STREAM_START);
678 763
679 snd_soc_dai_digital_mute(codec_dai, 0); 764 snd_soc_dai_digital_mute(codec_dai, 0);
@@ -692,26 +777,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
692 struct snd_pcm_hw_params *params) 777 struct snd_pcm_hw_params *params)
693{ 778{
694 struct snd_soc_pcm_runtime *rtd = substream->private_data; 779 struct snd_soc_pcm_runtime *rtd = substream->private_data;
695 struct snd_soc_device *socdev = rtd->socdev; 780 struct snd_soc_platform *platform = rtd->platform;
696 struct snd_soc_dai_link *machine = rtd->dai; 781 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
697 struct snd_soc_card *card = socdev->card; 782 struct snd_soc_dai *codec_dai = rtd->codec_dai;
698 struct snd_soc_platform *platform = card->platform;
699 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
700 struct snd_soc_dai *codec_dai = machine->codec_dai;
701 int ret = 0; 783 int ret = 0;
702 784
703 mutex_lock(&pcm_mutex); 785 mutex_lock(&pcm_mutex);
704 786
705 if (machine->ops && machine->ops->hw_params) { 787 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
706 ret = machine->ops->hw_params(substream, params); 788 ret = rtd->dai_link->ops->hw_params(substream, params);
707 if (ret < 0) { 789 if (ret < 0) {
708 printk(KERN_ERR "asoc: machine hw_params failed\n"); 790 printk(KERN_ERR "asoc: machine hw_params failed\n");
709 goto out; 791 goto out;
710 } 792 }
711 } 793 }
712 794
713 if (codec_dai->ops->hw_params) { 795 if (codec_dai->driver->ops->hw_params) {
714 ret = codec_dai->ops->hw_params(substream, params, codec_dai); 796 ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
715 if (ret < 0) { 797 if (ret < 0) {
716 printk(KERN_ERR "asoc: can't set codec %s hw params\n", 798 printk(KERN_ERR "asoc: can't set codec %s hw params\n",
717 codec_dai->name); 799 codec_dai->name);
@@ -719,8 +801,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
719 } 801 }
720 } 802 }
721 803
722 if (cpu_dai->ops->hw_params) { 804 if (cpu_dai->driver->ops->hw_params) {
723 ret = cpu_dai->ops->hw_params(substream, params, cpu_dai); 805 ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
724 if (ret < 0) { 806 if (ret < 0) {
725 printk(KERN_ERR "asoc: interface %s hw params failed\n", 807 printk(KERN_ERR "asoc: interface %s hw params failed\n",
726 cpu_dai->name); 808 cpu_dai->name);
@@ -728,8 +810,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
728 } 810 }
729 } 811 }
730 812
731 if (platform->pcm_ops->hw_params) { 813 if (platform->driver->ops->hw_params) {
732 ret = platform->pcm_ops->hw_params(substream, params); 814 ret = platform->driver->ops->hw_params(substream, params);
733 if (ret < 0) { 815 if (ret < 0) {
734 printk(KERN_ERR "asoc: platform %s hw params failed\n", 816 printk(KERN_ERR "asoc: platform %s hw params failed\n",
735 platform->name); 817 platform->name);
@@ -737,23 +819,23 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
737 } 819 }
738 } 820 }
739 821
740 machine->rate = params_rate(params); 822 rtd->rate = params_rate(params);
741 823
742out: 824out:
743 mutex_unlock(&pcm_mutex); 825 mutex_unlock(&pcm_mutex);
744 return ret; 826 return ret;
745 827
746platform_err: 828platform_err:
747 if (cpu_dai->ops->hw_free) 829 if (cpu_dai->driver->ops->hw_free)
748 cpu_dai->ops->hw_free(substream, cpu_dai); 830 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
749 831
750interface_err: 832interface_err:
751 if (codec_dai->ops->hw_free) 833 if (codec_dai->driver->ops->hw_free)
752 codec_dai->ops->hw_free(substream, codec_dai); 834 codec_dai->driver->ops->hw_free(substream, codec_dai);
753 835
754codec_err: 836codec_err:
755 if (machine->ops && machine->ops->hw_free) 837 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
756 machine->ops->hw_free(substream); 838 rtd->dai_link->ops->hw_free(substream);
757 839
758 mutex_unlock(&pcm_mutex); 840 mutex_unlock(&pcm_mutex);
759 return ret; 841 return ret;
@@ -765,13 +847,10 @@ codec_err:
765static int soc_pcm_hw_free(struct snd_pcm_substream *substream) 847static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
766{ 848{
767 struct snd_soc_pcm_runtime *rtd = substream->private_data; 849 struct snd_soc_pcm_runtime *rtd = substream->private_data;
768 struct snd_soc_device *socdev = rtd->socdev; 850 struct snd_soc_platform *platform = rtd->platform;
769 struct snd_soc_dai_link *machine = rtd->dai; 851 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
770 struct snd_soc_card *card = socdev->card; 852 struct snd_soc_dai *codec_dai = rtd->codec_dai;
771 struct snd_soc_platform *platform = card->platform; 853 struct snd_soc_codec *codec = rtd->codec;
772 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
773 struct snd_soc_dai *codec_dai = machine->codec_dai;
774 struct snd_soc_codec *codec = card->codec;
775 854
776 mutex_lock(&pcm_mutex); 855 mutex_lock(&pcm_mutex);
777 856
@@ -780,19 +859,19 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
780 snd_soc_dai_digital_mute(codec_dai, 1); 859 snd_soc_dai_digital_mute(codec_dai, 1);
781 860
782 /* free any machine hw params */ 861 /* free any machine hw params */
783 if (machine->ops && machine->ops->hw_free) 862 if (rtd->dai_link->ops && rtd->dai_link->ops->hw_free)
784 machine->ops->hw_free(substream); 863 rtd->dai_link->ops->hw_free(substream);
785 864
786 /* free any DMA resources */ 865 /* free any DMA resources */
787 if (platform->pcm_ops->hw_free) 866 if (platform->driver->ops->hw_free)
788 platform->pcm_ops->hw_free(substream); 867 platform->driver->ops->hw_free(substream);
789 868
790 /* now free hw params for the DAI's */ 869 /* now free hw params for the DAI's */
791 if (codec_dai->ops->hw_free) 870 if (codec_dai->driver->ops->hw_free)
792 codec_dai->ops->hw_free(substream, codec_dai); 871 codec_dai->driver->ops->hw_free(substream, codec_dai);
793 872
794 if (cpu_dai->ops->hw_free) 873 if (cpu_dai->driver->ops->hw_free)
795 cpu_dai->ops->hw_free(substream, cpu_dai); 874 cpu_dai->driver->ops->hw_free(substream, cpu_dai);
796 875
797 mutex_unlock(&pcm_mutex); 876 mutex_unlock(&pcm_mutex);
798 return 0; 877 return 0;
@@ -801,28 +880,25 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
801static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 880static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
802{ 881{
803 struct snd_soc_pcm_runtime *rtd = substream->private_data; 882 struct snd_soc_pcm_runtime *rtd = substream->private_data;
804 struct snd_soc_device *socdev = rtd->socdev; 883 struct snd_soc_platform *platform = rtd->platform;
805 struct snd_soc_card *card= socdev->card; 884 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
806 struct snd_soc_dai_link *machine = rtd->dai; 885 struct snd_soc_dai *codec_dai = rtd->codec_dai;
807 struct snd_soc_platform *platform = card->platform;
808 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
809 struct snd_soc_dai *codec_dai = machine->codec_dai;
810 int ret; 886 int ret;
811 887
812 if (codec_dai->ops->trigger) { 888 if (codec_dai->driver->ops->trigger) {
813 ret = codec_dai->ops->trigger(substream, cmd, codec_dai); 889 ret = codec_dai->driver->ops->trigger(substream, cmd, codec_dai);
814 if (ret < 0) 890 if (ret < 0)
815 return ret; 891 return ret;
816 } 892 }
817 893
818 if (platform->pcm_ops->trigger) { 894 if (platform->driver->ops->trigger) {
819 ret = platform->pcm_ops->trigger(substream, cmd); 895 ret = platform->driver->ops->trigger(substream, cmd);
820 if (ret < 0) 896 if (ret < 0)
821 return ret; 897 return ret;
822 } 898 }
823 899
824 if (cpu_dai->ops->trigger) { 900 if (cpu_dai->driver->ops->trigger) {
825 ret = cpu_dai->ops->trigger(substream, cmd, cpu_dai); 901 ret = cpu_dai->driver->ops->trigger(substream, cmd, cpu_dai);
826 if (ret < 0) 902 if (ret < 0)
827 return ret; 903 return ret;
828 } 904 }
@@ -837,27 +913,24 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
837static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream) 913static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
838{ 914{
839 struct snd_soc_pcm_runtime *rtd = substream->private_data; 915 struct snd_soc_pcm_runtime *rtd = substream->private_data;
840 struct snd_soc_device *socdev = rtd->socdev; 916 struct snd_soc_platform *platform = rtd->platform;
841 struct snd_soc_card *card = socdev->card; 917 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
842 struct snd_soc_platform *platform = card->platform; 918 struct snd_soc_dai *codec_dai = rtd->codec_dai;
843 struct snd_soc_dai_link *machine = rtd->dai;
844 struct snd_soc_dai *cpu_dai = machine->cpu_dai;
845 struct snd_soc_dai *codec_dai = machine->codec_dai;
846 struct snd_pcm_runtime *runtime = substream->runtime; 919 struct snd_pcm_runtime *runtime = substream->runtime;
847 snd_pcm_uframes_t offset = 0; 920 snd_pcm_uframes_t offset = 0;
848 snd_pcm_sframes_t delay = 0; 921 snd_pcm_sframes_t delay = 0;
849 922
850 if (platform->pcm_ops->pointer) 923 if (platform->driver->ops->pointer)
851 offset = platform->pcm_ops->pointer(substream); 924 offset = platform->driver->ops->pointer(substream);
852 925
853 if (cpu_dai->ops->delay) 926 if (cpu_dai->driver->ops->delay)
854 delay += cpu_dai->ops->delay(substream, cpu_dai); 927 delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
855 928
856 if (codec_dai->ops->delay) 929 if (codec_dai->driver->ops->delay)
857 delay += codec_dai->ops->delay(substream, codec_dai); 930 delay += codec_dai->driver->ops->delay(substream, codec_dai);
858 931
859 if (platform->delay) 932 if (platform->driver->delay)
860 delay += platform->delay(substream, codec_dai); 933 delay += platform->driver->delay(substream, codec_dai);
861 934
862 runtime->delay = delay; 935 runtime->delay = delay;
863 936
@@ -880,104 +953,111 @@ static struct snd_pcm_ops soc_pcm_ops = {
880static int soc_suspend(struct device *dev) 953static int soc_suspend(struct device *dev)
881{ 954{
882 struct platform_device *pdev = to_platform_device(dev); 955 struct platform_device *pdev = to_platform_device(dev);
883 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 956 struct snd_soc_card *card = platform_get_drvdata(pdev);
884 struct snd_soc_card *card = socdev->card;
885 struct snd_soc_platform *platform = card->platform;
886 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
887 struct snd_soc_codec *codec = card->codec;
888 int i; 957 int i;
889 958
890 /* If the initialization of this soc device failed, there is no codec 959 /* If the initialization of this soc device failed, there is no codec
891 * associated with it. Just bail out in this case. 960 * associated with it. Just bail out in this case.
892 */ 961 */
893 if (!codec) 962 if (list_empty(&card->codec_dev_list))
894 return 0; 963 return 0;
895 964
896 /* Due to the resume being scheduled into a workqueue we could 965 /* Due to the resume being scheduled into a workqueue we could
897 * suspend before that's finished - wait for it to complete. 966 * suspend before that's finished - wait for it to complete.
898 */ 967 */
899 snd_power_lock(codec->card); 968 snd_power_lock(card->snd_card);
900 snd_power_wait(codec->card, SNDRV_CTL_POWER_D0); 969 snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0);
901 snd_power_unlock(codec->card); 970 snd_power_unlock(card->snd_card);
902 971
903 /* we're going to block userspace touching us until resume completes */ 972 /* we're going to block userspace touching us until resume completes */
904 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); 973 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);
905 974
906 /* mute any active DAC's */ 975 /* mute any active DAC's */
907 for (i = 0; i < card->num_links; i++) { 976 for (i = 0; i < card->num_rtd; i++) {
908 struct snd_soc_dai *dai = card->dai_link[i].codec_dai; 977 struct snd_soc_dai *dai = card->rtd[i].codec_dai;
978 struct snd_soc_dai_driver *drv = dai->driver;
909 979
910 if (card->dai_link[i].ignore_suspend) 980 if (card->rtd[i].dai_link->ignore_suspend)
911 continue; 981 continue;
912 982
913 if (dai->ops->digital_mute && dai->playback.active) 983 if (drv->ops->digital_mute && dai->playback_active)
914 dai->ops->digital_mute(dai, 1); 984 drv->ops->digital_mute(dai, 1);
915 } 985 }
916 986
917 /* suspend all pcms */ 987 /* suspend all pcms */
918 for (i = 0; i < card->num_links; i++) { 988 for (i = 0; i < card->num_rtd; i++) {
919 if (card->dai_link[i].ignore_suspend) 989 if (card->rtd[i].dai_link->ignore_suspend)
920 continue; 990 continue;
921 991
922 snd_pcm_suspend_all(card->dai_link[i].pcm); 992 snd_pcm_suspend_all(card->rtd[i].pcm);
923 } 993 }
924 994
925 if (card->suspend_pre) 995 if (card->suspend_pre)
926 card->suspend_pre(pdev, PMSG_SUSPEND); 996 card->suspend_pre(pdev, PMSG_SUSPEND);
927 997
928 for (i = 0; i < card->num_links; i++) { 998 for (i = 0; i < card->num_rtd; i++) {
929 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 999 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
1000 struct snd_soc_platform *platform = card->rtd[i].platform;
930 1001
931 if (card->dai_link[i].ignore_suspend) 1002 if (card->rtd[i].dai_link->ignore_suspend)
932 continue; 1003 continue;
933 1004
934 if (cpu_dai->suspend && !cpu_dai->ac97_control) 1005 if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control)
935 cpu_dai->suspend(cpu_dai); 1006 cpu_dai->driver->suspend(cpu_dai);
936 if (platform->suspend) 1007 if (platform->driver->suspend && !platform->suspended) {
937 platform->suspend(&card->dai_link[i]); 1008 platform->driver->suspend(cpu_dai);
1009 platform->suspended = 1;
1010 }
938 } 1011 }
939 1012
940 /* close any waiting streams and save state */ 1013 /* close any waiting streams and save state */
941 run_delayed_work(&card->delayed_work); 1014 for (i = 0; i < card->num_rtd; i++) {
942 codec->suspend_bias_level = codec->bias_level; 1015 run_delayed_work(&card->rtd[i].delayed_work);
1016 card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level;
1017 }
943 1018
944 for (i = 0; i < codec->num_dai; i++) { 1019 for (i = 0; i < card->num_rtd; i++) {
945 char *stream = codec->dai[i].playback.stream_name; 1020 struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
946 1021
947 if (card->dai_link[i].ignore_suspend) 1022 if (card->rtd[i].dai_link->ignore_suspend)
948 continue; 1023 continue;
949 1024
950 if (stream != NULL) 1025 if (driver->playback.stream_name != NULL)
951 snd_soc_dapm_stream_event(codec, stream, 1026 snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
952 SND_SOC_DAPM_STREAM_SUSPEND); 1027 SND_SOC_DAPM_STREAM_SUSPEND);
953 stream = codec->dai[i].capture.stream_name; 1028
954 if (stream != NULL) 1029 if (driver->capture.stream_name != NULL)
955 snd_soc_dapm_stream_event(codec, stream, 1030 snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
956 SND_SOC_DAPM_STREAM_SUSPEND); 1031 SND_SOC_DAPM_STREAM_SUSPEND);
957 } 1032 }
958 1033
959 /* If there are paths active then the CODEC will be held with 1034 /* suspend all CODECs */
960 * bias _ON and should not be suspended. */ 1035 for (i = 0; i < card->num_rtd; i++) {
961 if (codec_dev->suspend) { 1036 struct snd_soc_codec *codec = card->rtd[i].codec;
962 switch (codec->bias_level) { 1037 /* If there are paths active then the CODEC will be held with
963 case SND_SOC_BIAS_STANDBY: 1038 * bias _ON and should not be suspended. */
964 case SND_SOC_BIAS_OFF: 1039 if (!codec->suspended && codec->driver->suspend) {
965 codec_dev->suspend(pdev, PMSG_SUSPEND); 1040 switch (codec->bias_level) {
966 break; 1041 case SND_SOC_BIAS_STANDBY:
967 default: 1042 case SND_SOC_BIAS_OFF:
968 dev_dbg(socdev->dev, "CODEC is on over suspend\n"); 1043 codec->driver->suspend(codec, PMSG_SUSPEND);
969 break; 1044 codec->suspended = 1;
1045 break;
1046 default:
1047 dev_dbg(codec->dev, "CODEC is on over suspend\n");
1048 break;
1049 }
970 } 1050 }
971 } 1051 }
972 1052
973 for (i = 0; i < card->num_links; i++) { 1053 for (i = 0; i < card->num_rtd; i++) {
974 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1054 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
975 1055
976 if (card->dai_link[i].ignore_suspend) 1056 if (card->rtd[i].dai_link->ignore_suspend)
977 continue; 1057 continue;
978 1058
979 if (cpu_dai->suspend && cpu_dai->ac97_control) 1059 if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control)
980 cpu_dai->suspend(cpu_dai); 1060 cpu_dai->driver->suspend(cpu_dai);
981 } 1061 }
982 1062
983 if (card->suspend_post) 1063 if (card->suspend_post)
@@ -991,127 +1071,127 @@ static int soc_suspend(struct device *dev)
991 */ 1071 */
992static void soc_resume_deferred(struct work_struct *work) 1072static void soc_resume_deferred(struct work_struct *work)
993{ 1073{
994 struct snd_soc_card *card = container_of(work, 1074 struct snd_soc_card *card =
995 struct snd_soc_card, 1075 container_of(work, struct snd_soc_card, deferred_resume_work);
996 deferred_resume_work); 1076 struct platform_device *pdev = to_platform_device(card->dev);
997 struct snd_soc_device *socdev = card->socdev;
998 struct snd_soc_platform *platform = card->platform;
999 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
1000 struct snd_soc_codec *codec = card->codec;
1001 struct platform_device *pdev = to_platform_device(socdev->dev);
1002 int i; 1077 int i;
1003 1078
1004 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, 1079 /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time,
1005 * so userspace apps are blocked from touching us 1080 * so userspace apps are blocked from touching us
1006 */ 1081 */
1007 1082
1008 dev_dbg(socdev->dev, "starting resume work\n"); 1083 dev_dbg(card->dev, "starting resume work\n");
1009 1084
1010 /* Bring us up into D2 so that DAPM starts enabling things */ 1085 /* Bring us up into D2 so that DAPM starts enabling things */
1011 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D2); 1086 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D2);
1012 1087
1013 if (card->resume_pre) 1088 if (card->resume_pre)
1014 card->resume_pre(pdev); 1089 card->resume_pre(pdev);
1015 1090
1016 for (i = 0; i < card->num_links; i++) { 1091 /* resume AC97 DAIs */
1017 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1092 for (i = 0; i < card->num_rtd; i++) {
1093 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
1018 1094
1019 if (card->dai_link[i].ignore_suspend) 1095 if (card->rtd[i].dai_link->ignore_suspend)
1020 continue; 1096 continue;
1021 1097
1022 if (cpu_dai->resume && cpu_dai->ac97_control) 1098 if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control)
1023 cpu_dai->resume(cpu_dai); 1099 cpu_dai->driver->resume(cpu_dai);
1024 } 1100 }
1025 1101
1026 /* If the CODEC was idle over suspend then it will have been 1102 for (i = 0; i < card->num_rtd; i++) {
1027 * left with bias OFF or STANDBY and suspended so we must now 1103 struct snd_soc_codec *codec = card->rtd[i].codec;
1028 * resume. Otherwise the suspend was suppressed. 1104 /* If the CODEC was idle over suspend then it will have been
1029 */ 1105 * left with bias OFF or STANDBY and suspended so we must now
1030 if (codec_dev->resume) { 1106 * resume. Otherwise the suspend was suppressed.
1031 switch (codec->bias_level) { 1107 */
1032 case SND_SOC_BIAS_STANDBY: 1108 if (codec->driver->resume && codec->suspended) {
1033 case SND_SOC_BIAS_OFF: 1109 switch (codec->bias_level) {
1034 codec_dev->resume(pdev); 1110 case SND_SOC_BIAS_STANDBY:
1035 break; 1111 case SND_SOC_BIAS_OFF:
1036 default: 1112 codec->driver->resume(codec);
1037 dev_dbg(socdev->dev, "CODEC was on over suspend\n"); 1113 codec->suspended = 0;
1038 break; 1114 break;
1115 default:
1116 dev_dbg(codec->dev, "CODEC was on over suspend\n");
1117 break;
1118 }
1039 } 1119 }
1040 } 1120 }
1041 1121
1042 for (i = 0; i < codec->num_dai; i++) { 1122 for (i = 0; i < card->num_rtd; i++) {
1043 char *stream = codec->dai[i].playback.stream_name; 1123 struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
1044 1124
1045 if (card->dai_link[i].ignore_suspend) 1125 if (card->rtd[i].dai_link->ignore_suspend)
1046 continue; 1126 continue;
1047 1127
1048 if (stream != NULL) 1128 if (driver->playback.stream_name != NULL)
1049 snd_soc_dapm_stream_event(codec, stream, 1129 snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
1050 SND_SOC_DAPM_STREAM_RESUME); 1130 SND_SOC_DAPM_STREAM_RESUME);
1051 stream = codec->dai[i].capture.stream_name; 1131
1052 if (stream != NULL) 1132 if (driver->capture.stream_name != NULL)
1053 snd_soc_dapm_stream_event(codec, stream, 1133 snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
1054 SND_SOC_DAPM_STREAM_RESUME); 1134 SND_SOC_DAPM_STREAM_RESUME);
1055 } 1135 }
1056 1136
1057 /* unmute any active DACs */ 1137 /* unmute any active DACs */
1058 for (i = 0; i < card->num_links; i++) { 1138 for (i = 0; i < card->num_rtd; i++) {
1059 struct snd_soc_dai *dai = card->dai_link[i].codec_dai; 1139 struct snd_soc_dai *dai = card->rtd[i].codec_dai;
1140 struct snd_soc_dai_driver *drv = dai->driver;
1060 1141
1061 if (card->dai_link[i].ignore_suspend) 1142 if (card->rtd[i].dai_link->ignore_suspend)
1062 continue; 1143 continue;
1063 1144
1064 if (dai->ops->digital_mute && dai->playback.active) 1145 if (drv->ops->digital_mute && dai->playback_active)
1065 dai->ops->digital_mute(dai, 0); 1146 drv->ops->digital_mute(dai, 0);
1066 } 1147 }
1067 1148
1068 for (i = 0; i < card->num_links; i++) { 1149 for (i = 0; i < card->num_rtd; i++) {
1069 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1150 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
1151 struct snd_soc_platform *platform = card->rtd[i].platform;
1070 1152
1071 if (card->dai_link[i].ignore_suspend) 1153 if (card->rtd[i].dai_link->ignore_suspend)
1072 continue; 1154 continue;
1073 1155
1074 if (cpu_dai->resume && !cpu_dai->ac97_control) 1156 if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control)
1075 cpu_dai->resume(cpu_dai); 1157 cpu_dai->driver->resume(cpu_dai);
1076 if (platform->resume) 1158 if (platform->driver->resume && platform->suspended) {
1077 platform->resume(&card->dai_link[i]); 1159 platform->driver->resume(cpu_dai);
1160 platform->suspended = 0;
1161 }
1078 } 1162 }
1079 1163
1080 if (card->resume_post) 1164 if (card->resume_post)
1081 card->resume_post(pdev); 1165 card->resume_post(pdev);
1082 1166
1083 dev_dbg(socdev->dev, "resume work completed\n"); 1167 dev_dbg(card->dev, "resume work completed\n");
1084 1168
1085 /* userspace can access us now we are back as we were before */ 1169 /* userspace can access us now we are back as we were before */
1086 snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); 1170 snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0);
1087} 1171}
1088 1172
1089/* powers up audio subsystem after a suspend */ 1173/* powers up audio subsystem after a suspend */
1090static int soc_resume(struct device *dev) 1174static int soc_resume(struct device *dev)
1091{ 1175{
1092 struct platform_device *pdev = to_platform_device(dev); 1176 struct platform_device *pdev = to_platform_device(dev);
1093 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1177 struct snd_soc_card *card = platform_get_drvdata(pdev);
1094 struct snd_soc_card *card = socdev->card; 1178 int i;
1095 struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai;
1096
1097 /* If the initialization of this soc device failed, there is no codec
1098 * associated with it. Just bail out in this case.
1099 */
1100 if (!card->codec)
1101 return 0;
1102 1179
1103 /* AC97 devices might have other drivers hanging off them so 1180 /* AC97 devices might have other drivers hanging off them so
1104 * need to resume immediately. Other drivers don't have that 1181 * need to resume immediately. Other drivers don't have that
1105 * problem and may take a substantial amount of time to resume 1182 * problem and may take a substantial amount of time to resume
1106 * due to I/O costs and anti-pop so handle them out of line. 1183 * due to I/O costs and anti-pop so handle them out of line.
1107 */ 1184 */
1108 if (cpu_dai->ac97_control) { 1185 for (i = 0; i < card->num_rtd; i++) {
1109 dev_dbg(socdev->dev, "Resuming AC97 immediately\n"); 1186 struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai;
1110 soc_resume_deferred(&card->deferred_resume_work); 1187 if (cpu_dai->driver->ac97_control) {
1111 } else { 1188 dev_dbg(dev, "Resuming AC97 immediately\n");
1112 dev_dbg(socdev->dev, "Scheduling resume work\n"); 1189 soc_resume_deferred(&card->deferred_resume_work);
1113 if (!schedule_work(&card->deferred_resume_work)) 1190 } else {
1114 dev_err(socdev->dev, "resume work item may be lost\n"); 1191 dev_dbg(dev, "Scheduling resume work\n");
1192 if (!schedule_work(&card->deferred_resume_work))
1193 dev_err(dev, "resume work item may be lost\n");
1194 }
1115 } 1195 }
1116 1196
1117 return 0; 1197 return 0;
@@ -1124,198 +1204,440 @@ static int soc_resume(struct device *dev)
1124static struct snd_soc_dai_ops null_dai_ops = { 1204static struct snd_soc_dai_ops null_dai_ops = {
1125}; 1205};
1126 1206
1127static void snd_soc_instantiate_card(struct snd_soc_card *card) 1207static int soc_bind_dai_link(struct snd_soc_card *card, int num)
1128{ 1208{
1129 struct platform_device *pdev = container_of(card->dev, 1209 struct snd_soc_dai_link *dai_link = &card->dai_link[num];
1130 struct platform_device, 1210 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1131 dev);
1132 struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
1133 struct snd_soc_codec *codec; 1211 struct snd_soc_codec *codec;
1134 struct snd_soc_platform *platform; 1212 struct snd_soc_platform *platform;
1135 struct snd_soc_dai *dai; 1213 struct snd_soc_dai *codec_dai, *cpu_dai;
1136 int i, found, ret, ac97;
1137 1214
1138 if (card->instantiated) 1215 if (rtd->complete)
1139 return; 1216 return 1;
1217 dev_dbg(card->dev, "binding %s at idx %d\n", dai_link->name, num);
1140 1218
1141 found = 0; 1219 /* do we already have the CPU DAI for this link ? */
1142 list_for_each_entry(platform, &platform_list, list) 1220 if (rtd->cpu_dai) {
1143 if (card->platform == platform) { 1221 goto find_codec;
1144 found = 1; 1222 }
1145 break; 1223 /* no, then find CPU DAI from registered DAIs*/
1224 list_for_each_entry(cpu_dai, &dai_list, list) {
1225 if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) {
1226
1227 if (!try_module_get(cpu_dai->dev->driver->owner))
1228 return -ENODEV;
1229
1230 rtd->cpu_dai = cpu_dai;
1231 goto find_codec;
1146 } 1232 }
1147 if (!found) {
1148 dev_dbg(card->dev, "Platform %s not registered\n",
1149 card->platform->name);
1150 return;
1151 } 1233 }
1234 dev_dbg(card->dev, "CPU DAI %s not registered\n",
1235 dai_link->cpu_dai_name);
1152 1236
1153 ac97 = 0; 1237find_codec:
1154 for (i = 0; i < card->num_links; i++) { 1238 /* do we already have the CODEC for this link ? */
1155 found = 0; 1239 if (rtd->codec) {
1156 list_for_each_entry(dai, &dai_list, list) 1240 goto find_platform;
1157 if (card->dai_link[i].cpu_dai == dai) { 1241 }
1158 found = 1; 1242
1159 break; 1243 /* no, then find CODEC from registered CODECs*/
1244 list_for_each_entry(codec, &codec_list, list) {
1245 if (!strcmp(codec->name, dai_link->codec_name)) {
1246 rtd->codec = codec;
1247
1248 if (!try_module_get(codec->dev->driver->owner))
1249 return -ENODEV;
1250
1251 /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/
1252 list_for_each_entry(codec_dai, &dai_list, list) {
1253 if (codec->dev == codec_dai->dev &&
1254 !strcmp(codec_dai->name, dai_link->codec_dai_name)) {
1255 rtd->codec_dai = codec_dai;
1256 goto find_platform;
1257 }
1160 } 1258 }
1161 if (!found) { 1259 dev_dbg(card->dev, "CODEC DAI %s not registered\n",
1162 dev_dbg(card->dev, "DAI %s not registered\n", 1260 dai_link->codec_dai_name);
1163 card->dai_link[i].cpu_dai->name); 1261
1164 return; 1262 goto find_platform;
1165 } 1263 }
1264 }
1265 dev_dbg(card->dev, "CODEC %s not registered\n",
1266 dai_link->codec_name);
1166 1267
1167 if (card->dai_link[i].cpu_dai->ac97_control) 1268find_platform:
1168 ac97 = 1; 1269 /* do we already have the CODEC DAI for this link ? */
1270 if (rtd->platform) {
1271 goto out;
1169 } 1272 }
1273 /* no, then find CPU DAI from registered DAIs*/
1274 list_for_each_entry(platform, &platform_list, list) {
1275 if (!strcmp(platform->name, dai_link->platform_name)) {
1170 1276
1171 for (i = 0; i < card->num_links; i++) { 1277 if (!try_module_get(platform->dev->driver->owner))
1172 if (!card->dai_link[i].codec_dai->ops) 1278 return -ENODEV;
1173 card->dai_link[i].codec_dai->ops = &null_dai_ops; 1279
1280 rtd->platform = platform;
1281 goto out;
1282 }
1174 } 1283 }
1175 1284
1176 /* If we have AC97 in the system then don't wait for the 1285 dev_dbg(card->dev, "platform %s not registered\n",
1177 * codec. This will need revisiting if we have to handle 1286 dai_link->platform_name);
1178 * systems with mixed AC97 and non-AC97 parts. Only check for 1287 return 0;
1179 * DAIs currently; we can't do this per link since some AC97 1288
1180 * codecs have non-AC97 DAIs. 1289out:
1181 */ 1290 /* mark rtd as complete if we found all 4 of our client devices */
1182 if (!ac97) 1291 if (rtd->codec && rtd->codec_dai && rtd->platform && rtd->cpu_dai) {
1183 for (i = 0; i < card->num_links; i++) { 1292 rtd->complete = 1;
1184 found = 0; 1293 card->num_rtd++;
1185 list_for_each_entry(dai, &dai_list, list) 1294 }
1186 if (card->dai_link[i].codec_dai == dai) { 1295 return 1;
1187 found = 1; 1296}
1188 break; 1297
1189 } 1298static void soc_remove_dai_link(struct snd_soc_card *card, int num)
1190 if (!found) { 1299{
1191 dev_dbg(card->dev, "DAI %s not registered\n", 1300 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1192 card->dai_link[i].codec_dai->name); 1301 struct snd_soc_codec *codec = rtd->codec;
1193 return; 1302 struct snd_soc_platform *platform = rtd->platform;
1194 } 1303 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
1304 int err;
1305
1306 /* unregister the rtd device */
1307 if (rtd->dev_registered) {
1308 device_remove_file(&rtd->dev, &dev_attr_pmdown_time);
1309 device_unregister(&rtd->dev);
1310 rtd->dev_registered = 0;
1311 }
1312
1313 /* remove the CODEC DAI */
1314 if (codec_dai && codec_dai->probed) {
1315 if (codec_dai->driver->remove) {
1316 err = codec_dai->driver->remove(codec_dai);
1317 if (err < 0)
1318 printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);
1195 } 1319 }
1320 codec_dai->probed = 0;
1321 list_del(&codec_dai->card_list);
1322 }
1196 1323
1197 /* Note that we do not current check for codec components */ 1324 /* remove the platform */
1325 if (platform && platform->probed) {
1326 if (platform->driver->remove) {
1327 err = platform->driver->remove(platform);
1328 if (err < 0)
1329 printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
1330 }
1331 platform->probed = 0;
1332 list_del(&platform->card_list);
1333 module_put(platform->dev->driver->owner);
1334 }
1198 1335
1199 dev_dbg(card->dev, "All components present, instantiating\n"); 1336 /* remove the CODEC */
1337 if (codec && codec->probed) {
1338 if (codec->driver->remove) {
1339 err = codec->driver->remove(codec);
1340 if (err < 0)
1341 printk(KERN_ERR "asoc: failed to remove %s\n", codec->name);
1342 }
1200 1343
1201 /* Found everything, bring it up */ 1344 /* Make sure all DAPM widgets are freed */
1202 card->pmdown_time = pmdown_time; 1345 snd_soc_dapm_free(codec);
1203 1346
1204 if (card->probe) { 1347 soc_cleanup_codec_debugfs(codec);
1205 ret = card->probe(pdev); 1348 device_remove_file(&rtd->dev, &dev_attr_codec_reg);
1206 if (ret < 0) 1349 codec->probed = 0;
1207 return; 1350 list_del(&codec->card_list);
1351 module_put(codec->dev->driver->owner);
1208 } 1352 }
1209 1353
1210 for (i = 0; i < card->num_links; i++) { 1354 /* remove the cpu_dai */
1211 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1355 if (cpu_dai && cpu_dai->probed) {
1212 if (cpu_dai->probe) { 1356 if (cpu_dai->driver->remove) {
1213 ret = cpu_dai->probe(pdev, cpu_dai); 1357 err = cpu_dai->driver->remove(cpu_dai);
1214 if (ret < 0) 1358 if (err < 0)
1215 goto cpu_dai_err; 1359 printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);
1216 } 1360 }
1361 cpu_dai->probed = 0;
1362 list_del(&cpu_dai->card_list);
1363 module_put(cpu_dai->dev->driver->owner);
1217 } 1364 }
1365}
1218 1366
1219 if (codec_dev->probe) { 1367static void rtd_release(struct device *dev) {}
1220 ret = codec_dev->probe(pdev); 1368
1221 if (ret < 0) 1369static int soc_probe_dai_link(struct snd_soc_card *card, int num)
1222 goto cpu_dai_err; 1370{
1371 struct snd_soc_dai_link *dai_link = &card->dai_link[num];
1372 struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
1373 struct snd_soc_codec *codec = rtd->codec;
1374 struct snd_soc_platform *platform = rtd->platform;
1375 struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
1376 int ret;
1377
1378 dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
1379
1380 /* config components */
1381 codec_dai->codec = codec;
1382 codec->card = card;
1383 cpu_dai->platform = platform;
1384 rtd->card = card;
1385 rtd->dev.parent = card->dev;
1386 codec_dai->card = card;
1387 cpu_dai->card = card;
1388
1389 /* set default power off timeout */
1390 rtd->pmdown_time = pmdown_time;
1391
1392 /* probe the cpu_dai */
1393 if (!cpu_dai->probed) {
1394 if (cpu_dai->driver->probe) {
1395 ret = cpu_dai->driver->probe(cpu_dai);
1396 if (ret < 0) {
1397 printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
1398 cpu_dai->name);
1399 return ret;
1400 }
1401 }
1402 cpu_dai->probed = 1;
1403 /* mark cpu_dai as probed and add to card cpu_dai list */
1404 list_add(&cpu_dai->card_list, &card->dai_dev_list);
1223 } 1405 }
1224 codec = card->codec;
1225 1406
1226 if (platform->probe) { 1407 /* probe the CODEC */
1227 ret = platform->probe(pdev); 1408 if (!codec->probed) {
1228 if (ret < 0) 1409 if (codec->driver->probe) {
1229 goto platform_err; 1410 ret = codec->driver->probe(codec);
1411 if (ret < 0) {
1412 printk(KERN_ERR "asoc: failed to probe CODEC %s\n",
1413 codec->name);
1414 return ret;
1415 }
1416 }
1417
1418 soc_init_codec_debugfs(codec);
1419
1420 /* mark codec as probed and add to card codec list */
1421 codec->probed = 1;
1422 list_add(&codec->card_list, &card->codec_dev_list);
1230 } 1423 }
1231 1424
1232 /* DAPM stream work */ 1425 /* probe the platform */
1233 INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work); 1426 if (!platform->probed) {
1234#ifdef CONFIG_PM 1427 if (platform->driver->probe) {
1235 /* deferred resume work */ 1428 ret = platform->driver->probe(platform);
1236 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); 1429 if (ret < 0) {
1237#endif 1430 printk(KERN_ERR "asoc: failed to probe platform %s\n",
1431 platform->name);
1432 return ret;
1433 }
1434 }
1435 /* mark platform as probed and add to card platform list */
1436 platform->probed = 1;
1437 list_add(&platform->card_list, &card->platform_dev_list);
1438 }
1238 1439
1239 for (i = 0; i < card->num_links; i++) { 1440 /* probe the CODEC DAI */
1240 if (card->dai_link[i].init) { 1441 if (!codec_dai->probed) {
1241 ret = card->dai_link[i].init(codec); 1442 if (codec_dai->driver->probe) {
1443 ret = codec_dai->driver->probe(codec_dai);
1242 if (ret < 0) { 1444 if (ret < 0) {
1243 printk(KERN_ERR "asoc: failed to init %s\n", 1445 printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
1244 card->dai_link[i].stream_name); 1446 codec_dai->name);
1245 continue; 1447 return ret;
1246 } 1448 }
1247 } 1449 }
1248 if (card->dai_link[i].codec_dai->ac97_control) 1450
1249 ac97 = 1; 1451 /* mark cpu_dai as probed and add to card cpu_dai list */
1452 codec_dai->probed = 1;
1453 list_add(&codec_dai->card_list, &card->dai_dev_list);
1250 } 1454 }
1251 1455
1252 snprintf(codec->card->shortname, sizeof(codec->card->shortname), 1456 /* DAPM dai link stream work */
1253 "%s", card->name); 1457 INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
1254 snprintf(codec->card->longname, sizeof(codec->card->longname), 1458
1255 "%s (%s)", card->name, codec->name); 1459 /* now that all clients have probed, initialise the DAI link */
1460 if (dai_link->init) {
1461 ret = dai_link->init(rtd);
1462 if (ret < 0) {
1463 printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name);
1464 return ret;
1465 }
1466 }
1256 1467
1257 /* Make sure all DAPM widgets are instantiated */ 1468 /* Make sure all DAPM widgets are instantiated */
1258 snd_soc_dapm_new_widgets(codec); 1469 snd_soc_dapm_new_widgets(codec);
1470 snd_soc_dapm_sync(codec);
1259 1471
1260 ret = snd_card_register(codec->card); 1472 /* register the rtd device */
1473 rtd->dev.release = rtd_release;
1474 rtd->dev.init_name = dai_link->name;
1475 ret = device_register(&rtd->dev);
1261 if (ret < 0) { 1476 if (ret < 0) {
1262 printk(KERN_ERR "asoc: failed to register soundcard for %s\n", 1477 printk(KERN_ERR "asoc: failed to register DAI runtime device %d\n", ret);
1263 codec->name); 1478 return ret;
1264 goto card_err;
1265 } 1479 }
1266 1480
1267 mutex_lock(&codec->mutex); 1481 rtd->dev_registered = 1;
1482 ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time);
1483 if (ret < 0)
1484 printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
1485
1486 /* add DAPM sysfs entries for this codec */
1487 ret = snd_soc_dapm_sys_add(&rtd->dev);
1488 if (ret < 0)
1489 printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entries\n");
1490
1491 /* add codec sysfs entries */
1492 ret = device_create_file(&rtd->dev, &dev_attr_codec_reg);
1493 if (ret < 0)
1494 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1495
1496 /* create the pcm */
1497 ret = soc_new_pcm(rtd, num);
1498 if (ret < 0) {
1499 printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name);
1500 return ret;
1501 }
1502
1503 /* add platform data for AC97 devices */
1504 if (rtd->codec_dai->driver->ac97_control)
1505 snd_ac97_dev_add_pdata(codec->ac97, rtd->cpu_dai->ac97_pdata);
1506
1507 return 0;
1508}
1509
1268#ifdef CONFIG_SND_SOC_AC97_BUS 1510#ifdef CONFIG_SND_SOC_AC97_BUS
1511static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
1512{
1513 int ret;
1514
1269 /* Only instantiate AC97 if not already done by the adaptor 1515 /* Only instantiate AC97 if not already done by the adaptor
1270 * for the generic AC97 subsystem. 1516 * for the generic AC97 subsystem.
1271 */ 1517 */
1272 if (ac97 && strcmp(codec->name, "AC97") != 0) { 1518 if (rtd->codec_dai->driver->ac97_control && !rtd->codec->ac97_registered) {
1273 ret = soc_ac97_dev_register(codec); 1519 /*
1520 * It is possible that the AC97 device is already registered to
1521 * the device subsystem. This happens when the device is created
1522 * via snd_ac97_mixer(). Currently only SoC codec that does so
1523 * is the generic AC97 glue but others migh emerge.
1524 *
1525 * In those cases we don't try to register the device again.
1526 */
1527 if (!rtd->codec->ac97_created)
1528 return 0;
1529
1530 ret = soc_ac97_dev_register(rtd->codec);
1274 if (ret < 0) { 1531 if (ret < 0) {
1275 printk(KERN_ERR "asoc: AC97 device register failed\n"); 1532 printk(KERN_ERR "asoc: AC97 device register failed\n");
1276 snd_card_free(codec->card); 1533 return ret;
1277 mutex_unlock(&codec->mutex);
1278 goto card_err;
1279 } 1534 }
1535
1536 rtd->codec->ac97_registered = 1;
1537 }
1538 return 0;
1539}
1540
1541static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec)
1542{
1543 if (codec->ac97_registered) {
1544 soc_ac97_dev_unregister(codec);
1545 codec->ac97_registered = 0;
1280 } 1546 }
1547}
1281#endif 1548#endif
1282 1549
1283 ret = snd_soc_dapm_sys_add(card->socdev->dev); 1550static void snd_soc_instantiate_card(struct snd_soc_card *card)
1284 if (ret < 0) 1551{
1285 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n"); 1552 struct platform_device *pdev = to_platform_device(card->dev);
1553 int ret, i;
1286 1554
1287 ret = device_create_file(card->socdev->dev, &dev_attr_pmdown_time); 1555 mutex_lock(&card->mutex);
1288 if (ret < 0)
1289 printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
1290 1556
1291 ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg); 1557 if (card->instantiated) {
1292 if (ret < 0) 1558 mutex_unlock(&card->mutex);
1293 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); 1559 return;
1560 }
1294 1561
1295 soc_init_codec_debugfs(codec); 1562 /* bind DAIs */
1296 mutex_unlock(&codec->mutex); 1563 for (i = 0; i < card->num_links; i++)
1564 soc_bind_dai_link(card, i);
1297 1565
1298 card->instantiated = 1; 1566 /* bind completed ? */
1567 if (card->num_rtd != card->num_links) {
1568 mutex_unlock(&card->mutex);
1569 return;
1570 }
1299 1571
1300 return; 1572 /* card bind complete so register a sound card */
1573 ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
1574 card->owner, 0, &card->snd_card);
1575 if (ret < 0) {
1576 printk(KERN_ERR "asoc: can't create sound card for card %s\n",
1577 card->name);
1578 mutex_unlock(&card->mutex);
1579 return;
1580 }
1581 card->snd_card->dev = card->dev;
1301 1582
1302card_err: 1583#ifdef CONFIG_PM
1303 if (platform->remove) 1584 /* deferred resume work */
1304 platform->remove(pdev); 1585 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
1586#endif
1305 1587
1306platform_err: 1588 /* initialise the sound card only once */
1307 if (codec_dev->remove) 1589 if (card->probe) {
1308 codec_dev->remove(pdev); 1590 ret = card->probe(pdev);
1591 if (ret < 0)
1592 goto card_probe_error;
1593 }
1309 1594
1310cpu_dai_err: 1595 for (i = 0; i < card->num_links; i++) {
1311 for (i--; i >= 0; i--) { 1596 ret = soc_probe_dai_link(card, i);
1312 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; 1597 if (ret < 0) {
1313 if (cpu_dai->remove) 1598 pr_err("asoc: failed to instantiate card %s: %d\n",
1314 cpu_dai->remove(pdev, cpu_dai); 1599 card->name, ret);
1600 goto probe_dai_err;
1601 }
1315 } 1602 }
1316 1603
1604 snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
1605 "%s", card->name);
1606 snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
1607 "%s", card->name);
1608
1609 ret = snd_card_register(card->snd_card);
1610 if (ret < 0) {
1611 printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
1612 goto probe_dai_err;
1613 }
1614
1615#ifdef CONFIG_SND_SOC_AC97_BUS
1616 /* register any AC97 codecs */
1617 for (i = 0; i < card->num_rtd; i++) {
1618 ret = soc_register_ac97_dai_link(&card->rtd[i]);
1619 if (ret < 0) {
1620 printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
1621 goto probe_dai_err;
1622 }
1623 }
1624#endif
1625
1626 card->instantiated = 1;
1627 mutex_unlock(&card->mutex);
1628 return;
1629
1630probe_dai_err:
1631 for (i = 0; i < card->num_links; i++)
1632 soc_remove_dai_link(card, i);
1633
1634card_probe_error:
1317 if (card->remove) 1635 if (card->remove)
1318 card->remove(pdev); 1636 card->remove(pdev);
1637
1638 snd_card_free(card->snd_card);
1639
1640 mutex_unlock(&card->mutex);
1319} 1641}
1320 1642
1321/* 1643/*
@@ -1332,15 +1654,15 @@ static void snd_soc_instantiate_cards(void)
1332/* probes a new socdev */ 1654/* probes a new socdev */
1333static int soc_probe(struct platform_device *pdev) 1655static int soc_probe(struct platform_device *pdev)
1334{ 1656{
1657 struct snd_soc_card *card = platform_get_drvdata(pdev);
1335 int ret = 0; 1658 int ret = 0;
1336 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1337 struct snd_soc_card *card = socdev->card;
1338
1339 /* Bodge while we push things out of socdev */
1340 card->socdev = socdev;
1341 1659
1342 /* Bodge while we unpick instantiation */ 1660 /* Bodge while we unpick instantiation */
1343 card->dev = &pdev->dev; 1661 card->dev = &pdev->dev;
1662 INIT_LIST_HEAD(&card->dai_dev_list);
1663 INIT_LIST_HEAD(&card->codec_dev_list);
1664 INIT_LIST_HEAD(&card->platform_dev_list);
1665
1344 ret = snd_soc_register_card(card); 1666 ret = snd_soc_register_card(card);
1345 if (ret != 0) { 1667 if (ret != 0) {
1346 dev_err(&pdev->dev, "Failed to register card\n"); 1668 dev_err(&pdev->dev, "Failed to register card\n");
@@ -1353,50 +1675,49 @@ static int soc_probe(struct platform_device *pdev)
1353/* removes a socdev */ 1675/* removes a socdev */
1354static int soc_remove(struct platform_device *pdev) 1676static int soc_remove(struct platform_device *pdev)
1355{ 1677{
1678 struct snd_soc_card *card = platform_get_drvdata(pdev);
1356 int i; 1679 int i;
1357 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1358 struct snd_soc_card *card = socdev->card;
1359 struct snd_soc_platform *platform = card->platform;
1360 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
1361 1680
1362 if (card->instantiated) { 1681 if (card->instantiated) {
1363 run_delayed_work(&card->delayed_work);
1364
1365 if (platform->remove)
1366 platform->remove(pdev);
1367 1682
1368 if (codec_dev->remove) 1683 /* make sure any delayed work runs */
1369 codec_dev->remove(pdev); 1684 for (i = 0; i < card->num_rtd; i++) {
1370 1685 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
1371 for (i = 0; i < card->num_links; i++) { 1686 run_delayed_work(&rtd->delayed_work);
1372 struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
1373 if (cpu_dai->remove)
1374 cpu_dai->remove(pdev, cpu_dai);
1375 } 1687 }
1376 1688
1689 /* remove and free each DAI */
1690 for (i = 0; i < card->num_rtd; i++)
1691 soc_remove_dai_link(card, i);
1692
1693 /* remove the card */
1377 if (card->remove) 1694 if (card->remove)
1378 card->remove(pdev); 1695 card->remove(pdev);
1379 }
1380 1696
1697 kfree(card->rtd);
1698 snd_card_free(card->snd_card);
1699 }
1381 snd_soc_unregister_card(card); 1700 snd_soc_unregister_card(card);
1382
1383 return 0; 1701 return 0;
1384} 1702}
1385 1703
1386static int soc_poweroff(struct device *dev) 1704static int soc_poweroff(struct device *dev)
1387{ 1705{
1388 struct platform_device *pdev = to_platform_device(dev); 1706 struct platform_device *pdev = to_platform_device(dev);
1389 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1707 struct snd_soc_card *card = platform_get_drvdata(pdev);
1390 struct snd_soc_card *card = socdev->card; 1708 int i;
1391 1709
1392 if (!card->instantiated) 1710 if (!card->instantiated)
1393 return 0; 1711 return 0;
1394 1712
1395 /* Flush out pmdown_time work - we actually do want to run it 1713 /* Flush out pmdown_time work - we actually do want to run it
1396 * now, we're shutting down so no imminent restart. */ 1714 * now, we're shutting down so no imminent restart. */
1397 run_delayed_work(&card->delayed_work); 1715 for (i = 0; i < card->num_rtd; i++) {
1716 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];
1717 run_delayed_work(&rtd->delayed_work);
1718 }
1398 1719
1399 snd_soc_dapm_shutdown(socdev); 1720 snd_soc_dapm_shutdown(card);
1400 1721
1401 return 0; 1722 return 0;
1402} 1723}
@@ -1419,53 +1740,42 @@ static struct platform_driver soc_driver = {
1419}; 1740};
1420 1741
1421/* create a new pcm */ 1742/* create a new pcm */
1422static int soc_new_pcm(struct snd_soc_device *socdev, 1743static int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
1423 struct snd_soc_dai_link *dai_link, int num) 1744{
1424{ 1745 struct snd_soc_codec *codec = rtd->codec;
1425 struct snd_soc_card *card = socdev->card; 1746 struct snd_soc_platform *platform = rtd->platform;
1426 struct snd_soc_codec *codec = card->codec; 1747 struct snd_soc_dai *codec_dai = rtd->codec_dai;
1427 struct snd_soc_platform *platform = card->platform; 1748 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
1428 struct snd_soc_dai *codec_dai = dai_link->codec_dai;
1429 struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
1430 struct snd_soc_pcm_runtime *rtd;
1431 struct snd_pcm *pcm; 1749 struct snd_pcm *pcm;
1432 char new_name[64]; 1750 char new_name[64];
1433 int ret = 0, playback = 0, capture = 0; 1751 int ret = 0, playback = 0, capture = 0;
1434 1752
1435 rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
1436 if (rtd == NULL)
1437 return -ENOMEM;
1438
1439 rtd->dai = dai_link;
1440 rtd->socdev = socdev;
1441 codec_dai->codec = card->codec;
1442
1443 /* check client and interface hw capabilities */ 1753 /* check client and interface hw capabilities */
1444 snprintf(new_name, sizeof(new_name), "%s %s-%d", 1754 snprintf(new_name, sizeof(new_name), "%s %s-%d",
1445 dai_link->stream_name, codec_dai->name, num); 1755 rtd->dai_link->stream_name, codec_dai->name, num);
1446 1756
1447 if (codec_dai->playback.channels_min) 1757 if (codec_dai->driver->playback.channels_min)
1448 playback = 1; 1758 playback = 1;
1449 if (codec_dai->capture.channels_min) 1759 if (codec_dai->driver->capture.channels_min)
1450 capture = 1; 1760 capture = 1;
1451 1761
1452 ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback, 1762 dev_dbg(rtd->card->dev, "registered pcm #%d %s\n",num,new_name);
1453 capture, &pcm); 1763 ret = snd_pcm_new(rtd->card->snd_card, new_name,
1764 num, playback, capture, &pcm);
1454 if (ret < 0) { 1765 if (ret < 0) {
1455 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", 1766 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
1456 codec->name);
1457 kfree(rtd);
1458 return ret; 1767 return ret;
1459 } 1768 }
1460 1769
1461 dai_link->pcm = pcm; 1770 rtd->pcm = pcm;
1462 pcm->private_data = rtd; 1771 pcm->private_data = rtd;
1463 soc_pcm_ops.mmap = platform->pcm_ops->mmap; 1772 soc_pcm_ops.mmap = platform->driver->ops->mmap;
1464 soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; 1773 soc_pcm_ops.pointer = platform->driver->ops->pointer;
1465 soc_pcm_ops.copy = platform->pcm_ops->copy; 1774 soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
1466 soc_pcm_ops.silence = platform->pcm_ops->silence; 1775 soc_pcm_ops.copy = platform->driver->ops->copy;
1467 soc_pcm_ops.ack = platform->pcm_ops->ack; 1776 soc_pcm_ops.silence = platform->driver->ops->silence;
1468 soc_pcm_ops.page = platform->pcm_ops->page; 1777 soc_pcm_ops.ack = platform->driver->ops->ack;
1778 soc_pcm_ops.page = platform->driver->ops->page;
1469 1779
1470 if (playback) 1780 if (playback)
1471 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); 1781 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
@@ -1473,14 +1783,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1473 if (capture) 1783 if (capture)
1474 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); 1784 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
1475 1785
1476 ret = platform->pcm_new(codec->card, codec_dai, pcm); 1786 ret = platform->driver->pcm_new(rtd->card->snd_card, codec_dai, pcm);
1477 if (ret < 0) { 1787 if (ret < 0) {
1478 printk(KERN_ERR "asoc: platform pcm constructor failed\n"); 1788 printk(KERN_ERR "asoc: platform pcm constructor failed\n");
1479 kfree(rtd);
1480 return ret; 1789 return ret;
1481 } 1790 }
1482 1791
1483 pcm->private_free = platform->pcm_free; 1792 pcm->private_free = platform->driver->pcm_free;
1484 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, 1793 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
1485 cpu_dai->name); 1794 cpu_dai->name);
1486 return ret; 1795 return ret;
@@ -1496,8 +1805,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
1496 */ 1805 */
1497int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) 1806int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
1498{ 1807{
1499 if (codec->volatile_register) 1808 if (codec->driver->volatile_register)
1500 return codec->volatile_register(reg); 1809 return codec->driver->volatile_register(reg);
1501 else 1810 else
1502 return 0; 1811 return 0;
1503} 1812}
@@ -1532,7 +1841,13 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
1532 1841
1533 codec->ac97->bus->ops = ops; 1842 codec->ac97->bus->ops = ops;
1534 codec->ac97->num = num; 1843 codec->ac97->num = num;
1535 codec->dev = &codec->ac97->dev; 1844
1845 /*
1846 * Mark the AC97 device to be created by us. This way we ensure that the
1847 * device will be registered with the device subsystem later on.
1848 */
1849 codec->ac97_created = 1;
1850
1536 mutex_unlock(&codec->mutex); 1851 mutex_unlock(&codec->mutex);
1537 return 0; 1852 return 0;
1538} 1853}
@@ -1547,9 +1862,13 @@ EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
1547void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) 1862void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
1548{ 1863{
1549 mutex_lock(&codec->mutex); 1864 mutex_lock(&codec->mutex);
1865#ifdef CONFIG_SND_SOC_AC97_BUS
1866 soc_unregister_ac97_dai_link(codec);
1867#endif
1550 kfree(codec->ac97->bus); 1868 kfree(codec->ac97->bus);
1551 kfree(codec->ac97); 1869 kfree(codec->ac97);
1552 codec->ac97 = NULL; 1870 codec->ac97 = NULL;
1871 codec->ac97_created = 0;
1553 mutex_unlock(&codec->mutex); 1872 mutex_unlock(&codec->mutex);
1554} 1873}
1555EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); 1874EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
@@ -1633,95 +1952,6 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1633EXPORT_SYMBOL_GPL(snd_soc_test_bits); 1952EXPORT_SYMBOL_GPL(snd_soc_test_bits);
1634 1953
1635/** 1954/**
1636 * snd_soc_new_pcms - create new sound card and pcms
1637 * @socdev: the SoC audio device
1638 * @idx: ALSA card index
1639 * @xid: card identification
1640 *
1641 * Create a new sound card based upon the codec and interface pcms.
1642 *
1643 * Returns 0 for success, else error.
1644 */
1645int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1646{
1647 struct snd_soc_card *card = socdev->card;
1648 struct snd_soc_codec *codec = card->codec;
1649 int ret, i;
1650
1651 mutex_lock(&codec->mutex);
1652
1653 /* register a sound card */
1654 ret = snd_card_create(idx, xid, codec->owner, 0, &codec->card);
1655 if (ret < 0) {
1656 printk(KERN_ERR "asoc: can't create sound card for codec %s\n",
1657 codec->name);
1658 mutex_unlock(&codec->mutex);
1659 return ret;
1660 }
1661
1662 codec->socdev = socdev;
1663 codec->card->dev = socdev->dev;
1664 codec->card->private_data = codec;
1665 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
1666
1667 /* create the pcms */
1668 for (i = 0; i < card->num_links; i++) {
1669 ret = soc_new_pcm(socdev, &card->dai_link[i], i);
1670 if (ret < 0) {
1671 printk(KERN_ERR "asoc: can't create pcm %s\n",
1672 card->dai_link[i].stream_name);
1673 mutex_unlock(&codec->mutex);
1674 return ret;
1675 }
1676 /* Check for codec->ac97 to handle the ac97.c fun */
1677 if (card->dai_link[i].codec_dai->ac97_control && codec->ac97) {
1678 snd_ac97_dev_add_pdata(codec->ac97,
1679 card->dai_link[i].cpu_dai->ac97_pdata);
1680 }
1681 }
1682
1683 mutex_unlock(&codec->mutex);
1684 return ret;
1685}
1686EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1687
1688/**
1689 * snd_soc_free_pcms - free sound card and pcms
1690 * @socdev: the SoC audio device
1691 *
1692 * Frees sound card and pcms associated with the socdev.
1693 * Also unregister the codec if it is an AC97 device.
1694 */
1695void snd_soc_free_pcms(struct snd_soc_device *socdev)
1696{
1697 struct snd_soc_codec *codec = socdev->card->codec;
1698#ifdef CONFIG_SND_SOC_AC97_BUS
1699 struct snd_soc_dai *codec_dai;
1700 int i;
1701#endif
1702
1703 mutex_lock(&codec->mutex);
1704 soc_cleanup_codec_debugfs(codec);
1705#ifdef CONFIG_SND_SOC_AC97_BUS
1706 for (i = 0; i < codec->num_dai; i++) {
1707 codec_dai = &codec->dai[i];
1708 if (codec_dai->ac97_control && codec->ac97 &&
1709 strcmp(codec->name, "AC97") != 0) {
1710 soc_ac97_dev_unregister(codec);
1711 goto free_card;
1712 }
1713 }
1714free_card:
1715#endif
1716
1717 if (codec->card)
1718 snd_card_free(codec->card);
1719 device_remove_file(socdev->dev, &dev_attr_codec_reg);
1720 mutex_unlock(&codec->mutex);
1721}
1722EXPORT_SYMBOL_GPL(snd_soc_free_pcms);
1723
1724/**
1725 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters 1955 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
1726 * @substream: the pcm substream 1956 * @substream: the pcm substream
1727 * @hw: the hardware parameters 1957 * @hw: the hardware parameters
@@ -1782,15 +2012,15 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
1782int snd_soc_add_controls(struct snd_soc_codec *codec, 2012int snd_soc_add_controls(struct snd_soc_codec *codec,
1783 const struct snd_kcontrol_new *controls, int num_controls) 2013 const struct snd_kcontrol_new *controls, int num_controls)
1784{ 2014{
1785 struct snd_card *card = codec->card; 2015 struct snd_card *card = codec->card->snd_card;
1786 int err, i; 2016 int err, i;
1787 2017
1788 for (i = 0; i < num_controls; i++) { 2018 for (i = 0; i < num_controls; i++) {
1789 const struct snd_kcontrol_new *control = &controls[i]; 2019 const struct snd_kcontrol_new *control = &controls[i];
1790 err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); 2020 err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL));
1791 if (err < 0) { 2021 if (err < 0) {
1792 dev_err(codec->dev, "%s: Failed to add %s\n", 2022 dev_err(codec->dev, "%s: Failed to add %s: %d\n",
1793 codec->name, control->name); 2023 codec->name, control->name, err);
1794 return err; 2024 return err;
1795 } 2025 }
1796 } 2026 }
@@ -2337,7 +2567,7 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2337int snd_soc_limit_volume(struct snd_soc_codec *codec, 2567int snd_soc_limit_volume(struct snd_soc_codec *codec,
2338 const char *name, int max) 2568 const char *name, int max)
2339{ 2569{
2340 struct snd_card *card = codec->card; 2570 struct snd_card *card = codec->card->snd_card;
2341 struct snd_kcontrol *kctl; 2571 struct snd_kcontrol *kctl;
2342 struct soc_mixer_control *mc; 2572 struct soc_mixer_control *mc;
2343 int found = 0; 2573 int found = 0;
@@ -2469,8 +2699,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
2469int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, 2699int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
2470 unsigned int freq, int dir) 2700 unsigned int freq, int dir)
2471{ 2701{
2472 if (dai->ops && dai->ops->set_sysclk) 2702 if (dai->driver && dai->driver->ops->set_sysclk)
2473 return dai->ops->set_sysclk(dai, clk_id, freq, dir); 2703 return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
2474 else 2704 else
2475 return -EINVAL; 2705 return -EINVAL;
2476} 2706}
@@ -2489,8 +2719,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
2489int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, 2719int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
2490 int div_id, int div) 2720 int div_id, int div)
2491{ 2721{
2492 if (dai->ops && dai->ops->set_clkdiv) 2722 if (dai->driver && dai->driver->ops->set_clkdiv)
2493 return dai->ops->set_clkdiv(dai, div_id, div); 2723 return dai->driver->ops->set_clkdiv(dai, div_id, div);
2494 else 2724 else
2495 return -EINVAL; 2725 return -EINVAL;
2496} 2726}
@@ -2509,8 +2739,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2509int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, 2739int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
2510 unsigned int freq_in, unsigned int freq_out) 2740 unsigned int freq_in, unsigned int freq_out)
2511{ 2741{
2512 if (dai->ops && dai->ops->set_pll) 2742 if (dai->driver && dai->driver->ops->set_pll)
2513 return dai->ops->set_pll(dai, pll_id, source, 2743 return dai->driver->ops->set_pll(dai, pll_id, source,
2514 freq_in, freq_out); 2744 freq_in, freq_out);
2515 else 2745 else
2516 return -EINVAL; 2746 return -EINVAL;
@@ -2526,8 +2756,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
2526 */ 2756 */
2527int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 2757int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
2528{ 2758{
2529 if (dai->ops && dai->ops->set_fmt) 2759 if (dai->driver && dai->driver->ops->set_fmt)
2530 return dai->ops->set_fmt(dai, fmt); 2760 return dai->driver->ops->set_fmt(dai, fmt);
2531 else 2761 else
2532 return -EINVAL; 2762 return -EINVAL;
2533} 2763}
@@ -2547,8 +2777,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
2547int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, 2777int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
2548 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) 2778 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
2549{ 2779{
2550 if (dai->ops && dai->ops->set_tdm_slot) 2780 if (dai->driver && dai->driver->ops->set_tdm_slot)
2551 return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask, 2781 return dai->driver->ops->set_tdm_slot(dai, tx_mask, rx_mask,
2552 slots, slot_width); 2782 slots, slot_width);
2553 else 2783 else
2554 return -EINVAL; 2784 return -EINVAL;
@@ -2571,8 +2801,8 @@ int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
2571 unsigned int tx_num, unsigned int *tx_slot, 2801 unsigned int tx_num, unsigned int *tx_slot,
2572 unsigned int rx_num, unsigned int *rx_slot) 2802 unsigned int rx_num, unsigned int *rx_slot)
2573{ 2803{
2574 if (dai->ops && dai->ops->set_channel_map) 2804 if (dai->driver && dai->driver->ops->set_channel_map)
2575 return dai->ops->set_channel_map(dai, tx_num, tx_slot, 2805 return dai->driver->ops->set_channel_map(dai, tx_num, tx_slot,
2576 rx_num, rx_slot); 2806 rx_num, rx_slot);
2577 else 2807 else
2578 return -EINVAL; 2808 return -EINVAL;
@@ -2588,8 +2818,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
2588 */ 2818 */
2589int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) 2819int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
2590{ 2820{
2591 if (dai->ops && dai->ops->set_tristate) 2821 if (dai->driver && dai->driver->ops->set_tristate)
2592 return dai->ops->set_tristate(dai, tristate); 2822 return dai->driver->ops->set_tristate(dai, tristate);
2593 else 2823 else
2594 return -EINVAL; 2824 return -EINVAL;
2595} 2825}
@@ -2604,8 +2834,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
2604 */ 2834 */
2605int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) 2835int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
2606{ 2836{
2607 if (dai->ops && dai->ops->digital_mute) 2837 if (dai->driver && dai->driver->ops->digital_mute)
2608 return dai->ops->digital_mute(dai, mute); 2838 return dai->driver->ops->digital_mute(dai, mute);
2609 else 2839 else
2610 return -EINVAL; 2840 return -EINVAL;
2611} 2841}
@@ -2622,11 +2852,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
2622 */ 2852 */
2623static int snd_soc_register_card(struct snd_soc_card *card) 2853static int snd_soc_register_card(struct snd_soc_card *card)
2624{ 2854{
2855 int i;
2856
2625 if (!card->name || !card->dev) 2857 if (!card->name || !card->dev)
2626 return -EINVAL; 2858 return -EINVAL;
2627 2859
2860 card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links,
2861 GFP_KERNEL);
2862 if (card->rtd == NULL)
2863 return -ENOMEM;
2864
2865 for (i = 0; i < card->num_links; i++)
2866 card->rtd[i].dai_link = &card->dai_link[i];
2867
2628 INIT_LIST_HEAD(&card->list); 2868 INIT_LIST_HEAD(&card->list);
2629 card->instantiated = 0; 2869 card->instantiated = 0;
2870 mutex_init(&card->mutex);
2630 2871
2631 mutex_lock(&client_mutex); 2872 mutex_lock(&client_mutex);
2632 list_add(&card->list, &card_list); 2873 list_add(&card->list, &card_list);
@@ -2652,30 +2893,97 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
2652 mutex_lock(&client_mutex); 2893 mutex_lock(&client_mutex);
2653 list_del(&card->list); 2894 list_del(&card->list);
2654 mutex_unlock(&client_mutex); 2895 mutex_unlock(&client_mutex);
2655
2656 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); 2896 dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
2657 2897
2658 return 0; 2898 return 0;
2659} 2899}
2660 2900
2901/*
2902 * Simplify DAI link configuration by removing ".-1" from device names
2903 * and sanitizing names.
2904 */
2905static inline char *fmt_single_name(struct device *dev, int *id)
2906{
2907 char *found, name[NAME_SIZE];
2908 int id1, id2;
2909
2910 if (dev_name(dev) == NULL)
2911 return NULL;
2912
2913 strncpy(name, dev_name(dev), NAME_SIZE);
2914
2915 /* are we a "%s.%d" name (platform and SPI components) */
2916 found = strstr(name, dev->driver->name);
2917 if (found) {
2918 /* get ID */
2919 if (sscanf(&found[strlen(dev->driver->name)], ".%d", id) == 1) {
2920
2921 /* discard ID from name if ID == -1 */
2922 if (*id == -1)
2923 found[strlen(dev->driver->name)] = '\0';
2924 }
2925
2926 } else {
2927 /* I2C component devices are named "bus-addr" */
2928 if (sscanf(name, "%x-%x", &id1, &id2) == 2) {
2929 char tmp[NAME_SIZE];
2930
2931 /* create unique ID number from I2C addr and bus */
2932 *id = ((id1 & 0xffff) << 16) + id2;
2933
2934 /* sanitize component name for DAI link creation */
2935 snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name);
2936 strncpy(name, tmp, NAME_SIZE);
2937 } else
2938 *id = 0;
2939 }
2940
2941 return kstrdup(name, GFP_KERNEL);
2942}
2943
2944/*
2945 * Simplify DAI link naming for single devices with multiple DAIs by removing
2946 * any ".-1" and using the DAI name (instead of device name).
2947 */
2948static inline char *fmt_multiple_name(struct device *dev,
2949 struct snd_soc_dai_driver *dai_drv)
2950{
2951 if (dai_drv->name == NULL) {
2952 printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n",
2953 dev_name(dev));
2954 return NULL;
2955 }
2956
2957 return kstrdup(dai_drv->name, GFP_KERNEL);
2958}
2959
2661/** 2960/**
2662 * snd_soc_register_dai - Register a DAI with the ASoC core 2961 * snd_soc_register_dai - Register a DAI with the ASoC core
2663 * 2962 *
2664 * @dai: DAI to register 2963 * @dai: DAI to register
2665 */ 2964 */
2666int snd_soc_register_dai(struct snd_soc_dai *dai) 2965int snd_soc_register_dai(struct device *dev,
2966 struct snd_soc_dai_driver *dai_drv)
2667{ 2967{
2668 if (!dai->name) 2968 struct snd_soc_dai *dai;
2669 return -EINVAL; 2969
2970 dev_dbg(dev, "dai register %s\n", dev_name(dev));
2670 2971
2671 /* The device should become mandatory over time */ 2972 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
2672 if (!dai->dev) 2973 if (dai == NULL)
2673 printk(KERN_WARNING "No device for DAI %s\n", dai->name); 2974 return -ENOMEM;
2674 2975
2675 if (!dai->ops) 2976 /* create DAI component name */
2676 dai->ops = &null_dai_ops; 2977 dai->name = fmt_single_name(dev, &dai->id);
2978 if (dai->name == NULL) {
2979 kfree(dai);
2980 return -ENOMEM;
2981 }
2677 2982
2678 INIT_LIST_HEAD(&dai->list); 2983 dai->dev = dev;
2984 dai->driver = dai_drv;
2985 if (!dai->driver->ops)
2986 dai->driver->ops = &null_dai_ops;
2679 2987
2680 mutex_lock(&client_mutex); 2988 mutex_lock(&client_mutex);
2681 list_add(&dai->list, &dai_list); 2989 list_add(&dai->list, &dai_list);
@@ -2693,13 +3001,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dai);
2693 * 3001 *
2694 * @dai: DAI to unregister 3002 * @dai: DAI to unregister
2695 */ 3003 */
2696void snd_soc_unregister_dai(struct snd_soc_dai *dai) 3004void snd_soc_unregister_dai(struct device *dev)
2697{ 3005{
3006 struct snd_soc_dai *dai;
3007
3008 list_for_each_entry(dai, &dai_list, list) {
3009 if (dev == dai->dev)
3010 goto found;
3011 }
3012 return;
3013
3014found:
2698 mutex_lock(&client_mutex); 3015 mutex_lock(&client_mutex);
2699 list_del(&dai->list); 3016 list_del(&dai->list);
2700 mutex_unlock(&client_mutex); 3017 mutex_unlock(&client_mutex);
2701 3018
2702 pr_debug("Unregistered DAI '%s'\n", dai->name); 3019 pr_debug("Unregistered DAI '%s'\n", dai->name);
3020 kfree(dai->name);
3021 kfree(dai);
2703} 3022}
2704EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); 3023EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
2705 3024
@@ -2709,21 +3028,50 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
2709 * @dai: Array of DAIs to register 3028 * @dai: Array of DAIs to register
2710 * @count: Number of DAIs 3029 * @count: Number of DAIs
2711 */ 3030 */
2712int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count) 3031int snd_soc_register_dais(struct device *dev,
3032 struct snd_soc_dai_driver *dai_drv, size_t count)
2713{ 3033{
2714 int i, ret; 3034 struct snd_soc_dai *dai;
3035 int i, ret = 0;
3036
3037 dev_dbg(dev, "dai register %s #%Zu\n", dev_name(dev), count);
2715 3038
2716 for (i = 0; i < count; i++) { 3039 for (i = 0; i < count; i++) {
2717 ret = snd_soc_register_dai(&dai[i]); 3040
2718 if (ret != 0) 3041 dai = kzalloc(sizeof(struct snd_soc_dai), GFP_KERNEL);
3042 if (dai == NULL)
3043 return -ENOMEM;
3044
3045 /* create DAI component name */
3046 dai->name = fmt_multiple_name(dev, &dai_drv[i]);
3047 if (dai->name == NULL) {
3048 kfree(dai);
3049 ret = -EINVAL;
2719 goto err; 3050 goto err;
3051 }
3052
3053 dai->dev = dev;
3054 dai->driver = &dai_drv[i];
3055 if (dai->driver->id)
3056 dai->id = dai->driver->id;
3057 else
3058 dai->id = i;
3059 if (!dai->driver->ops)
3060 dai->driver->ops = &null_dai_ops;
3061
3062 mutex_lock(&client_mutex);
3063 list_add(&dai->list, &dai_list);
3064 mutex_unlock(&client_mutex);
3065
3066 pr_debug("Registered DAI '%s'\n", dai->name);
2720 } 3067 }
2721 3068
3069 snd_soc_instantiate_cards();
2722 return 0; 3070 return 0;
2723 3071
2724err: 3072err:
2725 for (i--; i >= 0; i--) 3073 for (i--; i >= 0; i--)
2726 snd_soc_unregister_dai(&dai[i]); 3074 snd_soc_unregister_dai(dev);
2727 3075
2728 return ret; 3076 return ret;
2729} 3077}
@@ -2735,12 +3083,12 @@ EXPORT_SYMBOL_GPL(snd_soc_register_dais);
2735 * @dai: Array of DAIs to unregister 3083 * @dai: Array of DAIs to unregister
2736 * @count: Number of DAIs 3084 * @count: Number of DAIs
2737 */ 3085 */
2738void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count) 3086void snd_soc_unregister_dais(struct device *dev, size_t count)
2739{ 3087{
2740 int i; 3088 int i;
2741 3089
2742 for (i = 0; i < count; i++) 3090 for (i = 0; i < count; i++)
2743 snd_soc_unregister_dai(&dai[i]); 3091 snd_soc_unregister_dai(dev);
2744} 3092}
2745EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); 3093EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
2746 3094
@@ -2749,12 +3097,26 @@ EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
2749 * 3097 *
2750 * @platform: platform to register 3098 * @platform: platform to register
2751 */ 3099 */
2752int snd_soc_register_platform(struct snd_soc_platform *platform) 3100int snd_soc_register_platform(struct device *dev,
3101 struct snd_soc_platform_driver *platform_drv)
2753{ 3102{
2754 if (!platform->name) 3103 struct snd_soc_platform *platform;
2755 return -EINVAL; 3104
3105 dev_dbg(dev, "platform register %s\n", dev_name(dev));
2756 3106
2757 INIT_LIST_HEAD(&platform->list); 3107 platform = kzalloc(sizeof(struct snd_soc_platform), GFP_KERNEL);
3108 if (platform == NULL)
3109 return -ENOMEM;
3110
3111 /* create platform component name */
3112 platform->name = fmt_single_name(dev, &platform->id);
3113 if (platform->name == NULL) {
3114 kfree(platform);
3115 return -ENOMEM;
3116 }
3117
3118 platform->dev = dev;
3119 platform->driver = platform_drv;
2758 3120
2759 mutex_lock(&client_mutex); 3121 mutex_lock(&client_mutex);
2760 list_add(&platform->list, &platform_list); 3122 list_add(&platform->list, &platform_list);
@@ -2772,13 +3134,24 @@ EXPORT_SYMBOL_GPL(snd_soc_register_platform);
2772 * 3134 *
2773 * @platform: platform to unregister 3135 * @platform: platform to unregister
2774 */ 3136 */
2775void snd_soc_unregister_platform(struct snd_soc_platform *platform) 3137void snd_soc_unregister_platform(struct device *dev)
2776{ 3138{
3139 struct snd_soc_platform *platform;
3140
3141 list_for_each_entry(platform, &platform_list, list) {
3142 if (dev == platform->dev)
3143 goto found;
3144 }
3145 return;
3146
3147found:
2777 mutex_lock(&client_mutex); 3148 mutex_lock(&client_mutex);
2778 list_del(&platform->list); 3149 list_del(&platform->list);
2779 mutex_unlock(&client_mutex); 3150 mutex_unlock(&client_mutex);
2780 3151
2781 pr_debug("Unregistered platform '%s'\n", platform->name); 3152 pr_debug("Unregistered platform '%s'\n", platform->name);
3153 kfree(platform->name);
3154 kfree(platform);
2782} 3155}
2783EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); 3156EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
2784 3157
@@ -2820,22 +3193,61 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream)
2820 * 3193 *
2821 * @codec: codec to register 3194 * @codec: codec to register
2822 */ 3195 */
2823int snd_soc_register_codec(struct snd_soc_codec *codec) 3196int snd_soc_register_codec(struct device *dev,
3197 struct snd_soc_codec_driver *codec_drv,
3198 struct snd_soc_dai_driver *dai_drv, int num_dai)
2824{ 3199{
2825 int i; 3200 struct snd_soc_codec *codec;
3201 int ret, i;
2826 3202
2827 if (!codec->name) 3203 dev_dbg(dev, "codec register %s\n", dev_name(dev));
2828 return -EINVAL; 3204
3205 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
3206 if (codec == NULL)
3207 return -ENOMEM;
3208
3209 /* create CODEC component name */
3210 codec->name = fmt_single_name(dev, &codec->id);
3211 if (codec->name == NULL) {
3212 kfree(codec);
3213 return -ENOMEM;
3214 }
2829 3215
2830 /* The device should become mandatory over time */ 3216 /* allocate CODEC register cache */
2831 if (!codec->dev) 3217 if (codec_drv->reg_cache_size && codec_drv->reg_word_size) {
2832 printk(KERN_WARNING "No device for codec %s\n", codec->name);
2833 3218
2834 INIT_LIST_HEAD(&codec->list); 3219 if (codec_drv->reg_cache_default)
3220 codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
3221 codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL);
3222 else
3223 codec->reg_cache = kzalloc(codec_drv->reg_cache_size *
3224 codec_drv->reg_word_size, GFP_KERNEL);
2835 3225
2836 for (i = 0; i < codec->num_dai; i++) { 3226 if (codec->reg_cache == NULL) {
2837 fixup_codec_formats(&codec->dai[i].playback); 3227 kfree(codec->name);
2838 fixup_codec_formats(&codec->dai[i].capture); 3228 kfree(codec);
3229 return -ENOMEM;
3230 }
3231 }
3232
3233 codec->dev = dev;
3234 codec->driver = codec_drv;
3235 codec->bias_level = SND_SOC_BIAS_OFF;
3236 codec->num_dai = num_dai;
3237 mutex_init(&codec->mutex);
3238 INIT_LIST_HEAD(&codec->dapm_widgets);
3239 INIT_LIST_HEAD(&codec->dapm_paths);
3240
3241 for (i = 0; i < num_dai; i++) {
3242 fixup_codec_formats(&dai_drv[i].playback);
3243 fixup_codec_formats(&dai_drv[i].capture);
3244 }
3245
3246 /* register any DAIs */
3247 if (num_dai) {
3248 ret = snd_soc_register_dais(dev, dai_drv, num_dai);
3249 if (ret < 0)
3250 goto error;
2839 } 3251 }
2840 3252
2841 mutex_lock(&client_mutex); 3253 mutex_lock(&client_mutex);
@@ -2844,8 +3256,17 @@ int snd_soc_register_codec(struct snd_soc_codec *codec)
2844 mutex_unlock(&client_mutex); 3256 mutex_unlock(&client_mutex);
2845 3257
2846 pr_debug("Registered codec '%s'\n", codec->name); 3258 pr_debug("Registered codec '%s'\n", codec->name);
2847
2848 return 0; 3259 return 0;
3260
3261error:
3262 for (i--; i >= 0; i--)
3263 snd_soc_unregister_dai(dev);
3264
3265 if (codec->reg_cache)
3266 kfree(codec->reg_cache);
3267 kfree(codec->name);
3268 kfree(codec);
3269 return ret;
2849} 3270}
2850EXPORT_SYMBOL_GPL(snd_soc_register_codec); 3271EXPORT_SYMBOL_GPL(snd_soc_register_codec);
2851 3272
@@ -2854,13 +3275,32 @@ EXPORT_SYMBOL_GPL(snd_soc_register_codec);
2854 * 3275 *
2855 * @codec: codec to unregister 3276 * @codec: codec to unregister
2856 */ 3277 */
2857void snd_soc_unregister_codec(struct snd_soc_codec *codec) 3278void snd_soc_unregister_codec(struct device *dev)
2858{ 3279{
3280 struct snd_soc_codec *codec;
3281 int i;
3282
3283 list_for_each_entry(codec, &codec_list, list) {
3284 if (dev == codec->dev)
3285 goto found;
3286 }
3287 return;
3288
3289found:
3290 if (codec->num_dai)
3291 for (i = 0; i < codec->num_dai; i++)
3292 snd_soc_unregister_dai(dev);
3293
2859 mutex_lock(&client_mutex); 3294 mutex_lock(&client_mutex);
2860 list_del(&codec->list); 3295 list_del(&codec->list);
2861 mutex_unlock(&client_mutex); 3296 mutex_unlock(&client_mutex);
2862 3297
2863 pr_debug("Unregistered codec '%s'\n", codec->name); 3298 pr_debug("Unregistered codec '%s'\n", codec->name);
3299
3300 if (codec->reg_cache)
3301 kfree(codec->reg_cache);
3302 kfree(codec->name);
3303 kfree(codec);
2864} 3304}
2865EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); 3305EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
2866 3306
@@ -2873,10 +3313,23 @@ static int __init snd_soc_init(void)
2873 "ASoC: Failed to create debugfs directory\n"); 3313 "ASoC: Failed to create debugfs directory\n");
2874 debugfs_root = NULL; 3314 debugfs_root = NULL;
2875 } 3315 }
3316
3317 if (!debugfs_create_file("codecs", 0444, debugfs_root, NULL,
3318 &codec_list_fops))
3319 pr_warn("ASoC: Failed to create CODEC list debugfs file\n");
3320
3321 if (!debugfs_create_file("dais", 0444, debugfs_root, NULL,
3322 &dai_list_fops))
3323 pr_warn("ASoC: Failed to create DAI list debugfs file\n");
3324
3325 if (!debugfs_create_file("platforms", 0444, debugfs_root, NULL,
3326 &platform_list_fops))
3327 pr_warn("ASoC: Failed to create platform list debugfs file\n");
2876#endif 3328#endif
2877 3329
2878 return platform_driver_register(&soc_driver); 3330 return platform_driver_register(&soc_driver);
2879} 3331}
3332module_init(snd_soc_init);
2880 3333
2881static void __exit snd_soc_exit(void) 3334static void __exit snd_soc_exit(void)
2882{ 3335{
@@ -2885,8 +3338,6 @@ static void __exit snd_soc_exit(void)
2885#endif 3338#endif
2886 platform_driver_unregister(&soc_driver); 3339 platform_driver_unregister(&soc_driver);
2887} 3340}
2888
2889module_init(snd_soc_init);
2890module_exit(snd_soc_exit); 3341module_exit(snd_soc_exit);
2891 3342
2892/* Module information */ 3343/* Module information */
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 03cb7c05ebec..035cab85cb66 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 }
@@ -1188,8 +1183,9 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
1188static ssize_t dapm_widget_show(struct device *dev, 1183static ssize_t dapm_widget_show(struct device *dev,
1189 struct device_attribute *attr, char *buf) 1184 struct device_attribute *attr, char *buf)
1190{ 1185{
1191 struct snd_soc_device *devdata = dev_get_drvdata(dev); 1186 struct snd_soc_pcm_runtime *rtd =
1192 struct snd_soc_codec *codec = devdata->card->codec; 1187 container_of(dev, struct snd_soc_pcm_runtime, dev);
1188 struct snd_soc_codec *codec =rtd->codec;
1193 struct snd_soc_dapm_widget *w; 1189 struct snd_soc_dapm_widget *w;
1194 int count = 0; 1190 int count = 0;
1195 char *state = "not set"; 1191 char *state = "not set";
@@ -1998,9 +1994,10 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
1998 * 1994 *
1999 * Returns 0 for success else error. 1995 * Returns 0 for success else error.
2000 */ 1996 */
2001int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, 1997int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
2002 char *stream, int event) 1998 const char *stream, int event)
2003{ 1999{
2000 struct snd_soc_codec *codec = rtd->codec;
2004 struct snd_soc_dapm_widget *w; 2001 struct snd_soc_dapm_widget *w;
2005 2002
2006 if (stream == NULL) 2003 if (stream == NULL)
@@ -2168,25 +2165,19 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
2168 2165
2169/** 2166/**
2170 * snd_soc_dapm_free - free dapm resources 2167 * snd_soc_dapm_free - free dapm resources
2171 * @socdev: SoC device 2168 * @card: SoC device
2172 * 2169 *
2173 * Free all dapm widgets and resources. 2170 * Free all dapm widgets and resources.
2174 */ 2171 */
2175void snd_soc_dapm_free(struct snd_soc_device *socdev) 2172void snd_soc_dapm_free(struct snd_soc_codec *codec)
2176{ 2173{
2177 struct snd_soc_codec *codec = socdev->card->codec; 2174 snd_soc_dapm_sys_remove(codec->dev);
2178
2179 snd_soc_dapm_sys_remove(socdev->dev);
2180 dapm_free_widgets(codec); 2175 dapm_free_widgets(codec);
2181} 2176}
2182EXPORT_SYMBOL_GPL(snd_soc_dapm_free); 2177EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
2183 2178
2184/* 2179static void soc_dapm_shutdown_codec(struct snd_soc_codec *codec)
2185 * snd_soc_dapm_shutdown - callback for system shutdown
2186 */
2187void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
2188{ 2180{
2189 struct snd_soc_codec *codec = socdev->card->codec;
2190 struct snd_soc_dapm_widget *w; 2181 struct snd_soc_dapm_widget *w;
2191 LIST_HEAD(down_list); 2182 LIST_HEAD(down_list);
2192 int powerdown = 0; 2183 int powerdown = 0;
@@ -2203,12 +2194,23 @@ void snd_soc_dapm_shutdown(struct snd_soc_device *socdev)
2203 * standby. 2194 * standby.
2204 */ 2195 */
2205 if (powerdown) { 2196 if (powerdown) {
2206 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE); 2197 snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_PREPARE);
2207 dapm_seq_run(codec, &down_list, 0, dapm_down_seq); 2198 dapm_seq_run(codec, &down_list, 0, dapm_down_seq);
2208 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY); 2199 snd_soc_dapm_set_bias_level(NULL, codec, SND_SOC_BIAS_STANDBY);
2209 } 2200 }
2201}
2202
2203/*
2204 * snd_soc_dapm_shutdown - callback for system shutdown
2205 */
2206void snd_soc_dapm_shutdown(struct snd_soc_card *card)
2207{
2208 struct snd_soc_codec *codec;
2209
2210 list_for_each_entry(codec, &card->codec_dev_list, list)
2211 soc_dapm_shutdown_codec(codec);
2210 2212
2211 snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); 2213 snd_soc_dapm_set_bias_level(card, codec, SND_SOC_BIAS_OFF);
2212} 2214}
2213 2215
2214/* Module information */ 2216/* 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 */