From b5394770e00de0bdc38c89981219d0ddc61787af Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 3 Sep 2009 15:59:26 +0200 Subject: [PATCH] --- yaml --- r: 157761 b: refs/heads/master c: c631d03c6873b9e17906556e84fcafc42f26a7c2 h: refs/heads/master i: 157759: f2a887a6dfd671c0f650fa20a71e81f75f0d161a v: v3 --- [refs] | 2 +- trunk/MAINTAINERS | 3 +- trunk/Makefile | 2 +- trunk/arch/arm/mach-omap2/mcbsp.c | 5 - trunk/arch/arm/mach-pxa/include/mach/audio.h | 3 - trunk/arch/arm/plat-omap/dma.c | 10 - trunk/arch/arm/plat-omap/include/mach/mcbsp.h | 51 +- trunk/arch/arm/plat-omap/mcbsp.c | 401 +--- .../arm/plat-s3c/include/plat/audio-simtec.h | 37 - .../plat-s3c/include/plat/regs-s3c2412-iis.h | 5 - trunk/arch/ia64/kernel/dma-mapping.c | 4 +- trunk/arch/ia64/lib/ip_fast_csum.S | 8 +- trunk/arch/parisc/kernel/traps.c | 2 +- trunk/arch/powerpc/kernel/power7-pmu.c | 6 +- trunk/arch/powerpc/sysdev/xilinx_intc.c | 1 + trunk/arch/sparc/kernel/irq_64.c | 2 +- trunk/arch/sparc/kernel/nmi.c | 2 +- trunk/arch/sparc/prom/misc_64.c | 2 +- trunk/arch/sparc/prom/printf.c | 7 +- trunk/arch/x86/kernel/apic/probe_64.c | 10 - trunk/arch/x86/xen/enlighten.c | 2 - trunk/block/blk-sysfs.c | 2 +- trunk/crypto/algapi.c | 11 +- trunk/drivers/acpi/acpica/exstorob.c | 12 - trunk/drivers/acpi/video.c | 7 +- trunk/drivers/ata/ata_piix.c | 14 +- trunk/drivers/block/aoe/aoe.h | 2 +- trunk/drivers/block/aoe/aoeblk.c | 12 +- trunk/drivers/block/aoe/aoedev.c | 1 - trunk/drivers/char/agp/intel-agp.c | 8 +- trunk/drivers/char/n_tty.c | 3 +- trunk/drivers/char/pty.c | 10 +- trunk/drivers/cpufreq/cpufreq.c | 95 +- trunk/drivers/firewire/core-iso.c | 4 +- trunk/drivers/firewire/ohci.c | 14 - trunk/drivers/firewire/sbp2.c | 8 +- trunk/drivers/gpu/drm/i915/i915_drv.h | 7 - trunk/drivers/gpu/drm/i915/i915_gem.c | 99 +- trunk/drivers/gpu/drm/i915/intel_bios.c | 51 +- trunk/drivers/gpu/drm/i915/intel_crt.c | 11 +- trunk/drivers/gpu/drm/i915/intel_display.c | 87 +- trunk/drivers/gpu/drm/i915/intel_dp.c | 12 - trunk/drivers/gpu/drm/i915/intel_drv.h | 21 - trunk/drivers/gpu/drm/i915/intel_dvo.c | 6 - trunk/drivers/gpu/drm/i915/intel_hdmi.c | 18 +- trunk/drivers/gpu/drm/i915/intel_lvds.c | 2 - trunk/drivers/gpu/drm/i915/intel_sdvo.c | 13 +- trunk/drivers/gpu/drm/i915/intel_tv.c | 3 - trunk/drivers/gpu/drm/radeon/r300.c | 2 +- trunk/drivers/gpu/drm/radeon/radeon_asic.h | 6 +- trunk/drivers/gpu/drm/radeon/rs600.c | 65 - trunk/drivers/gpu/drm/radeon/rs690.c | 64 + trunk/drivers/gpu/drm/radeon/rv515.c | 2 +- trunk/drivers/ide/ide-cs.c | 1 - trunk/drivers/input/keyboard/atkbd.c | 35 - trunk/drivers/input/serio/i8042-x86ia64io.h | 8 - trunk/drivers/md/dm-exception-store.c | 13 - trunk/drivers/md/dm-exception-store.h | 4 - trunk/drivers/md/dm-log-userspace-base.c | 39 +- trunk/drivers/md/dm-log-userspace-transfer.c | 6 +- trunk/drivers/md/dm-log-userspace-transfer.h | 2 +- trunk/drivers/md/dm-raid1.c | 8 +- trunk/drivers/md/dm-snap-persistent.c | 88 +- trunk/drivers/md/dm-snap.c | 23 +- trunk/drivers/md/dm-stripe.c | 13 +- trunk/drivers/md/dm-table.c | 51 +- trunk/drivers/md/dm.c | 15 +- trunk/drivers/media/dvb/siano/Kconfig | 40 +- trunk/drivers/media/dvb/siano/Makefile | 9 +- trunk/drivers/media/dvb/siano/smsdvb.c | 44 - trunk/drivers/media/dvb/siano/smssdio.c | 54 +- .../drivers/media/video/em28xx/em28xx-cards.c | 44 +- trunk/drivers/media/video/em28xx/em28xx.h | 1 - trunk/drivers/media/video/gspca/Kconfig | 2 +- trunk/drivers/media/video/zr364xx.c | 2 +- trunk/drivers/mtd/devices/m25p80.c | 2 +- trunk/drivers/mtd/nftlcore.c | 15 +- trunk/drivers/net/gianfar.c | 1 - trunk/drivers/net/wireless/ipw2x00/ipw2200.c | 120 +- trunk/drivers/pci/iov.c | 23 - trunk/drivers/pci/pci.h | 13 - trunk/drivers/pci/setup-bus.c | 4 +- trunk/drivers/pci/setup-res.c | 8 +- trunk/drivers/platform/x86/toshiba_acpi.c | 1 - trunk/fs/autofs4/expire.c | 2 +- trunk/fs/compat.c | 17 +- trunk/fs/exec.c | 63 +- trunk/fs/ext2/namei.c | 4 - trunk/fs/jffs2/wbuf.c | 10 - trunk/fs/namei.c | 22 +- trunk/fs/nilfs2/btnode.c | 2 +- trunk/fs/notify/inotify/inotify_user.c | 20 +- trunk/fs/ocfs2/aops.c | 4 +- trunk/fs/ocfs2/dcache.c | 11 - trunk/fs/xfs/linux-2.6/xfs_ioctl32.c | 2 +- trunk/include/crypto/algapi.h | 1 - trunk/include/crypto/internal/skcipher.h | 4 +- trunk/include/linux/binfmts.h | 1 - trunk/include/linux/device-mapper.h | 4 - trunk/include/linux/dm-log-userspace.h | 13 +- trunk/include/linux/lmb.h | 2 +- trunk/include/linux/tty.h | 4 +- trunk/include/linux/workqueue.h | 15 - trunk/include/net/pkt_sched.h | 4 +- trunk/include/sound/ac97_codec.h | 9 - trunk/include/sound/memalloc.h | 6 - trunk/include/sound/pcm.h | 23 - trunk/include/sound/sh_fsi.h | 83 - trunk/include/sound/soc-dai.h | 40 +- trunk/include/sound/soc-dapm.h | 10 - trunk/include/sound/soc.h | 49 +- trunk/include/sound/uda1380.h | 22 - trunk/include/sound/wm8993.h | 44 - trunk/kernel/module.c | 7 +- trunk/kernel/perf_counter.c | 3 +- trunk/mm/nommu.c | 3 +- trunk/mm/page_alloc.c | 6 +- trunk/mm/percpu.c | 15 +- trunk/mm/slub.c | 4 +- trunk/net/core/sock.c | 2 +- trunk/net/sched/sch_api.c | 12 +- trunk/net/sched/sch_cbq.c | 25 +- trunk/net/sunrpc/clnt.c | 1 - trunk/security/integrity/ima/ima_main.c | 6 +- trunk/sound/arm/pxa2xx-ac97.c | 10 - trunk/sound/arm/pxa2xx-pcm-lib.c | 3 - trunk/sound/core/Kconfig | 4 - trunk/sound/core/Makefile | 2 +- trunk/sound/core/control.c | 34 +- trunk/sound/core/info.c | 4 +- trunk/sound/core/memalloc.c | 4 - trunk/sound/core/pcm_memory.c | 2 - trunk/sound/drivers/dummy.c | 413 ++-- trunk/sound/isa/cmi8330.c | 86 +- trunk/sound/pci/Kconfig | 4 +- trunk/sound/pci/ali5451/ali5451.c | 65 + trunk/sound/pci/azt3328.c | 1116 ++++----- trunk/sound/pci/azt3328.h | 103 +- trunk/sound/pci/cs46xx/cs46xx_lib.h | 2 +- trunk/sound/pci/ctxfi/ct20k2reg.h | 9 +- trunk/sound/pci/ctxfi/ctamixer.c | 20 +- trunk/sound/pci/ctxfi/ctatc.c | 77 +- trunk/sound/pci/ctxfi/ctdaio.c | 30 +- trunk/sound/pci/ctxfi/cthw20k1.c | 22 +- trunk/sound/pci/ctxfi/cthw20k2.c | 73 +- trunk/sound/pci/ctxfi/ctmixer.c | 8 +- trunk/sound/pci/ctxfi/ctpcm.c | 6 +- trunk/sound/pci/ctxfi/ctresource.c | 4 +- trunk/sound/pci/ctxfi/ctsrc.c | 10 +- trunk/sound/pci/ctxfi/ctvmem.c | 6 +- trunk/sound/pci/hda/patch_realtek.c | 34 +- trunk/sound/pci/hda/patch_via.c | 1 - trunk/sound/pci/oxygen/oxygen_lib.c | 3 - trunk/sound/pci/oxygen/oxygen_pcm.c | 2 - trunk/sound/soc/Kconfig | 1 - trunk/sound/soc/Makefile | 3 +- trunk/sound/soc/atmel/sam9g20_wm8731.c | 138 +- trunk/sound/soc/au1x/psc-ac97.c | 129 +- trunk/sound/soc/au1x/psc.h | 1 - trunk/sound/soc/blackfin/Kconfig | 31 +- trunk/sound/soc/blackfin/Makefile | 8 - trunk/sound/soc/blackfin/bf5xx-ac97.c | 10 +- trunk/sound/soc/blackfin/bf5xx-ad1836.c | 128 - trunk/sound/soc/blackfin/bf5xx-ad1938.c | 142 -- trunk/sound/soc/blackfin/bf5xx-ad73311.c | 16 +- trunk/sound/soc/blackfin/bf5xx-i2s.c | 8 +- trunk/sound/soc/blackfin/bf5xx-ssm2602.c | 16 +- trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c | 330 --- trunk/sound/soc/blackfin/bf5xx-tdm-pcm.h | 21 - trunk/sound/soc/blackfin/bf5xx-tdm.c | 343 --- trunk/sound/soc/blackfin/bf5xx-tdm.h | 14 - trunk/sound/soc/codecs/Kconfig | 44 - trunk/sound/soc/codecs/Makefile | 26 - trunk/sound/soc/codecs/ad1836.c | 446 ---- trunk/sound/soc/codecs/ad1836.h | 64 - trunk/sound/soc/codecs/ad1938.c | 682 ------ trunk/sound/soc/codecs/ad1938.h | 100 - trunk/sound/soc/codecs/ak4535.c | 16 + trunk/sound/soc/codecs/ak4642.c | 502 ---- trunk/sound/soc/codecs/ak4642.h | 20 - trunk/sound/soc/codecs/cs4270.c | 27 +- trunk/sound/soc/codecs/cx20442.c | 501 ---- trunk/sound/soc/codecs/cx20442.h | 20 - trunk/sound/soc/codecs/max9877.c | 308 --- trunk/sound/soc/codecs/max9877.h | 37 - trunk/sound/soc/codecs/spdif_transciever.c | 3 - trunk/sound/soc/codecs/stac9766.c | 4 +- trunk/sound/soc/codecs/tlv320aic3x.c | 233 +- trunk/sound/soc/codecs/tlv320aic3x.h | 2 + trunk/sound/soc/codecs/twl4030.c | 260 +- trunk/sound/soc/codecs/twl4030.h | 2 - trunk/sound/soc/codecs/uda134x.c | 2 +- trunk/sound/soc/codecs/uda1380.c | 313 ++- trunk/sound/soc/codecs/uda1380.h | 8 + trunk/sound/soc/codecs/wm8350.c | 51 +- trunk/sound/soc/codecs/wm8400.c | 26 +- trunk/sound/soc/codecs/wm8510.c | 175 +- trunk/sound/soc/codecs/wm8523.c | 699 ------ trunk/sound/soc/codecs/wm8523.h | 160 -- trunk/sound/soc/codecs/wm8580.c | 211 +- trunk/sound/soc/codecs/wm8728.c | 111 +- trunk/sound/soc/codecs/wm8731.c | 218 +- trunk/sound/soc/codecs/wm8750.c | 154 +- trunk/sound/soc/codecs/wm8753.c | 35 - trunk/sound/soc/codecs/wm8776.c | 744 ------ trunk/sound/soc/codecs/wm8776.h | 51 - trunk/sound/soc/codecs/wm8900.c | 345 +-- trunk/sound/soc/codecs/wm8903.c | 267 ++- trunk/sound/soc/codecs/wm8940.c | 160 +- trunk/sound/soc/codecs/wm8960.c | 233 +- trunk/sound/soc/codecs/wm8961.c | 1265 ---------- trunk/sound/soc/codecs/wm8961.h | 866 ------- trunk/sound/soc/codecs/wm8971.c | 127 +- trunk/sound/soc/codecs/wm8974.c | 808 ------- trunk/sound/soc/codecs/wm8974.h | 99 - trunk/sound/soc/codecs/wm8988.c | 180 +- trunk/sound/soc/codecs/wm8990.c | 194 +- trunk/sound/soc/codecs/wm8993.c | 1675 ------------- trunk/sound/soc/codecs/wm8993.h | 2132 ----------------- trunk/sound/soc/codecs/wm9081.c | 317 +-- trunk/sound/soc/codecs/wm9705.c | 2 +- trunk/sound/soc/codecs/wm_hubs.c | 743 ------ trunk/sound/soc/codecs/wm_hubs.h | 24 - trunk/sound/soc/davinci/Kconfig | 33 - trunk/sound/soc/davinci/Makefile | 5 - trunk/sound/soc/davinci/davinci-evm.c | 140 +- trunk/sound/soc/davinci/davinci-i2s.c | 340 ++- trunk/sound/soc/davinci/davinci-mcasp.c | 973 -------- trunk/sound/soc/davinci/davinci-mcasp.h | 60 - trunk/sound/soc/davinci/davinci-pcm.c | 10 +- trunk/sound/soc/davinci/davinci-pcm.h | 19 +- trunk/sound/soc/fsl/mpc5200_dma.c | 17 - trunk/sound/soc/fsl/mpc5200_psc_ac97.c | 3 +- trunk/sound/soc/imx/Kconfig | 21 - trunk/sound/soc/imx/Makefile | 10 - trunk/sound/soc/imx/mx1_mx2-pcm.c | 488 ---- trunk/sound/soc/imx/mx1_mx2-pcm.h | 26 - trunk/sound/soc/imx/mx27vis_wm8974.c | 317 --- trunk/sound/soc/imx/mxc-ssi.c | 868 ------- trunk/sound/soc/imx/mxc-ssi.h | 238 -- trunk/sound/soc/omap/Kconfig | 15 - trunk/sound/soc/omap/Makefile | 4 - trunk/sound/soc/omap/ams-delta.c | 646 ----- trunk/sound/soc/omap/n810.c | 12 +- trunk/sound/soc/omap/omap-mcbsp.c | 123 +- trunk/sound/soc/omap/omap-mcbsp.h | 4 - trunk/sound/soc/omap/omap-pcm.c | 53 +- trunk/sound/soc/omap/omap-pcm.h | 2 - trunk/sound/soc/omap/sdp3430.c | 18 +- trunk/sound/soc/omap/zoom2.c | 314 --- trunk/sound/soc/pxa/magician.c | 56 +- trunk/sound/soc/pxa/palm27x.c | 204 +- trunk/sound/soc/pxa/pxa-ssp.c | 77 +- trunk/sound/soc/pxa/pxa2xx-ac97.c | 12 +- trunk/sound/soc/s3c24xx/Kconfig | 35 +- trunk/sound/soc/s3c24xx/Makefile | 9 - .../sound/soc/s3c24xx/neo1973_gta02_wm8753.c | 498 ---- trunk/sound/soc/s3c24xx/s3c-i2s-v2.c | 17 +- trunk/sound/soc/s3c24xx/s3c2443-ac97.c | 20 +- trunk/sound/soc/s3c24xx/s3c24xx-i2s.c | 5 - trunk/sound/soc/s3c24xx/s3c24xx-pcm.c | 2 +- trunk/sound/soc/s3c24xx/s3c24xx_simtec.c | 394 --- trunk/sound/soc/s3c24xx/s3c24xx_simtec.h | 22 - .../sound/soc/s3c24xx/s3c24xx_simtec_hermes.c | 153 -- .../soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c | 137 -- trunk/sound/soc/s6000/s6105-ipcam.c | 12 +- trunk/sound/soc/sh/Kconfig | 15 +- trunk/sound/soc/sh/Makefile | 4 - trunk/sound/soc/sh/fsi-ak4642.c | 107 - trunk/sound/soc/sh/fsi.c | 1004 -------- trunk/sound/soc/soc-cache.c | 218 -- trunk/sound/soc/soc-core.c | 148 +- trunk/sound/soc/soc-dapm.c | 498 +--- trunk/sound/soc/soc-jack.c | 24 +- trunk/sound/soc/txx9/txx9aclc.c | 10 +- 275 files changed, 4466 insertions(+), 25663 deletions(-) delete mode 100644 trunk/arch/arm/plat-s3c/include/plat/audio-simtec.h delete mode 100644 trunk/include/sound/sh_fsi.h delete mode 100644 trunk/include/sound/uda1380.h delete mode 100644 trunk/include/sound/wm8993.h delete mode 100644 trunk/sound/soc/blackfin/bf5xx-ad1836.c delete mode 100644 trunk/sound/soc/blackfin/bf5xx-ad1938.c delete mode 100644 trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c delete mode 100644 trunk/sound/soc/blackfin/bf5xx-tdm-pcm.h delete mode 100644 trunk/sound/soc/blackfin/bf5xx-tdm.c delete mode 100644 trunk/sound/soc/blackfin/bf5xx-tdm.h delete mode 100644 trunk/sound/soc/codecs/ad1836.c delete mode 100644 trunk/sound/soc/codecs/ad1836.h delete mode 100644 trunk/sound/soc/codecs/ad1938.c delete mode 100644 trunk/sound/soc/codecs/ad1938.h delete mode 100644 trunk/sound/soc/codecs/ak4642.c delete mode 100644 trunk/sound/soc/codecs/ak4642.h delete mode 100644 trunk/sound/soc/codecs/cx20442.c delete mode 100644 trunk/sound/soc/codecs/cx20442.h delete mode 100644 trunk/sound/soc/codecs/max9877.c delete mode 100644 trunk/sound/soc/codecs/max9877.h delete mode 100644 trunk/sound/soc/codecs/wm8523.c delete mode 100644 trunk/sound/soc/codecs/wm8523.h delete mode 100644 trunk/sound/soc/codecs/wm8776.c delete mode 100644 trunk/sound/soc/codecs/wm8776.h delete mode 100644 trunk/sound/soc/codecs/wm8961.c delete mode 100644 trunk/sound/soc/codecs/wm8961.h delete mode 100644 trunk/sound/soc/codecs/wm8974.c delete mode 100644 trunk/sound/soc/codecs/wm8974.h delete mode 100644 trunk/sound/soc/codecs/wm8993.c delete mode 100644 trunk/sound/soc/codecs/wm8993.h delete mode 100644 trunk/sound/soc/codecs/wm_hubs.c delete mode 100644 trunk/sound/soc/codecs/wm_hubs.h delete mode 100644 trunk/sound/soc/davinci/davinci-mcasp.c delete mode 100644 trunk/sound/soc/davinci/davinci-mcasp.h delete mode 100644 trunk/sound/soc/imx/Kconfig delete mode 100644 trunk/sound/soc/imx/Makefile delete mode 100644 trunk/sound/soc/imx/mx1_mx2-pcm.c delete mode 100644 trunk/sound/soc/imx/mx1_mx2-pcm.h delete mode 100644 trunk/sound/soc/imx/mx27vis_wm8974.c delete mode 100644 trunk/sound/soc/imx/mxc-ssi.c delete mode 100644 trunk/sound/soc/imx/mxc-ssi.h delete mode 100644 trunk/sound/soc/omap/ams-delta.c delete mode 100644 trunk/sound/soc/omap/zoom2.c delete mode 100644 trunk/sound/soc/s3c24xx/neo1973_gta02_wm8753.c delete mode 100644 trunk/sound/soc/s3c24xx/s3c24xx_simtec.c delete mode 100644 trunk/sound/soc/s3c24xx/s3c24xx_simtec.h delete mode 100644 trunk/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c delete mode 100644 trunk/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c delete mode 100644 trunk/sound/soc/sh/fsi-ak4642.c delete mode 100644 trunk/sound/soc/sh/fsi.c delete mode 100644 trunk/sound/soc/soc-cache.c diff --git a/[refs] b/[refs] index 0d579064c7dc..104970c94ae8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f9892a52e2405b4c5fa205d4f18ad292cb7e40bb +refs/heads/master: c631d03c6873b9e17906556e84fcafc42f26a7c2 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 8dca9d89c6c1..60299a9a7adb 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -2239,7 +2239,8 @@ S: Maintained F: drivers/media/video/gspca/pac207.c GSPCA SN9C20X SUBDRIVER -M: Brian Johnson +P: Brian Johnson +M: brijohn@gmail.com L: linux-media@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git S: Maintained diff --git a/trunk/Makefile b/trunk/Makefile index 60de4ef31254..25c615e57302 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 31 -EXTRAVERSION = +EXTRAVERSION = -rc8 NAME = Man-Eating Seals of Antiquity # *DOCUMENTATION* diff --git a/trunk/arch/arm/mach-omap2/mcbsp.c b/trunk/arch/arm/mach-omap2/mcbsp.c index 0447d26d454b..99b6e1546311 100644 --- a/trunk/arch/arm/mach-omap2/mcbsp.c +++ b/trunk/arch/arm/mach-omap2/mcbsp.c @@ -128,7 +128,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP1_IRQ_RX, .tx_irq = INT_24XX_MCBSP1_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x6F, }, { .phys_base = OMAP34XX_MCBSP2_BASE, @@ -137,7 +136,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP2_IRQ_RX, .tx_irq = INT_24XX_MCBSP2_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x3FF, }, { .phys_base = OMAP34XX_MCBSP3_BASE, @@ -146,7 +144,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP3_IRQ_RX, .tx_irq = INT_24XX_MCBSP3_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x6F, }, { .phys_base = OMAP34XX_MCBSP4_BASE, @@ -155,7 +152,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP4_IRQ_RX, .tx_irq = INT_24XX_MCBSP4_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x6F, }, { .phys_base = OMAP34XX_MCBSP5_BASE, @@ -164,7 +160,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = { .rx_irq = INT_24XX_MCBSP5_IRQ_RX, .tx_irq = INT_24XX_MCBSP5_IRQ_TX, .ops = &omap2_mcbsp_ops, - .buffer_size = 0x6F, }, }; #define OMAP34XX_MCBSP_PDATA_SZ ARRAY_SIZE(omap34xx_mcbsp_pdata) diff --git a/trunk/arch/arm/mach-pxa/include/mach/audio.h b/trunk/arch/arm/mach-pxa/include/mach/audio.h index a3449e35a6f5..16eb02552d5d 100644 --- a/trunk/arch/arm/mach-pxa/include/mach/audio.h +++ b/trunk/arch/arm/mach-pxa/include/mach/audio.h @@ -3,12 +3,10 @@ #include #include -#include /* * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95) * a -1 value means no gpio will be used for reset - * @codec_pdata: AC97 codec platform_data * reset_gpio should only be specified for pxa27x CPUs where a silicon * bug prevents correct operation of the reset line. If not specified, @@ -22,7 +20,6 @@ typedef struct { void (*resume)(void *); void *priv; int reset_gpio; - void *codec_pdata[AC97_BUS_MAX_DEVICES]; } pxa2xx_audio_ops_t; extern void pxa_set_ac97_info(pxa2xx_audio_ops_t *ops); diff --git a/trunk/arch/arm/plat-omap/dma.c b/trunk/arch/arm/plat-omap/dma.c index 9b00f4cbc903..e3ac94f09006 100644 --- a/trunk/arch/arm/plat-omap/dma.c +++ b/trunk/arch/arm/plat-omap/dma.c @@ -1127,11 +1127,6 @@ int omap_dma_running(void) void omap_dma_link_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { - if (lch_head == lch_queue) { - dma_write(dma_read(CCR(lch_head)) | (3 << 8), - CCR(lch_head)); - return; - } printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); BUG(); return; @@ -1154,11 +1149,6 @@ EXPORT_SYMBOL(omap_dma_link_lch); void omap_dma_unlink_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { - if (lch_head == lch_queue) { - dma_write(dma_read(CCR(lch_head)) & ~(3 << 8), - CCR(lch_head)); - return; - } printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); BUG(); return; diff --git a/trunk/arch/arm/plat-omap/include/mach/mcbsp.h b/trunk/arch/arm/plat-omap/include/mach/mcbsp.h index 63a3f254af7b..bb154ea76769 100644 --- a/trunk/arch/arm/plat-omap/include/mach/mcbsp.h +++ b/trunk/arch/arm/plat-omap/include/mach/mcbsp.h @@ -134,11 +134,6 @@ #define OMAP_MCBSP_REG_XCERG 0x74 #define OMAP_MCBSP_REG_XCERH 0x78 #define OMAP_MCBSP_REG_SYSCON 0x8C -#define OMAP_MCBSP_REG_THRSH2 0x90 -#define OMAP_MCBSP_REG_THRSH1 0x94 -#define OMAP_MCBSP_REG_IRQST 0xA0 -#define OMAP_MCBSP_REG_IRQEN 0xA4 -#define OMAP_MCBSP_REG_WAKEUPEN 0xA8 #define OMAP_MCBSP_REG_XCCR 0xAC #define OMAP_MCBSP_REG_RCCR 0xB0 @@ -254,27 +249,8 @@ #define RDISABLE 0x0001 /********************** McBSP SYSCONFIG bit definitions ********************/ -#define CLOCKACTIVITY(value) ((value)<<8) -#define SIDLEMODE(value) ((value)<<3) -#define ENAWAKEUP 0x0004 #define SOFTRST 0x0002 -/********************** McBSP DMA operating modes **************************/ -#define MCBSP_DMA_MODE_ELEMENT 0 -#define MCBSP_DMA_MODE_THRESHOLD 1 -#define MCBSP_DMA_MODE_FRAME 2 - -/********************** McBSP WAKEUPEN bit definitions *********************/ -#define XEMPTYEOFEN 0x4000 -#define XRDYEN 0x0400 -#define XEOFEN 0x0200 -#define XFSXEN 0x0100 -#define XSYNCERREN 0x0080 -#define RRDYEN 0x0008 -#define REOFEN 0x0004 -#define RFSREN 0x0002 -#define RSYNCERREN 0x0001 - /* we don't do multichannel for now */ struct omap_mcbsp_reg_cfg { u16 spcr2; @@ -368,9 +344,6 @@ struct omap_mcbsp_platform_data { u8 dma_rx_sync, dma_tx_sync; u16 rx_irq, tx_irq; struct omap_mcbsp_ops *ops; -#ifdef CONFIG_ARCH_OMAP34XX - u16 buffer_size; -#endif }; struct omap_mcbsp { @@ -404,11 +377,6 @@ struct omap_mcbsp { struct omap_mcbsp_platform_data *pdata; struct clk *iclk; struct clk *fclk; -#ifdef CONFIG_ARCH_OMAP34XX - int dma_op_mode; - u16 max_tx_thres; - u16 max_rx_thres; -#endif }; extern struct omap_mcbsp **mcbsp_ptr; extern int omap_mcbsp_count; @@ -417,25 +385,10 @@ int omap_mcbsp_init(void); void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config, int size); void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config); -#ifdef CONFIG_ARCH_OMAP34XX -void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold); -void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold); -u16 omap_mcbsp_get_max_tx_threshold(unsigned int id); -u16 omap_mcbsp_get_max_rx_threshold(unsigned int id); -int omap_mcbsp_get_dma_op_mode(unsigned int id); -#else -static inline void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) -{ } -static inline void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) -{ } -static inline u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) { return 0; } -static inline u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) { return 0; } -static inline int omap_mcbsp_get_dma_op_mode(unsigned int id) { return 0; } -#endif int omap_mcbsp_request(unsigned int id); void omap_mcbsp_free(unsigned int id); -void omap_mcbsp_start(unsigned int id, int tx, int rx); -void omap_mcbsp_stop(unsigned int id, int tx, int rx); +void omap_mcbsp_start(unsigned int id); +void omap_mcbsp_stop(unsigned int id); void omap_mcbsp_xmit_word(unsigned int id, u32 word); u32 omap_mcbsp_recv_word(unsigned int id); diff --git a/trunk/arch/arm/plat-omap/mcbsp.c b/trunk/arch/arm/plat-omap/mcbsp.c index 8dc7927906f1..efa0e0111f38 100644 --- a/trunk/arch/arm/plat-omap/mcbsp.c +++ b/trunk/arch/arm/plat-omap/mcbsp.c @@ -198,170 +198,6 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) } EXPORT_SYMBOL(omap_mcbsp_config); -#ifdef CONFIG_ARCH_OMAP34XX -/* - * omap_mcbsp_set_tx_threshold configures how to deal - * with transmit threshold. the threshold value and handler can be - * configure in here. - */ -void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) -{ - struct omap_mcbsp *mcbsp; - void __iomem *io_base; - - if (!cpu_is_omap34xx()) - return; - - if (!omap_mcbsp_check_valid_id(id)) { - printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); - return; - } - mcbsp = id_to_mcbsp_ptr(id); - io_base = mcbsp->io_base; - - OMAP_MCBSP_WRITE(io_base, THRSH2, threshold); -} -EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold); - -/* - * omap_mcbsp_set_rx_threshold configures how to deal - * with receive threshold. the threshold value and handler can be - * configure in here. - */ -void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) -{ - struct omap_mcbsp *mcbsp; - void __iomem *io_base; - - if (!cpu_is_omap34xx()) - return; - - if (!omap_mcbsp_check_valid_id(id)) { - printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); - return; - } - mcbsp = id_to_mcbsp_ptr(id); - io_base = mcbsp->io_base; - - OMAP_MCBSP_WRITE(io_base, THRSH1, threshold); -} -EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold); - -/* - * omap_mcbsp_get_max_tx_thres just return the current configured - * maximum threshold for transmission - */ -u16 omap_mcbsp_get_max_tx_threshold(unsigned int id) -{ - struct omap_mcbsp *mcbsp; - - if (!omap_mcbsp_check_valid_id(id)) { - printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); - return -ENODEV; - } - mcbsp = id_to_mcbsp_ptr(id); - - return mcbsp->max_tx_thres; -} -EXPORT_SYMBOL(omap_mcbsp_get_max_tx_threshold); - -/* - * omap_mcbsp_get_max_rx_thres just return the current configured - * maximum threshold for reception - */ -u16 omap_mcbsp_get_max_rx_threshold(unsigned int id) -{ - struct omap_mcbsp *mcbsp; - - if (!omap_mcbsp_check_valid_id(id)) { - printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); - return -ENODEV; - } - mcbsp = id_to_mcbsp_ptr(id); - - return mcbsp->max_rx_thres; -} -EXPORT_SYMBOL(omap_mcbsp_get_max_rx_threshold); - -/* - * omap_mcbsp_get_dma_op_mode just return the current configured - * operating mode for the mcbsp channel - */ -int omap_mcbsp_get_dma_op_mode(unsigned int id) -{ - struct omap_mcbsp *mcbsp; - int dma_op_mode; - - if (!omap_mcbsp_check_valid_id(id)) { - printk(KERN_ERR "%s: Invalid id (%u)\n", __func__, id + 1); - return -ENODEV; - } - mcbsp = id_to_mcbsp_ptr(id); - - spin_lock_irq(&mcbsp->lock); - dma_op_mode = mcbsp->dma_op_mode; - spin_unlock_irq(&mcbsp->lock); - - return dma_op_mode; -} -EXPORT_SYMBOL(omap_mcbsp_get_dma_op_mode); - -static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) -{ - /* - * Enable wakup behavior, smart idle and all wakeups - * REVISIT: some wakeups may be unnecessary - */ - if (cpu_is_omap34xx()) { - u16 syscon; - - syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); - syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); - - spin_lock_irq(&mcbsp->lock); - if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { - syscon |= (ENAWAKEUP | SIDLEMODE(0x02) | - CLOCKACTIVITY(0x02)); - OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, - XRDYEN | RRDYEN); - } else { - syscon |= SIDLEMODE(0x01); - } - spin_unlock_irq(&mcbsp->lock); - - OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); - } -} - -static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) -{ - /* - * Disable wakup behavior, smart idle and all wakeups - */ - if (cpu_is_omap34xx()) { - u16 syscon; - - syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); - syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); - /* - * HW bug workaround - If no_idle mode is taken, we need to - * go to smart_idle before going to always_idle, or the - * device will not hit retention anymore. - */ - syscon |= SIDLEMODE(0x02); - OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); - - syscon &= ~(SIDLEMODE(0x03)); - OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); - - OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, 0); - } -} -#else -static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {} -static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {} -#endif - /* * We can choose between IRQ based or polled IO. * This needs to be called before omap_mcbsp_request(). @@ -421,9 +257,6 @@ int omap_mcbsp_request(unsigned int id) clk_enable(mcbsp->iclk); clk_enable(mcbsp->fclk); - /* Do procedure specific to omap34xx arch, if applicable */ - omap34xx_mcbsp_request(mcbsp); - /* * Make sure that transmitter, receiver and sample-rate generator are * not running before activating IRQs. @@ -472,9 +305,6 @@ void omap_mcbsp_free(unsigned int id) if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(id); - /* Do procedure specific to omap34xx arch, if applicable */ - omap34xx_mcbsp_free(mcbsp); - clk_disable(mcbsp->fclk); clk_disable(mcbsp->iclk); @@ -498,15 +328,14 @@ void omap_mcbsp_free(unsigned int id) EXPORT_SYMBOL(omap_mcbsp_free); /* - * Here we start the McBSP, by enabling transmitter, receiver or both. - * If no transmitter or receiver is active prior calling, then sample-rate - * generator and frame sync are started. + * Here we start the McBSP, by enabling the sample + * generator, both transmitter and receivers, + * and the frame sync. */ -void omap_mcbsp_start(unsigned int id, int tx, int rx) +void omap_mcbsp_start(unsigned int id) { struct omap_mcbsp *mcbsp; void __iomem *io_base; - int idle; u16 w; if (!omap_mcbsp_check_valid_id(id)) { @@ -519,58 +348,32 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; - idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | - OMAP_MCBSP_READ(io_base, SPCR1)) & 1); - - if (idle) { - /* Start the sample generator */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); - } + /* Start the sample generator */ + w = OMAP_MCBSP_READ(io_base, SPCR2); + OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); /* Enable transmitter and receiver */ - tx &= 1; w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | tx); + OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1); - rx &= 1; w = OMAP_MCBSP_READ(io_base, SPCR1); - OMAP_MCBSP_WRITE(io_base, SPCR1, w | rx); + OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1); - /* - * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec - * REVISIT: 100us may give enough time for two CLKSRG, however - * due to some unknown PM related, clock gating etc. reason it - * is now at 500us. - */ - udelay(500); + udelay(100); - if (idle) { - /* Start frame sync */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); - } - - if (cpu_is_omap2430() || cpu_is_omap34xx()) { - /* Release the transmitter and receiver */ - w = OMAP_MCBSP_READ(io_base, XCCR); - w &= ~(tx ? XDISABLE : 0); - OMAP_MCBSP_WRITE(io_base, XCCR, w); - w = OMAP_MCBSP_READ(io_base, RCCR); - w &= ~(rx ? RDISABLE : 0); - OMAP_MCBSP_WRITE(io_base, RCCR, w); - } + /* Start frame sync */ + w = OMAP_MCBSP_READ(io_base, SPCR2); + OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); /* Dump McBSP Regs */ omap_mcbsp_dump_reg(id); } EXPORT_SYMBOL(omap_mcbsp_start); -void omap_mcbsp_stop(unsigned int id, int tx, int rx) +void omap_mcbsp_stop(unsigned int id) { struct omap_mcbsp *mcbsp; void __iomem *io_base; - int idle; u16 w; if (!omap_mcbsp_check_valid_id(id)) { @@ -582,33 +385,16 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) io_base = mcbsp->io_base; /* Reset transmitter */ - tx &= 1; - if (cpu_is_omap2430() || cpu_is_omap34xx()) { - w = OMAP_MCBSP_READ(io_base, XCCR); - w |= (tx ? XDISABLE : 0); - OMAP_MCBSP_WRITE(io_base, XCCR, w); - } w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~tx); + OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1)); /* Reset receiver */ - rx &= 1; - if (cpu_is_omap2430() || cpu_is_omap34xx()) { - w = OMAP_MCBSP_READ(io_base, RCCR); - w |= (tx ? RDISABLE : 0); - OMAP_MCBSP_WRITE(io_base, RCCR, w); - } w = OMAP_MCBSP_READ(io_base, SPCR1); - OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~rx); - - idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | - OMAP_MCBSP_READ(io_base, SPCR1)) & 1); + OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1)); - if (idle) { - /* Reset the sample rate generator */ - w = OMAP_MCBSP_READ(io_base, SPCR2); - OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); - } + /* Reset the sample rate generator */ + w = OMAP_MCBSP_READ(io_base, SPCR2); + OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); } EXPORT_SYMBOL(omap_mcbsp_stop); @@ -1097,149 +883,6 @@ void omap_mcbsp_set_spi_mode(unsigned int id, } EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); -#ifdef CONFIG_ARCH_OMAP34XX -#define max_thres(m) (mcbsp->pdata->buffer_size) -#define valid_threshold(m, val) ((val) <= max_thres(m)) -#define THRESHOLD_PROP_BUILDER(prop) \ -static ssize_t prop##_show(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%u\n", mcbsp->prop); \ -} \ - \ -static ssize_t prop##_store(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t size) \ -{ \ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \ - unsigned long val; \ - int status; \ - \ - status = strict_strtoul(buf, 0, &val); \ - if (status) \ - return status; \ - \ - if (!valid_threshold(mcbsp, val)) \ - return -EDOM; \ - \ - mcbsp->prop = val; \ - return size; \ -} \ - \ -static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store); - -THRESHOLD_PROP_BUILDER(max_tx_thres); -THRESHOLD_PROP_BUILDER(max_rx_thres); - -static const char *dma_op_modes[] = { - "element", "threshold", "frame", -}; - -static ssize_t dma_op_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); - int dma_op_mode, i = 0; - ssize_t len = 0; - const char * const *s; - - spin_lock_irq(&mcbsp->lock); - dma_op_mode = mcbsp->dma_op_mode; - spin_unlock_irq(&mcbsp->lock); - - for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) { - if (dma_op_mode == i) - len += sprintf(buf + len, "[%s] ", *s); - else - len += sprintf(buf + len, "%s ", *s); - } - len += sprintf(buf + len, "\n"); - - return len; -} - -static ssize_t dma_op_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t size) -{ - struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); - const char * const *s; - int i = 0; - - for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) - if (sysfs_streq(buf, *s)) - break; - - if (i == ARRAY_SIZE(dma_op_modes)) - return -EINVAL; - - spin_lock_irq(&mcbsp->lock); - if (!mcbsp->free) { - size = -EBUSY; - goto unlock; - } - mcbsp->dma_op_mode = i; - -unlock: - spin_unlock_irq(&mcbsp->lock); - - return size; -} - -static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); - -static const struct attribute *additional_attrs[] = { - &dev_attr_max_tx_thres.attr, - &dev_attr_max_rx_thres.attr, - &dev_attr_dma_op_mode.attr, - NULL, -}; - -static const struct attribute_group additional_attr_group = { - .attrs = (struct attribute **)additional_attrs, -}; - -static inline int __devinit omap_additional_add(struct device *dev) -{ - return sysfs_create_group(&dev->kobj, &additional_attr_group); -} - -static inline void __devexit omap_additional_remove(struct device *dev) -{ - sysfs_remove_group(&dev->kobj, &additional_attr_group); -} - -static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) -{ - mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; - if (cpu_is_omap34xx()) { - mcbsp->max_tx_thres = max_thres(mcbsp); - mcbsp->max_rx_thres = max_thres(mcbsp); - /* - * REVISIT: Set dmap_op_mode to THRESHOLD as default - * for mcbsp2 instances. - */ - if (omap_additional_add(mcbsp->dev)) - dev_warn(mcbsp->dev, - "Unable to create additional controls\n"); - } else { - mcbsp->max_tx_thres = -EINVAL; - mcbsp->max_rx_thres = -EINVAL; - } -} - -static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) -{ - if (cpu_is_omap34xx()) - omap_additional_remove(mcbsp->dev); -} -#else -static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {} -static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {} -#endif /* CONFIG_ARCH_OMAP34XX */ - /* * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. * 730 has only 2 McBSP, and both of them are MPU peripherals. @@ -1310,10 +953,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) mcbsp->dev = &pdev->dev; mcbsp_ptr[id] = mcbsp; platform_set_drvdata(pdev, mcbsp); - - /* Initialize mcbsp properties for OMAP34XX if needed / applicable */ - omap34xx_device_init(mcbsp); - return 0; err_fclk: @@ -1337,8 +976,6 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) mcbsp->pdata->ops->free) mcbsp->pdata->ops->free(mcbsp->id); - omap34xx_device_exit(mcbsp); - clk_disable(mcbsp->fclk); clk_disable(mcbsp->iclk); clk_put(mcbsp->fclk); diff --git a/trunk/arch/arm/plat-s3c/include/plat/audio-simtec.h b/trunk/arch/arm/plat-s3c/include/plat/audio-simtec.h deleted file mode 100644 index 0f440b9168db..000000000000 --- a/trunk/arch/arm/plat-s3c/include/plat/audio-simtec.h +++ /dev/null @@ -1,37 +0,0 @@ -/* arch/arm/plat-s3c/include/plat/audio-simtec.h - * - * Copyright 2008 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Simtec Audio support. -*/ - -/** - * struct s3c24xx_audio_simtec_pdata - platform data for simtec audio - * @use_mpllin: Select codec clock from MPLLin - * @output_cdclk: Need to output CDCLK to the codec - * @have_mic: Set if we have a MIC socket - * @have_lout: Set if we have a LineOut socket - * @amp_gpio: GPIO pin to enable the AMP - * @amp_gain: Option GPIO to control AMP gain - */ -struct s3c24xx_audio_simtec_pdata { - unsigned int use_mpllin:1; - unsigned int output_cdclk:1; - - unsigned int have_mic:1; - unsigned int have_lout:1; - - int amp_gpio; - int amp_gain[2]; - - void (*startup)(void); -}; - -extern int simtec_audio_add(const char *codec_name, - struct s3c24xx_audio_simtec_pdata *pdata); diff --git a/trunk/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h b/trunk/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h index 07659dad1748..0fad7571030e 100644 --- a/trunk/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h +++ b/trunk/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h @@ -33,11 +33,6 @@ #define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1) #define S3C2412_IISCON_IIS_ACTIVE (1 << 0) -#define S3C64XX_IISMOD_BLC_16BIT (0 << 13) -#define S3C64XX_IISMOD_BLC_8BIT (1 << 13) -#define S3C64XX_IISMOD_BLC_24BIT (2 << 13) -#define S3C64XX_IISMOD_BLC_MASK (3 << 13) - #define S3C64XX_IISMOD_IMS_PCLK (0 << 10) #define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10) diff --git a/trunk/arch/ia64/kernel/dma-mapping.c b/trunk/arch/ia64/kernel/dma-mapping.c index f2c1600da097..39a3cd0a4173 100644 --- a/trunk/arch/ia64/kernel/dma-mapping.c +++ b/trunk/arch/ia64/kernel/dma-mapping.c @@ -10,9 +10,7 @@ EXPORT_SYMBOL(dma_ops); static int __init dma_init(void) { - dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); - - return 0; + dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); } fs_initcall(dma_init); diff --git a/trunk/arch/ia64/lib/ip_fast_csum.S b/trunk/arch/ia64/lib/ip_fast_csum.S index 620d9dc5220f..1f86aeb2c948 100644 --- a/trunk/arch/ia64/lib/ip_fast_csum.S +++ b/trunk/arch/ia64/lib/ip_fast_csum.S @@ -96,22 +96,20 @@ END(ip_fast_csum) GLOBAL_ENTRY(csum_ipv6_magic) ld4 r20=[in0],4 ld4 r21=[in1],4 - zxt4 in2=in2 + dep r15=in3,in2,32,16 ;; ld4 r22=[in0],4 ld4 r23=[in1],4 - dep r15=in3,in2,32,16 + mux1 r15=r15,@rev ;; ld4 r24=[in0],4 ld4 r25=[in1],4 - mux1 r15=r15,@rev + shr.u r15=r15,16 add r16=r20,r21 add r17=r22,r23 - zxt4 in4=in4 ;; ld4 r26=[in0],4 ld4 r27=[in1],4 - shr.u r15=r15,16 add r18=r24,r25 add r8=r16,r17 ;; diff --git a/trunk/arch/parisc/kernel/traps.c b/trunk/arch/parisc/kernel/traps.c index 8b58bf0b7d5a..528f0ff9b273 100644 --- a/trunk/arch/parisc/kernel/traps.c +++ b/trunk/arch/parisc/kernel/traps.c @@ -532,7 +532,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) /* Kill the user process later */ regs->iaoq[0] = 0 | 3; regs->iaoq[1] = regs->iaoq[0] + 4; - regs->iasq[0] = regs->iasq[1] = regs->sr[7]; + regs->iasq[0] = regs->iasq[0] = regs->sr[7]; regs->gr[0] &= ~PSW_B; return; } diff --git a/trunk/arch/powerpc/kernel/power7-pmu.c b/trunk/arch/powerpc/kernel/power7-pmu.c index 018d094d92f9..388cf57ad827 100644 --- a/trunk/arch/powerpc/kernel/power7-pmu.c +++ b/trunk/arch/powerpc/kernel/power7-pmu.c @@ -317,7 +317,7 @@ static int power7_generic_events[] = { */ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */ - [C(OP_READ)] = { 0xc880, 0x400f0 }, + [C(OP_READ)] = { 0x400f0, 0xc880 }, [C(OP_WRITE)] = { 0, 0x300f0 }, [C(OP_PREFETCH)] = { 0xd8b8, 0 }, }, @@ -327,8 +327,8 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { [C(OP_PREFETCH)] = { 0x408a, 0 }, }, [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */ - [C(OP_READ)] = { 0x16080, 0x26080 }, - [C(OP_WRITE)] = { 0x16082, 0x26082 }, + [C(OP_READ)] = { 0x6080, 0x6084 }, + [C(OP_WRITE)] = { 0x6082, 0x6086 }, [C(OP_PREFETCH)] = { 0, 0 }, }, [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */ diff --git a/trunk/arch/powerpc/sysdev/xilinx_intc.c b/trunk/arch/powerpc/sysdev/xilinx_intc.c index 40edad520770..3ee1fd37bbfc 100644 --- a/trunk/arch/powerpc/sysdev/xilinx_intc.c +++ b/trunk/arch/powerpc/sysdev/xilinx_intc.c @@ -234,6 +234,7 @@ static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc) generic_handle_irq(cascade_irq); /* Let xilinx_intc end the interrupt */ + desc->chip->ack(irq); desc->chip->unmask(irq); } diff --git a/trunk/arch/sparc/kernel/irq_64.c b/trunk/arch/sparc/kernel/irq_64.c index 8daab33fc17d..f0ee79055409 100644 --- a/trunk/arch/sparc/kernel/irq_64.c +++ b/trunk/arch/sparc/kernel/irq_64.c @@ -886,7 +886,7 @@ void notrace init_irqwork_curcpu(void) * Therefore you cannot make any OBP calls, not even prom_printf, * from these two routines. */ -static void __cpuinit notrace register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask) +static void __cpuinit register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask) { unsigned long num_entries = (qmask + 1) / 64; unsigned long status; diff --git a/trunk/arch/sparc/kernel/nmi.c b/trunk/arch/sparc/kernel/nmi.c index b75bf502cd42..2c0cc72d295b 100644 --- a/trunk/arch/sparc/kernel/nmi.c +++ b/trunk/arch/sparc/kernel/nmi.c @@ -103,7 +103,7 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) } if (!touched && __get_cpu_var(last_irq_sum) == sum) { local_inc(&__get_cpu_var(alert_counter)); - if (local_read(&__get_cpu_var(alert_counter)) == 30 * nmi_hz) + if (local_read(&__get_cpu_var(alert_counter)) == 5 * nmi_hz) die_nmi("BUG: NMI Watchdog detected LOCKUP", regs, panic_on_timeout); } else { diff --git a/trunk/arch/sparc/prom/misc_64.c b/trunk/arch/sparc/prom/misc_64.c index 39fc6af21b7c..eedffb4fec2d 100644 --- a/trunk/arch/sparc/prom/misc_64.c +++ b/trunk/arch/sparc/prom/misc_64.c @@ -88,7 +88,7 @@ void prom_cmdline(void) /* Drop into the prom, but completely terminate the program. * No chance of continuing. */ -void notrace prom_halt(void) +void prom_halt(void) { #ifdef CONFIG_SUN_LDOMS if (ldom_domaining_enabled) diff --git a/trunk/arch/sparc/prom/printf.c b/trunk/arch/sparc/prom/printf.c index ca869266b9f3..660943ee4c2a 100644 --- a/trunk/arch/sparc/prom/printf.c +++ b/trunk/arch/sparc/prom/printf.c @@ -14,14 +14,14 @@ */ #include -#include #include #include static char ppbuf[1024]; -void notrace prom_write(const char *buf, unsigned int n) +void +prom_write(const char *buf, unsigned int n) { char ch; @@ -33,7 +33,8 @@ void notrace prom_write(const char *buf, unsigned int n) } } -void notrace prom_printf(const char *fmt, ...) +void +prom_printf(const char *fmt, ...) { va_list args; int i; diff --git a/trunk/arch/x86/kernel/apic/probe_64.c b/trunk/arch/x86/kernel/apic/probe_64.c index fcec2f1d34a1..bc3e880f9b82 100644 --- a/trunk/arch/x86/kernel/apic/probe_64.c +++ b/trunk/arch/x86/kernel/apic/probe_64.c @@ -44,11 +44,6 @@ static struct apic *apic_probe[] __initdata = { NULL, }; -static int apicid_phys_pkg_id(int initial_apic_id, int index_msb) -{ - return hard_smp_processor_id() >> index_msb; -} - /* * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode. */ @@ -74,11 +69,6 @@ void __init default_setup_apic_routing(void) printk(KERN_INFO "Setting APIC routing to %s\n", apic->name); } - if (is_vsmp_box()) { - /* need to update phys_pkg_id */ - apic->phys_pkg_id = apicid_phys_pkg_id; - } - /* * Now that apic routing model is selected, configure the * fault handling for intr remapping. diff --git a/trunk/arch/x86/xen/enlighten.c b/trunk/arch/x86/xen/enlighten.c index eb33aaa8415d..e90540a46a0b 100644 --- a/trunk/arch/x86/xen/enlighten.c +++ b/trunk/arch/x86/xen/enlighten.c @@ -215,7 +215,6 @@ static __init void xen_init_cpuid_mask(void) (1 << X86_FEATURE_ACPI)); /* disable ACPI */ ax = 1; - cx = 0; xen_cpuid(&ax, &bx, &cx, &dx); /* cpuid claims we support xsave; try enabling it to see what happens */ @@ -1060,7 +1059,6 @@ asmlinkage void __init xen_start_kernel(void) /* set up basic CPUID stuff */ cpu_detect(&new_cpu_data); new_cpu_data.hard_math = 1; - new_cpu_data.wp_works_ok = 1; new_cpu_data.x86_capability[0] = cpuid_edx(1); #endif diff --git a/trunk/block/blk-sysfs.c b/trunk/block/blk-sysfs.c index d3aa2aadb3e0..418d63619680 100644 --- a/trunk/block/blk-sysfs.c +++ b/trunk/block/blk-sysfs.c @@ -133,7 +133,7 @@ queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) return -EINVAL; spin_lock_irq(q->queue_lock); - q->limits.max_sectors = max_sectors_kb << 1; + blk_queue_max_sectors(q, max_sectors_kb << 1); spin_unlock_irq(q->queue_lock); return ret; diff --git a/trunk/crypto/algapi.c b/trunk/crypto/algapi.c index df0863d56995..56c62e2858d5 100644 --- a/trunk/crypto/algapi.c +++ b/trunk/crypto/algapi.c @@ -692,7 +692,7 @@ int crypto_enqueue_request(struct crypto_queue *queue, } EXPORT_SYMBOL_GPL(crypto_enqueue_request); -void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset) +struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) { struct list_head *request; @@ -707,14 +707,7 @@ void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset) request = queue->list.next; list_del(request); - return (char *)list_entry(request, struct crypto_async_request, list) - - offset; -} -EXPORT_SYMBOL_GPL(__crypto_dequeue_request); - -struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue) -{ - return __crypto_dequeue_request(queue, 0); + return list_entry(request, struct crypto_async_request, list); } EXPORT_SYMBOL_GPL(crypto_dequeue_request); diff --git a/trunk/drivers/acpi/acpica/exstorob.c b/trunk/drivers/acpi/acpica/exstorob.c index 257706e7734f..67340cc70142 100644 --- a/trunk/drivers/acpi/acpica/exstorob.c +++ b/trunk/drivers/acpi/acpica/exstorob.c @@ -70,12 +70,6 @@ acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc, ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc); - /* If Source and Target are the same, just return */ - - if (source_desc == target_desc) { - return_ACPI_STATUS(AE_OK); - } - /* We know that source_desc is a buffer by now */ buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer); @@ -167,12 +161,6 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, ACPI_FUNCTION_TRACE_PTR(ex_store_string_to_string, source_desc); - /* If Source and Target are the same, just return */ - - if (source_desc == target_desc) { - return_ACPI_STATUS(AE_OK); - } - /* We know that source_desc is a string by now */ buffer = ACPI_CAST_PTR(u8, source_desc->string.pointer); diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index 60ea984c84a0..8851315ce858 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -2004,11 +2004,8 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) status = acpi_remove_notify_handler(device->dev->handle, ACPI_DEVICE_NOTIFY, acpi_video_device_notify); - if (device->backlight) { - sysfs_remove_link(&device->backlight->dev.kobj, "device"); - backlight_device_unregister(device->backlight); - device->backlight = NULL; - } + sysfs_remove_link(&device->backlight->dev.kobj, "device"); + backlight_device_unregister(device->backlight); if (device->cdev) { sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling"); diff --git a/trunk/drivers/ata/ata_piix.c b/trunk/drivers/ata/ata_piix.c index 9ac4e378992e..56b8a3ff1286 100644 --- a/trunk/drivers/ata/ata_piix.c +++ b/trunk/drivers/ata/ata_piix.c @@ -664,8 +664,6 @@ static int piix_pata_prereset(struct ata_link *link, unsigned long deadline) return ata_sff_prereset(link, deadline); } -static DEFINE_SPINLOCK(piix_lock); - /** * piix_set_piomode - Initialize host controller PATA PIO timings * @ap: Port whose timings we are configuring @@ -679,9 +677,8 @@ static DEFINE_SPINLOCK(piix_lock); static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) { - struct pci_dev *dev = to_pci_dev(ap->host->dev); - unsigned long flags; unsigned int pio = adev->pio_mode - XFER_PIO_0; + struct pci_dev *dev = to_pci_dev(ap->host->dev); unsigned int is_slave = (adev->devno != 0); unsigned int master_port= ap->port_no ? 0x42 : 0x40; unsigned int slave_port = 0x44; @@ -711,8 +708,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) if (adev->class == ATA_DEV_ATA) control |= 4; /* PPE enable */ - spin_lock_irqsave(&piix_lock, flags); - /* PIO configuration clears DTE unconditionally. It will be * programmed in set_dmamode which is guaranteed to be called * after set_piomode if any DMA mode is available. @@ -752,8 +747,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) udma_enable &= ~(1 << (2 * ap->port_no + adev->devno)); pci_write_config_byte(dev, 0x48, udma_enable); } - - spin_unlock_irqrestore(&piix_lock, flags); } /** @@ -771,7 +764,6 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev) static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, int isich) { struct pci_dev *dev = to_pci_dev(ap->host->dev); - unsigned long flags; u8 master_port = ap->port_no ? 0x42 : 0x40; u16 master_data; u8 speed = adev->dma_mode; @@ -785,8 +777,6 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in { 2, 1 }, { 2, 3 }, }; - spin_lock_irqsave(&piix_lock, flags); - pci_read_config_word(dev, master_port, &master_data); if (ap->udma_mask) pci_read_config_byte(dev, 0x48, &udma_enable); @@ -877,8 +867,6 @@ static void do_pata_set_dmamode(struct ata_port *ap, struct ata_device *adev, in /* Don't scribble on 0x48 if the controller does not support UDMA */ if (ap->udma_mask) pci_write_config_byte(dev, 0x48, udma_enable); - - spin_unlock_irqrestore(&piix_lock, flags); } /** diff --git a/trunk/drivers/block/aoe/aoe.h b/trunk/drivers/block/aoe/aoe.h index db195abad698..5e41e6dd657b 100644 --- a/trunk/drivers/block/aoe/aoe.h +++ b/trunk/drivers/block/aoe/aoe.h @@ -155,7 +155,7 @@ struct aoedev { u16 fw_ver; /* version of blade's firmware */ struct work_struct work;/* disk create work struct */ struct gendisk *gd; - struct request_queue *blkq; + struct request_queue blkq; struct hd_geometry geo; sector_t ssize; struct timer_list timer; diff --git a/trunk/drivers/block/aoe/aoeblk.c b/trunk/drivers/block/aoe/aoeblk.c index 1e15889c4b98..2307a271bdc9 100644 --- a/trunk/drivers/block/aoe/aoeblk.c +++ b/trunk/drivers/block/aoe/aoeblk.c @@ -264,12 +264,9 @@ aoeblk_gdalloc(void *vp) goto err_disk; } - d->blkq = blk_alloc_queue(GFP_KERNEL); - if (!d->blkq) + blk_queue_make_request(&d->blkq, aoeblk_make_request); + if (bdi_init(&d->blkq.backing_dev_info)) goto err_mempool; - blk_queue_make_request(d->blkq, aoeblk_make_request); - if (bdi_init(&d->blkq->backing_dev_info)) - goto err_blkq; spin_lock_irqsave(&d->lock, flags); gd->major = AOE_MAJOR; gd->first_minor = d->sysminor * AOE_PARTITIONS; @@ -279,7 +276,7 @@ aoeblk_gdalloc(void *vp) snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%d", d->aoemajor, d->aoeminor); - gd->queue = d->blkq; + gd->queue = &d->blkq; d->gd = gd; d->flags &= ~DEVFL_GDALLOC; d->flags |= DEVFL_UP; @@ -290,9 +287,6 @@ aoeblk_gdalloc(void *vp) aoedisk_add_sysfs(d); return; -err_blkq: - blk_cleanup_queue(d->blkq); - d->blkq = NULL; err_mempool: mempool_destroy(d->bufpool); err_disk: diff --git a/trunk/drivers/block/aoe/aoedev.c b/trunk/drivers/block/aoe/aoedev.c index fa67027789aa..eeea477d9601 100644 --- a/trunk/drivers/block/aoe/aoedev.c +++ b/trunk/drivers/block/aoe/aoedev.c @@ -113,7 +113,6 @@ aoedev_freedev(struct aoedev *d) if (d->bufpool) mempool_destroy(d->bufpool); skbpoolfree(d); - blk_cleanup_queue(d->blkq); kfree(d); } diff --git a/trunk/drivers/char/agp/intel-agp.c b/trunk/drivers/char/agp/intel-agp.c index c58557790585..8c9d50db5c3a 100644 --- a/trunk/drivers/char/agp/intel-agp.c +++ b/trunk/drivers/char/agp/intel-agp.c @@ -49,7 +49,6 @@ #define PCI_DEVICE_ID_INTEL_IGDNG_D_HB 0x0040 #define PCI_DEVICE_ID_INTEL_IGDNG_D_IG 0x0042 #define PCI_DEVICE_ID_INTEL_IGDNG_M_HB 0x0044 -#define PCI_DEVICE_ID_INTEL_IGDNG_MA_HB 0x0062 #define PCI_DEVICE_ID_INTEL_IGDNG_M_IG 0x0046 /* cover 915 and 945 variants */ @@ -82,8 +81,7 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G41_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_D_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_MA_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDNG_M_HB) extern int agp_memory_reserved; @@ -1218,7 +1216,6 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) case PCI_DEVICE_ID_INTEL_G41_HB: case PCI_DEVICE_ID_INTEL_IGDNG_D_HB: case PCI_DEVICE_ID_INTEL_IGDNG_M_HB: - case PCI_DEVICE_ID_INTEL_IGDNG_MA_HB: *gtt_offset = *gtt_size = MB(2); break; default: @@ -2198,8 +2195,6 @@ static const struct intel_driver_description { "IGDNG/D", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IGDNG_M_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, "IGDNG/M", NULL, &intel_i965_driver }, - { PCI_DEVICE_ID_INTEL_IGDNG_MA_HB, PCI_DEVICE_ID_INTEL_IGDNG_M_IG, 0, - "IGDNG/MA", NULL, &intel_i965_driver }, { 0, 0, 0, NULL, NULL, NULL } }; @@ -2403,7 +2398,6 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_G41_HB), ID(PCI_DEVICE_ID_INTEL_IGDNG_D_HB), ID(PCI_DEVICE_ID_INTEL_IGDNG_M_HB), - ID(PCI_DEVICE_ID_INTEL_IGDNG_MA_HB), { } }; diff --git a/trunk/drivers/char/n_tty.c b/trunk/drivers/char/n_tty.c index 4e28b35024ec..973be2f44195 100644 --- a/trunk/drivers/char/n_tty.c +++ b/trunk/drivers/char/n_tty.c @@ -300,7 +300,8 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space) if (space < 2) return -1; tty->canon_column = tty->column = 0; - tty->ops->write(tty, "\r\n", 2); + tty_put_char(tty, '\r'); + tty_put_char(tty, c); return 2; } tty->canon_column = tty->column; diff --git a/trunk/drivers/char/pty.c b/trunk/drivers/char/pty.c index b33d6688e910..d083c73d784a 100644 --- a/trunk/drivers/char/pty.c +++ b/trunk/drivers/char/pty.c @@ -109,13 +109,21 @@ static int pty_space(struct tty_struct *to) * the other side of the pty/tty pair. */ -static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) +static int pty_write(struct tty_struct *tty, const unsigned char *buf, + int count) { struct tty_struct *to = tty->link; + int c; if (tty->stopped) return 0; + /* This isn't locked but our 8K is quite sloppy so no + big deal */ + + c = pty_space(to); + if (c > count) + c = count; if (c > 0) { /* Stuff the data into the input queue of the other end */ c = tty_insert_flip_string(to, buf, c); diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index 2968ed6a9c49..fd69086d08d5 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -1250,11 +1250,20 @@ static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg) { int ret = 0; +#ifdef __powerpc__ int cpu = sysdev->id; + unsigned int cur_freq = 0; struct cpufreq_policy *cpu_policy; dprintk("suspending cpu %u\n", cpu); + /* + * This whole bogosity is here because Powerbooks are made of fail. + * No sane platform should need any of the code below to be run. + * (it's entirely the wrong thing to do, as driver->get may + * reenable interrupts on some architectures). + */ + if (!cpu_online(cpu)) return 0; @@ -1273,13 +1282,47 @@ static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg) if (cpufreq_driver->suspend) { ret = cpufreq_driver->suspend(cpu_policy, pmsg); - if (ret) + if (ret) { printk(KERN_ERR "cpufreq: suspend failed in ->suspend " "step on CPU %u\n", cpu_policy->cpu); + goto out; + } + } + + if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS) + goto out; + + if (cpufreq_driver->get) + cur_freq = cpufreq_driver->get(cpu_policy->cpu); + + if (!cur_freq || !cpu_policy->cur) { + printk(KERN_ERR "cpufreq: suspend failed to assert current " + "frequency is what timing core thinks it is.\n"); + goto out; + } + + if (unlikely(cur_freq != cpu_policy->cur)) { + struct cpufreq_freqs freqs; + + if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) + dprintk("Warning: CPU frequency is %u, " + "cpufreq assumed %u kHz.\n", + cur_freq, cpu_policy->cur); + + freqs.cpu = cpu; + freqs.old = cpu_policy->cur; + freqs.new = cur_freq; + + srcu_notifier_call_chain(&cpufreq_transition_notifier_list, + CPUFREQ_SUSPENDCHANGE, &freqs); + adjust_jiffies(CPUFREQ_SUSPENDCHANGE, &freqs); + + cpu_policy->cur = cur_freq; } out: cpufreq_cpu_put(cpu_policy); +#endif /* __powerpc__ */ return ret; } @@ -1287,21 +1330,24 @@ static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg) * cpufreq_resume - restore proper CPU frequency handling after resume * * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) - * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are - * restored. It will verify that the current freq is in sync with - * what we believe it to be. This is a bit later than when it - * should be, but nonethteless it's better than calling - * cpufreq_driver->get() here which might re-enable interrupts... + * 2.) if ->target and !CPUFREQ_CONST_LOOPS: verify we're in sync + * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are + * restored. */ static int cpufreq_resume(struct sys_device *sysdev) { int ret = 0; +#ifdef __powerpc__ int cpu = sysdev->id; struct cpufreq_policy *cpu_policy; dprintk("resuming cpu %u\n", cpu); + /* As with the ->suspend method, all the code below is + * only necessary because Powerbooks suck. + * See commit 42d4dc3f4e1e for jokes. */ + if (!cpu_online(cpu)) return 0; @@ -1327,10 +1373,45 @@ static int cpufreq_resume(struct sys_device *sysdev) } } - schedule_work(&cpu_policy->update); + if (!(cpufreq_driver->flags & CPUFREQ_CONST_LOOPS)) { + unsigned int cur_freq = 0; + + if (cpufreq_driver->get) + cur_freq = cpufreq_driver->get(cpu_policy->cpu); + + if (!cur_freq || !cpu_policy->cur) { + printk(KERN_ERR "cpufreq: resume failed to assert " + "current frequency is what timing core " + "thinks it is.\n"); + goto out; + } + + if (unlikely(cur_freq != cpu_policy->cur)) { + struct cpufreq_freqs freqs; + if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN)) + dprintk("Warning: CPU frequency " + "is %u, cpufreq assumed %u kHz.\n", + cur_freq, cpu_policy->cur); + + freqs.cpu = cpu; + freqs.old = cpu_policy->cur; + freqs.new = cur_freq; + + srcu_notifier_call_chain( + &cpufreq_transition_notifier_list, + CPUFREQ_RESUMECHANGE, &freqs); + adjust_jiffies(CPUFREQ_RESUMECHANGE, &freqs); + + cpu_policy->cur = cur_freq; + } + } + +out: + schedule_work(&cpu_policy->update); fail: cpufreq_cpu_put(cpu_policy); +#endif /* __powerpc__ */ return ret; } diff --git a/trunk/drivers/firewire/core-iso.c b/trunk/drivers/firewire/core-iso.c index 1c0b504a42f3..110e731f5574 100644 --- a/trunk/drivers/firewire/core-iso.c +++ b/trunk/drivers/firewire/core-iso.c @@ -196,7 +196,7 @@ static int manage_bandwidth(struct fw_card *card, int irm_id, int generation, switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, CSR_REGISTER_BASE + CSR_BANDWIDTH_AVAILABLE, - data, 8)) { + data, sizeof(data))) { case RCODE_GENERATION: /* A generation change frees all bandwidth. */ return allocate ? -EAGAIN : bandwidth; @@ -233,7 +233,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, data[1] = old ^ c; switch (fw_run_transaction(card, TCODE_LOCK_COMPARE_SWAP, irm_id, generation, SCODE_100, - offset, data, 8)) { + offset, data, sizeof(data))) { case RCODE_GENERATION: /* A generation change frees all channels. */ return allocate ? -EAGAIN : i; diff --git a/trunk/drivers/firewire/ohci.c b/trunk/drivers/firewire/ohci.c index 76b321bb73f9..ecddd11b797a 100644 --- a/trunk/drivers/firewire/ohci.c +++ b/trunk/drivers/firewire/ohci.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -2373,9 +2372,6 @@ static void ohci_pmac_off(struct pci_dev *dev) #define ohci_pmac_off(dev) #endif /* CONFIG_PPC_PMAC */ -#define PCI_VENDOR_ID_AGERE PCI_VENDOR_ID_ATT -#define PCI_DEVICE_ID_AGERE_FW643 0x5901 - static int __devinit pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) { @@ -2426,16 +2422,6 @@ static int __devinit pci_probe(struct pci_dev *dev, version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; ohci->use_dualbuffer = version >= OHCI_VERSION_1_1; - /* dual-buffer mode is broken if more than one IR context is active */ - if (dev->vendor == PCI_VENDOR_ID_AGERE && - dev->device == PCI_DEVICE_ID_AGERE_FW643) - ohci->use_dualbuffer = false; - - /* dual-buffer mode is broken */ - if (dev->vendor == PCI_VENDOR_ID_RICOH && - dev->device == PCI_DEVICE_ID_RICOH_R5C832) - ohci->use_dualbuffer = false; - /* x86-32 currently doesn't use highmem for dma_alloc_coherent */ #if !defined(CONFIG_X86_32) /* dual-buffer mode is broken with descriptor addresses above 2G */ diff --git a/trunk/drivers/firewire/sbp2.c b/trunk/drivers/firewire/sbp2.c index e5df822a8130..8d51568ee143 100644 --- a/trunk/drivers/firewire/sbp2.c +++ b/trunk/drivers/firewire/sbp2.c @@ -456,12 +456,12 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, } spin_unlock_irqrestore(&card->lock, flags); - if (&orb->link != &lu->orb_list) { + if (&orb->link != &lu->orb_list) orb->callback(orb, &status); - kref_put(&orb->kref, free_orb); - } else { + else fw_error("status write for unknown orb\n"); - } + + kref_put(&orb->kref, free_orb); fw_send_response(card, request, RCODE_COMPLETE); } diff --git a/trunk/drivers/gpu/drm/i915/i915_drv.h b/trunk/drivers/gpu/drm/i915/i915_drv.h index 5b4f87e55621..7537f57d8a87 100644 --- a/trunk/drivers/gpu/drm/i915/i915_drv.h +++ b/trunk/drivers/gpu/drm/i915/i915_drv.h @@ -222,7 +222,6 @@ typedef struct drm_i915_private { unsigned int edp_support:1; int lvds_ssc_freq; - int crt_ddc_bus; /* -1 = unknown, else GPIO to use for CRT DDC */ struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */ int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */ int num_fence_regs; /* 8 on pre-965, 16 otherwise */ @@ -385,9 +384,6 @@ typedef struct drm_i915_private { */ struct list_head inactive_list; - /** LRU list of objects with fence regs on them. */ - struct list_head fence_list; - /** * List of breadcrumbs associated with GPU requests currently * outstanding. @@ -455,9 +451,6 @@ struct drm_i915_gem_object { /** This object's place on the active/flushing/inactive lists */ struct list_head list; - /** This object's place on the fenced object LRU */ - struct list_head fence_list; - /** * This is set if the object is on the active or flushing lists * (has pending rendering), and is not set if it's on inactive (ready diff --git a/trunk/drivers/gpu/drm/i915/i915_gem.c b/trunk/drivers/gpu/drm/i915/i915_gem.c index 80e5ba490dc2..140bee142fc2 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem.c @@ -978,7 +978,6 @@ int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_set_domain *args = data; struct drm_gem_object *obj; uint32_t read_domains = args->read_domains; @@ -1011,18 +1010,8 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, obj, obj->size, read_domains, write_domain); #endif if (read_domains & I915_GEM_DOMAIN_GTT) { - struct drm_i915_gem_object *obj_priv = obj->driver_private; - ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); - /* Update the LRU on the fence for the CPU access that's - * about to occur. - */ - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { - list_move_tail(&obj_priv->fence_list, - &dev_priv->mm.fence_list); - } - /* Silently promote "you're not bound, there was nothing to do" * to success, since the client was just asking us to * make sure everything was done. @@ -1166,7 +1155,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } /* Need a new fence register? */ - if (obj_priv->tiling_mode != I915_TILING_NONE) { + if (obj_priv->fence_reg == I915_FENCE_REG_NONE && + obj_priv->tiling_mode != I915_TILING_NONE) { ret = i915_gem_object_get_fence_reg(obj); if (ret) { mutex_unlock(&dev->struct_mutex); @@ -2218,12 +2208,6 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) struct drm_i915_gem_object *old_obj_priv = NULL; int i, ret, avail; - /* Just update our place in the LRU if our fence is getting used. */ - if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { - list_move_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list); - return 0; - } - switch (obj_priv->tiling_mode) { case I915_TILING_NONE: WARN(1, "allocating a fence for non-tiled object?\n"); @@ -2245,6 +2229,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) } /* First try to find a free reg */ +try_again: avail = 0; for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { reg = &dev_priv->fence_regs[i]; @@ -2258,62 +2243,63 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) /* None available, try to steal one or wait for a user to finish */ if (i == dev_priv->num_fence_regs) { - struct drm_gem_object *old_obj = NULL; + uint32_t seqno = dev_priv->mm.next_gem_seqno; if (avail == 0) return -ENOSPC; - list_for_each_entry(old_obj_priv, &dev_priv->mm.fence_list, - fence_list) { - old_obj = old_obj_priv->obj; + for (i = dev_priv->fence_reg_start; + i < dev_priv->num_fence_regs; i++) { + uint32_t this_seqno; + + reg = &dev_priv->fence_regs[i]; + old_obj_priv = reg->obj->driver_private; if (old_obj_priv->pin_count) continue; - /* Take a reference, as otherwise the wait_rendering - * below may cause the object to get freed out from - * under us. - */ - drm_gem_object_reference(old_obj); - /* i915 uses fences for GPU access to tiled buffers */ if (IS_I965G(dev) || !old_obj_priv->active) break; - /* This brings the object to the head of the LRU if it - * had been written to. The only way this should - * result in us waiting longer than the expected - * optimal amount of time is if there was a - * fence-using buffer later that was read-only. - */ - i915_gem_object_flush_gpu_write_domain(old_obj); - ret = i915_gem_object_wait_rendering(old_obj); - if (ret != 0) { - drm_gem_object_unreference(old_obj); - return ret; + /* find the seqno of the first available fence */ + this_seqno = old_obj_priv->last_rendering_seqno; + if (this_seqno != 0 && + reg->obj->write_domain == 0 && + i915_seqno_passed(seqno, this_seqno)) + seqno = this_seqno; + } + + /* + * Now things get ugly... we have to wait for one of the + * objects to finish before trying again. + */ + if (i == dev_priv->num_fence_regs) { + if (seqno == dev_priv->mm.next_gem_seqno) { + i915_gem_flush(dev, + I915_GEM_GPU_DOMAINS, + I915_GEM_GPU_DOMAINS); + seqno = i915_add_request(dev, NULL, + I915_GEM_GPU_DOMAINS); + if (seqno == 0) + return -ENOMEM; } - break; + ret = i915_wait_request(dev, seqno); + if (ret) + return ret; + goto try_again; } /* * Zap this virtual mapping so we can set up a fence again * for this object next time we need it. */ - i915_gem_release_mmap(old_obj); - - i = old_obj_priv->fence_reg; - reg = &dev_priv->fence_regs[i]; - + i915_gem_release_mmap(reg->obj); old_obj_priv->fence_reg = I915_FENCE_REG_NONE; - list_del_init(&old_obj_priv->fence_list); - - drm_gem_object_unreference(old_obj); } obj_priv->fence_reg = i; - list_add_tail(&obj_priv->fence_list, &dev_priv->mm.fence_list); - reg->obj = obj; if (IS_I965G(dev)) @@ -2356,7 +2342,6 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; obj_priv->fence_reg = I915_FENCE_REG_NONE; - list_del_init(&obj_priv->fence_list); } /** @@ -3610,7 +3595,9 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) * Pre-965 chips need a fence register set up in order to * properly handle tiled surfaces. */ - if (!IS_I965G(dev) && obj_priv->tiling_mode != I915_TILING_NONE) { + if (!IS_I965G(dev) && + obj_priv->fence_reg == I915_FENCE_REG_NONE && + obj_priv->tiling_mode != I915_TILING_NONE) { ret = i915_gem_object_get_fence_reg(obj); if (ret != 0) { if (ret != -EBUSY && ret != -ERESTARTSYS) @@ -3819,7 +3806,6 @@ int i915_gem_init_object(struct drm_gem_object *obj) obj_priv->obj = obj; obj_priv->fence_reg = I915_FENCE_REG_NONE; INIT_LIST_HEAD(&obj_priv->list); - INIT_LIST_HEAD(&obj_priv->fence_list); return 0; } @@ -4232,11 +4218,15 @@ int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + int ret; + if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; + ret = i915_gem_idle(dev); drm_irq_uninstall(dev); - return i915_gem_idle(dev); + + return ret; } void @@ -4263,7 +4253,6 @@ i915_gem_load(struct drm_device *dev) INIT_LIST_HEAD(&dev_priv->mm.flushing_list); INIT_LIST_HEAD(&dev_priv->mm.inactive_list); INIT_LIST_HEAD(&dev_priv->mm.request_list); - INIT_LIST_HEAD(&dev_priv->mm.fence_list); INIT_DELAYED_WORK(&dev_priv->mm.retire_work, i915_gem_retire_work_handler); dev_priv->mm.next_gem_seqno = 1; diff --git a/trunk/drivers/gpu/drm/i915/intel_bios.c b/trunk/drivers/gpu/drm/i915/intel_bios.c index f806fcc54e09..300aee3296c2 100644 --- a/trunk/drivers/gpu/drm/i915/intel_bios.c +++ b/trunk/drivers/gpu/drm/i915/intel_bios.c @@ -59,16 +59,6 @@ find_section(struct bdb_header *bdb, int section_id) return NULL; } -static u16 -get_blocksize(void *p) -{ - u16 *block_ptr, block_size; - - block_ptr = (u16 *)((char *)p - 2); - block_size = *block_ptr; - return block_size; -} - static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, struct lvds_dvo_timing *dvo_timing) @@ -224,41 +214,6 @@ parse_general_features(struct drm_i915_private *dev_priv, } } -static void -parse_general_definitions(struct drm_i915_private *dev_priv, - struct bdb_header *bdb) -{ - struct bdb_general_definitions *general; - const int crt_bus_map_table[] = { - GPIOB, - GPIOA, - GPIOC, - GPIOD, - GPIOE, - GPIOF, - }; - - /* Set sensible defaults in case we can't find the general block - or it is the wrong chipset */ - dev_priv->crt_ddc_bus = -1; - - general = find_section(bdb, BDB_GENERAL_DEFINITIONS); - if (general) { - u16 block_size = get_blocksize(general); - if (block_size >= sizeof(*general)) { - int bus_pin = general->crt_ddc_gmbus_pin; - DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin); - if ((bus_pin >= 1) && (bus_pin <= 6)) { - dev_priv->crt_ddc_bus = - crt_bus_map_table[bus_pin-1]; - } - } else { - DRM_DEBUG("BDB_GD too small (%d). Invalid.\n", - block_size); - } - } -} - static void parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, struct bdb_header *bdb) @@ -267,7 +222,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, struct bdb_general_definitions *p_defs; struct child_device_config *p_child; int i, child_device_num, count; - u16 block_size; + u16 block_size, *block_ptr; p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); if (!p_defs) { @@ -285,7 +240,8 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, return; } /* get the block size of general definitions */ - block_size = get_blocksize(p_defs); + block_ptr = (u16 *)((char *)p_defs - 2); + block_size = *block_ptr; /* get the number of child device */ child_device_num = (block_size - sizeof(*p_defs)) / sizeof(*p_child); @@ -406,7 +362,6 @@ intel_init_bios(struct drm_device *dev) /* Grab useful general definitions */ parse_general_features(dev_priv, bdb); - parse_general_definitions(dev_priv, bdb); parse_lfp_panel_data(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); parse_sdvo_device_mapping(dev_priv, bdb); diff --git a/trunk/drivers/gpu/drm/i915/intel_crt.c b/trunk/drivers/gpu/drm/i915/intel_crt.c index 590f81c8f594..4cf8e2e88a40 100644 --- a/trunk/drivers/gpu/drm/i915/intel_crt.c +++ b/trunk/drivers/gpu/drm/i915/intel_crt.c @@ -508,7 +508,6 @@ void intel_crt_init(struct drm_device *dev) { struct drm_connector *connector; struct intel_output *intel_output; - struct drm_i915_private *dev_priv = dev->dev_private; u32 i2c_reg; intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); @@ -528,12 +527,8 @@ void intel_crt_init(struct drm_device *dev) /* Set up the DDC bus. */ if (IS_IGDNG(dev)) i2c_reg = PCH_GPIOA; - else { + else i2c_reg = GPIOA; - /* Use VBT information for CRT DDC if available */ - if (dev_priv->crt_ddc_bus != -1) - i2c_reg = dev_priv->crt_ddc_bus; - } intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); if (!intel_output->ddc_bus) { dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " @@ -542,10 +537,6 @@ void intel_crt_init(struct drm_device *dev) } intel_output->type = INTEL_OUTPUT_ANALOG; - intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | - (1 << INTEL_ANALOG_CLONE_BIT) | - (1 << INTEL_SDVO_LVDS_CLONE_BIT); - intel_output->crtc_mask = (1 << 0) | (1 << 1); connector->interlace_allowed = 0; connector->doublescan_allowed = 0; diff --git a/trunk/drivers/gpu/drm/i915/intel_display.c b/trunk/drivers/gpu/drm/i915/intel_display.c index 748ed50c55ca..d6fce2133413 100644 --- a/trunk/drivers/gpu/drm/i915/intel_display.c +++ b/trunk/drivers/gpu/drm/i915/intel_display.c @@ -666,7 +666,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, intel_clock_t clock; int err = target; - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && + if (IS_I9XX(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && (I915_READ(LVDS)) != 0) { /* * For LVDS, if the panel is on, just rely on its current @@ -2005,21 +2005,7 @@ static void igd_enable_cxsr(struct drm_device *dev, unsigned long clock, return; } -/* - * Latency for FIFO fetches is dependent on several factors: - * - memory configuration (speed, channels) - * - chipset - * - current MCH state - * It can be fairly high in some situations, so here we assume a fairly - * pessimal value. It's a tradeoff between extra memory fetches (if we - * set this value too high, the FIFO will fetch frequently to stay full) - * and power consumption (set it too low to save power and we might see - * FIFO underruns and display "flicker"). - * - * A value of 5us seems to be a good balance; safe for very low end - * platforms but not overly aggressive on lower latency configs. - */ -const static int latency_ns = 5000; +const static int latency_ns = 3000; /* default for non-igd platforms */ static int intel_get_fifo_size(struct drm_device *dev, int plane) { @@ -2410,7 +2396,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, if (is_sdvo) { dpll |= DPLL_DVO_HIGH_SPEED; sdvo_pixel_multiply = adjusted_mode->clock / mode->clock; - if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) + if (IS_I945G(dev) || IS_I945GM(dev)) dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; else if (IS_IGDNG(dev)) dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; @@ -3184,7 +3170,7 @@ static int intel_connector_clones(struct drm_device *dev, int type_mask) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct intel_output *intel_output = to_intel_output(connector); - if (type_mask & intel_output->clone_mask) + if (type_mask & (1 << intel_output->type)) index_mask |= (1 << entry); entry++; } @@ -3232,30 +3218,30 @@ static void intel_setup_outputs(struct drm_device *dev) intel_dp_init(dev, PCH_DP_D); } else if (IS_I9XX(dev)) { - bool found = false; + int found; + u32 reg; if (I915_READ(SDVOB) & SDVO_DETECTED) { found = intel_sdvo_init(dev, SDVOB); if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) intel_hdmi_init(dev, SDVOB); - if (!found && SUPPORTS_INTEGRATED_DP(dev)) intel_dp_init(dev, DP_B); } /* Before G4X SDVOC doesn't have its own detect register */ + if (IS_G4X(dev)) + reg = SDVOC; + else + reg = SDVOB; - if (I915_READ(SDVOB) & SDVO_DETECTED) + if (I915_READ(reg) & SDVO_DETECTED) { found = intel_sdvo_init(dev, SDVOC); - - if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) { - - if (SUPPORTS_INTEGRATED_HDMI(dev)) + if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) intel_hdmi_init(dev, SDVOC); - if (SUPPORTS_INTEGRATED_DP(dev)) + if (!found && SUPPORTS_INTEGRATED_DP(dev)) intel_dp_init(dev, DP_C); } - if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) intel_dp_init(dev, DP_D); } else @@ -3267,10 +3253,51 @@ static void intel_setup_outputs(struct drm_device *dev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct intel_output *intel_output = to_intel_output(connector); struct drm_encoder *encoder = &intel_output->enc; + int crtc_mask = 0, clone_mask = 0; - encoder->possible_crtcs = intel_output->crtc_mask; - encoder->possible_clones = intel_connector_clones(dev, - intel_output->clone_mask); + /* valid crtcs */ + switch(intel_output->type) { + case INTEL_OUTPUT_HDMI: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << INTEL_OUTPUT_HDMI)); + break; + case INTEL_OUTPUT_DVO: + case INTEL_OUTPUT_SDVO: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | + (1 << INTEL_OUTPUT_DVO) | + (1 << INTEL_OUTPUT_SDVO)); + break; + case INTEL_OUTPUT_ANALOG: + crtc_mask = ((1 << 0)| + (1 << 1)); + clone_mask = ((1 << INTEL_OUTPUT_ANALOG) | + (1 << INTEL_OUTPUT_DVO) | + (1 << INTEL_OUTPUT_SDVO)); + break; + case INTEL_OUTPUT_LVDS: + crtc_mask = (1 << 1); + clone_mask = (1 << INTEL_OUTPUT_LVDS); + break; + case INTEL_OUTPUT_TVOUT: + crtc_mask = ((1 << 0) | + (1 << 1)); + clone_mask = (1 << INTEL_OUTPUT_TVOUT); + break; + case INTEL_OUTPUT_DISPLAYPORT: + crtc_mask = ((1 << 0) | + (1 << 1)); + clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); + break; + case INTEL_OUTPUT_EDP: + crtc_mask = (1 << 1); + clone_mask = (1 << INTEL_OUTPUT_EDP); + break; + } + encoder->possible_crtcs = crtc_mask; + encoder->possible_clones = intel_connector_clones(dev, clone_mask); } } diff --git a/trunk/drivers/gpu/drm/i915/intel_dp.c b/trunk/drivers/gpu/drm/i915/intel_dp.c index 2b914d732076..a6ff15ac548a 100644 --- a/trunk/drivers/gpu/drm/i915/intel_dp.c +++ b/trunk/drivers/gpu/drm/i915/intel_dp.c @@ -1254,18 +1254,6 @@ intel_dp_init(struct drm_device *dev, int output_reg) else intel_output->type = INTEL_OUTPUT_DISPLAYPORT; - if (output_reg == DP_B) - intel_output->clone_mask = (1 << INTEL_DP_B_CLONE_BIT); - else if (output_reg == DP_C) - intel_output->clone_mask = (1 << INTEL_DP_C_CLONE_BIT); - else if (output_reg == DP_D) - intel_output->clone_mask = (1 << INTEL_DP_D_CLONE_BIT); - - if (IS_eDP(intel_output)) { - intel_output->crtc_mask = (1 << 1); - intel_output->clone_mask = (1 << INTEL_EDP_CLONE_BIT); - } else - intel_output->crtc_mask = (1 << 0) | (1 << 1); connector->interlace_allowed = true; connector->doublescan_allowed = 0; diff --git a/trunk/drivers/gpu/drm/i915/intel_drv.h b/trunk/drivers/gpu/drm/i915/intel_drv.h index 26a6227c15fe..d6f92ea1b553 100644 --- a/trunk/drivers/gpu/drm/i915/intel_drv.h +++ b/trunk/drivers/gpu/drm/i915/intel_drv.h @@ -57,25 +57,6 @@ #define INTEL_OUTPUT_DISPLAYPORT 7 #define INTEL_OUTPUT_EDP 8 -/* Intel Pipe Clone Bit */ -#define INTEL_HDMIB_CLONE_BIT 1 -#define INTEL_HDMIC_CLONE_BIT 2 -#define INTEL_HDMID_CLONE_BIT 3 -#define INTEL_HDMIE_CLONE_BIT 4 -#define INTEL_HDMIF_CLONE_BIT 5 -#define INTEL_SDVO_NON_TV_CLONE_BIT 6 -#define INTEL_SDVO_TV_CLONE_BIT 7 -#define INTEL_SDVO_LVDS_CLONE_BIT 8 -#define INTEL_ANALOG_CLONE_BIT 9 -#define INTEL_TV_CLONE_BIT 10 -#define INTEL_DP_B_CLONE_BIT 11 -#define INTEL_DP_C_CLONE_BIT 12 -#define INTEL_DP_D_CLONE_BIT 13 -#define INTEL_LVDS_CLONE_BIT 14 -#define INTEL_DVO_TMDS_CLONE_BIT 15 -#define INTEL_DVO_LVDS_CLONE_BIT 16 -#define INTEL_EDP_CLONE_BIT 17 - #define INTEL_DVO_CHIP_NONE 0 #define INTEL_DVO_CHIP_LVDS 1 #define INTEL_DVO_CHIP_TMDS 2 @@ -105,8 +86,6 @@ struct intel_output { bool needs_tv_clock; void *dev_priv; void (*hot_plug)(struct intel_output *); - int crtc_mask; - int clone_mask; }; struct intel_crtc { diff --git a/trunk/drivers/gpu/drm/i915/intel_dvo.c b/trunk/drivers/gpu/drm/i915/intel_dvo.c index a4d2606de778..13bff20930e8 100644 --- a/trunk/drivers/gpu/drm/i915/intel_dvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_dvo.c @@ -435,20 +435,14 @@ void intel_dvo_init(struct drm_device *dev) continue; intel_output->type = INTEL_OUTPUT_DVO; - intel_output->crtc_mask = (1 << 0) | (1 << 1); switch (dvo->type) { case INTEL_DVO_CHIP_TMDS: - intel_output->clone_mask = - (1 << INTEL_DVO_TMDS_CLONE_BIT) | - (1 << INTEL_ANALOG_CLONE_BIT); drm_connector_init(dev, connector, &intel_dvo_connector_funcs, DRM_MODE_CONNECTOR_DVII); encoder_type = DRM_MODE_ENCODER_TMDS; break; case INTEL_DVO_CHIP_LVDS: - intel_output->clone_mask = - (1 << INTEL_DVO_LVDS_CLONE_BIT); drm_connector_init(dev, connector, &intel_dvo_connector_funcs, DRM_MODE_CONNECTOR_LVDS); diff --git a/trunk/drivers/gpu/drm/i915/intel_hdmi.c b/trunk/drivers/gpu/drm/i915/intel_hdmi.c index fa304e136010..1842290cded3 100644 --- a/trunk/drivers/gpu/drm/i915/intel_hdmi.c +++ b/trunk/drivers/gpu/drm/i915/intel_hdmi.c @@ -230,28 +230,22 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) connector->interlace_allowed = 0; connector->doublescan_allowed = 0; - intel_output->crtc_mask = (1 << 0) | (1 << 1); /* Set up the DDC bus. */ - if (sdvox_reg == SDVOB) { - intel_output->clone_mask = (1 << INTEL_HDMIB_CLONE_BIT); + if (sdvox_reg == SDVOB) intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "HDMIB"); - } else if (sdvox_reg == SDVOC) { - intel_output->clone_mask = (1 << INTEL_HDMIC_CLONE_BIT); + else if (sdvox_reg == SDVOC) intel_output->ddc_bus = intel_i2c_create(dev, GPIOD, "HDMIC"); - } else if (sdvox_reg == HDMIB) { - intel_output->clone_mask = (1 << INTEL_HDMID_CLONE_BIT); + else if (sdvox_reg == HDMIB) intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOE, "HDMIB"); - } else if (sdvox_reg == HDMIC) { - intel_output->clone_mask = (1 << INTEL_HDMIE_CLONE_BIT); + else if (sdvox_reg == HDMIC) intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOD, "HDMIC"); - } else if (sdvox_reg == HDMID) { - intel_output->clone_mask = (1 << INTEL_HDMIF_CLONE_BIT); + else if (sdvox_reg == HDMID) intel_output->ddc_bus = intel_i2c_create(dev, PCH_GPIOF, "HDMID"); - } + if (!intel_output->ddc_bus) goto err_connector; diff --git a/trunk/drivers/gpu/drm/i915/intel_lvds.c b/trunk/drivers/gpu/drm/i915/intel_lvds.c index 8df02ef89261..3f445a80c552 100644 --- a/trunk/drivers/gpu/drm/i915/intel_lvds.c +++ b/trunk/drivers/gpu/drm/i915/intel_lvds.c @@ -916,8 +916,6 @@ void intel_lvds_init(struct drm_device *dev) drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); intel_output->type = INTEL_OUTPUT_LVDS; - intel_output->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); - intel_output->crtc_mask = (1 << 1); drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; diff --git a/trunk/drivers/gpu/drm/i915/intel_sdvo.c b/trunk/drivers/gpu/drm/i915/intel_sdvo.c index d3b74ba62b4a..5371d9332554 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sdvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_sdvo.c @@ -1458,7 +1458,7 @@ intel_sdvo_multifunc_encoder(struct intel_output *intel_output) (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)) caps++; if (sdvo_priv->caps.output_flags & - (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1)) + (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID0)) caps++; if (sdvo_priv->caps.output_flags & (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1)) @@ -1967,9 +1967,6 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags) intel_sdvo_set_colorimetry(intel_output, SDVO_COLORIMETRY_RGB256); connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; - intel_output->clone_mask = - (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | - (1 << INTEL_ANALOG_CLONE_BIT); } } else if (flags & SDVO_OUTPUT_SVID0) { @@ -1978,14 +1975,11 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags) connector->connector_type = DRM_MODE_CONNECTOR_SVIDEO; sdvo_priv->is_tv = true; intel_output->needs_tv_clock = true; - intel_output->clone_mask = 1 << INTEL_SDVO_TV_CLONE_BIT; } else if (flags & SDVO_OUTPUT_RGB0) { sdvo_priv->controlled_output = SDVO_OUTPUT_RGB0; encoder->encoder_type = DRM_MODE_ENCODER_DAC; connector->connector_type = DRM_MODE_CONNECTOR_VGA; - intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | - (1 << INTEL_ANALOG_CLONE_BIT); } else if (flags & SDVO_OUTPUT_RGB1) { sdvo_priv->controlled_output = SDVO_OUTPUT_RGB1; @@ -1997,16 +1991,12 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags) encoder->encoder_type = DRM_MODE_ENCODER_LVDS; connector->connector_type = DRM_MODE_CONNECTOR_LVDS; sdvo_priv->is_lvds = true; - intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) | - (1 << INTEL_SDVO_LVDS_CLONE_BIT); } else if (flags & SDVO_OUTPUT_LVDS1) { sdvo_priv->controlled_output = SDVO_OUTPUT_LVDS1; encoder->encoder_type = DRM_MODE_ENCODER_LVDS; connector->connector_type = DRM_MODE_CONNECTOR_LVDS; sdvo_priv->is_lvds = true; - intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT) | - (1 << INTEL_SDVO_LVDS_CLONE_BIT); } else { unsigned char bytes[2]; @@ -2019,7 +2009,6 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags) bytes[0], bytes[1]); ret = false; } - intel_output->crtc_mask = (1 << 0) | (1 << 1); if (ret && registered) ret = drm_sysfs_connector_add(connector) == 0 ? true : false; diff --git a/trunk/drivers/gpu/drm/i915/intel_tv.c b/trunk/drivers/gpu/drm/i915/intel_tv.c index 5b1c9e9fdba0..da4ab4dc1630 100644 --- a/trunk/drivers/gpu/drm/i915/intel_tv.c +++ b/trunk/drivers/gpu/drm/i915/intel_tv.c @@ -1718,7 +1718,6 @@ intel_tv_init(struct drm_device *dev) if (!intel_output) { return; } - connector = &intel_output->base; drm_connector_init(dev, connector, &intel_tv_connector_funcs, @@ -1730,8 +1729,6 @@ intel_tv_init(struct drm_device *dev) drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); tv_priv = (struct intel_tv_priv *)(intel_output + 1); intel_output->type = INTEL_OUTPUT_TVOUT; - intel_output->crtc_mask = (1 << 0) | (1 << 1); - intel_output->clone_mask = (1 << INTEL_TV_CLONE_BIT); intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1)); intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT); intel_output->dev_priv = tv_priv; diff --git a/trunk/drivers/gpu/drm/radeon/r300.c b/trunk/drivers/gpu/drm/radeon/r300.c index 051bca6e3a4f..053f4ec397f7 100644 --- a/trunk/drivers/gpu/drm/radeon/r300.c +++ b/trunk/drivers/gpu/drm/radeon/r300.c @@ -995,7 +995,7 @@ static const unsigned r300_reg_safe_bm[159] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0003FC01, 0xFFFFFCF8, 0xFF800B19, + 0x0003FC01, 0xFFFFFFF8, 0xFE800B19, }; static int r300_packet0_check(struct radeon_cs_parser *p, diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.h b/trunk/drivers/gpu/drm/radeon/radeon_asic.h index 93d8f8889302..7ca6c13569b5 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.h @@ -266,7 +266,6 @@ static struct radeon_asic rs400_asic = { /* * rs600. */ -int rs600_init(struct radeon_device *dev); void rs600_errata(struct radeon_device *rdev); void rs600_vram_info(struct radeon_device *rdev); int rs600_mc_init(struct radeon_device *rdev); @@ -282,7 +281,7 @@ uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs600_bandwidth_update(struct radeon_device *rdev); static struct radeon_asic rs600_asic = { - .init = &rs600_init, + .init = &r300_init, .errata = &rs600_errata, .vram_info = &rs600_vram_info, .gpu_reset = &r300_gpu_reset, @@ -317,6 +316,7 @@ static struct radeon_asic rs600_asic = { /* * rs690,rs740 */ +int rs690_init(struct radeon_device *rdev); void rs690_errata(struct radeon_device *rdev); void rs690_vram_info(struct radeon_device *rdev); int rs690_mc_init(struct radeon_device *rdev); @@ -325,7 +325,7 @@ uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs690_bandwidth_update(struct radeon_device *rdev); static struct radeon_asic rs690_asic = { - .init = &rs600_init, + .init = &rs690_init, .errata = &rs690_errata, .vram_info = &rs690_vram_info, .gpu_reset = &r300_gpu_reset, diff --git a/trunk/drivers/gpu/drm/radeon/rs600.c b/trunk/drivers/gpu/drm/radeon/rs600.c index 02fd11aad6a2..7e8ce983a908 100644 --- a/trunk/drivers/gpu/drm/radeon/rs600.c +++ b/trunk/drivers/gpu/drm/radeon/rs600.c @@ -409,68 +409,3 @@ void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) ((reg) & RS600_MC_ADDR_MASK)); WREG32(RS600_MC_DATA, v); } - -static const unsigned rs600_reg_safe_bm[219] = { - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, - 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000, - 0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, - 0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF, - 0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, - 0x00000000, 0x0000C100, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0003FC01, 0xFFFFFCF8, 0xFF800B19, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, - 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, -}; - -int rs600_init(struct radeon_device *rdev) -{ - rdev->config.r300.reg_safe_bm = rs600_reg_safe_bm; - rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs600_reg_safe_bm); - return 0; -} diff --git a/trunk/drivers/gpu/drm/radeon/rs690.c b/trunk/drivers/gpu/drm/radeon/rs690.c index 879882533e45..bc6b7c5339bc 100644 --- a/trunk/drivers/gpu/drm/radeon/rs690.c +++ b/trunk/drivers/gpu/drm/radeon/rs690.c @@ -653,3 +653,67 @@ void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) WREG32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); } +static const unsigned rs690_reg_safe_bm[219] = { + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0x17FF1FFF,0xFFFFFFFC,0xFFFFFFFF,0xFF30FFBF, + 0xFFFFFFF8,0xC3E6FFFF,0xFFFFF6DF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFF03F, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFEFCE,0xF00EBFFF,0x007C0000, + 0xF0000078,0xFF000009,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFF7FF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFC78,0xFFFFFFFF,0xFFFFFFFE,0xFFFFFFFF, + 0x38FF8F50,0xFFF88082,0xF000000C,0xFAE009FF, + 0x0000FFFF,0xFFFFFFFF,0xFFFFFFFF,0x00000000, + 0x00000000,0x0000C100,0x00000000,0x00000000, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0xFFFF0000,0xFFFFFFFF,0xFF80FFFF, + 0x00000000,0x00000000,0x00000000,0x00000000, + 0x0003FC01,0xFFFFFFF8,0xFE800B19,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, +}; + +int rs690_init(struct radeon_device *rdev) +{ + rdev->config.r300.reg_safe_bm = rs690_reg_safe_bm; + rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rs690_reg_safe_bm); + return 0; +} diff --git a/trunk/drivers/gpu/drm/radeon/rv515.c b/trunk/drivers/gpu/drm/radeon/rv515.c index 0566fb67e460..31a7f668ae5a 100644 --- a/trunk/drivers/gpu/drm/radeon/rv515.c +++ b/trunk/drivers/gpu/drm/radeon/rv515.c @@ -508,7 +508,7 @@ static const unsigned r500_reg_safe_bm[219] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0003FC01, 0x3FFFFCF8, 0xFF800B19, 0xFFDFFFFF, + 0x0003FC01, 0x3FFFFCF8, 0xFE800B19, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, diff --git a/trunk/drivers/ide/ide-cs.c b/trunk/drivers/ide/ide-cs.c index 063b933d864a..527908ff298c 100644 --- a/trunk/drivers/ide/ide-cs.c +++ b/trunk/drivers/ide/ide-cs.c @@ -408,7 +408,6 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_PROD_ID123("PCMCIA", "IDE CARD", "F1", 0x281f1c5d, 0x1907960c, 0xf7fde8b9), PCMCIA_DEVICE_PROD_ID12("ARGOSY", "CD-ROM", 0x78f308dc, 0x66536591), PCMCIA_DEVICE_PROD_ID12("ARGOSY", "PnPIDE", 0x78f308dc, 0x0c694728), - PCMCIA_DEVICE_PROD_ID12("CNF ", "CD-ROM", 0x46d7db81, 0x66536591), PCMCIA_DEVICE_PROD_ID12("CNF CD-M", "CD-ROM", 0x7d93b852, 0x66536591), PCMCIA_DEVICE_PROD_ID12("Creative Technology Ltd.", "PCMCIA CD-ROM Interface Card", 0xff8c8a45, 0xfe8020c4), PCMCIA_DEVICE_PROD_ID12("Digital Equipment Corporation.", "Digital Mobile Media CD-ROM", 0x17692a66, 0xef1dcbde), diff --git a/trunk/drivers/input/keyboard/atkbd.c b/trunk/drivers/input/keyboard/atkbd.c index 6c6a09b1c0fe..95fe0452dae4 100644 --- a/trunk/drivers/input/keyboard/atkbd.c +++ b/trunk/drivers/input/keyboard/atkbd.c @@ -879,14 +879,6 @@ static unsigned int atkbd_hp_zv6100_forced_release_keys[] = { 0xae, 0xb0, -1U }; -/* - * Perform fixup for HP (Compaq) Presario R4000 R4100 R4200 that don't generate - * release for their volume buttons - */ -static unsigned int atkbd_hp_r4000_forced_release_keys[] = { - 0xae, 0xb0, -1U -}; - /* * Samsung NC10,NC20 with Fn+F? key release not working */ @@ -1544,33 +1536,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { .callback = atkbd_setup_forced_release, .driver_data = atkbd_hp_zv6100_forced_release_keys, }, - { - .ident = "HP Presario R4000", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"), - }, - .callback = atkbd_setup_forced_release, - .driver_data = atkbd_hp_r4000_forced_release_keys, - }, - { - .ident = "HP Presario R4100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"), - }, - .callback = atkbd_setup_forced_release, - .driver_data = atkbd_hp_r4000_forced_release_keys, - }, - { - .ident = "HP Presario R4200", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"), - }, - .callback = atkbd_setup_forced_release, - .driver_data = atkbd_hp_r4000_forced_release_keys, - }, { .ident = "Inventec Symphony", .matches = { diff --git a/trunk/drivers/input/serio/i8042-x86ia64io.h b/trunk/drivers/input/serio/i8042-x86ia64io.h index ccbf23ece8e3..ae04d8a494e5 100644 --- a/trunk/drivers/input/serio/i8042-x86ia64io.h +++ b/trunk/drivers/input/serio/i8042-x86ia64io.h @@ -382,14 +382,6 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"), }, }, - { - .ident = "Acer Aspire 5536", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), - }, - }, { } }; diff --git a/trunk/drivers/md/dm-exception-store.c b/trunk/drivers/md/dm-exception-store.c index 556acff3952f..3710ff88fc10 100644 --- a/trunk/drivers/md/dm-exception-store.c +++ b/trunk/drivers/md/dm-exception-store.c @@ -171,14 +171,6 @@ static int set_chunk_size(struct dm_exception_store *store, */ chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9); - return dm_exception_store_set_chunk_size(store, chunk_size_ulong, - error); -} - -int dm_exception_store_set_chunk_size(struct dm_exception_store *store, - unsigned long chunk_size_ulong, - char **error) -{ /* Check chunk_size is a power of 2 */ if (!is_power_of_2(chunk_size_ulong)) { *error = "Chunk size is not a power of 2"; @@ -191,11 +183,6 @@ int dm_exception_store_set_chunk_size(struct dm_exception_store *store, return -EINVAL; } - if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) { - *error = "Chunk size is too high"; - return -EINVAL; - } - store->chunk_size = chunk_size_ulong; store->chunk_mask = chunk_size_ulong - 1; store->chunk_shift = ffs(chunk_size_ulong) - 1; diff --git a/trunk/drivers/md/dm-exception-store.h b/trunk/drivers/md/dm-exception-store.h index 812c71872ba0..2442c8c07898 100644 --- a/trunk/drivers/md/dm-exception-store.h +++ b/trunk/drivers/md/dm-exception-store.h @@ -168,10 +168,6 @@ static inline chunk_t sector_to_chunk(struct dm_exception_store *store, int dm_exception_store_type_register(struct dm_exception_store_type *type); int dm_exception_store_type_unregister(struct dm_exception_store_type *type); -int dm_exception_store_set_chunk_size(struct dm_exception_store *store, - unsigned long chunk_size_ulong, - char **error); - int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, unsigned *args_used, struct dm_exception_store **store); diff --git a/trunk/drivers/md/dm-log-userspace-base.c b/trunk/drivers/md/dm-log-userspace-base.c index 6e186b1a062d..e69b96560997 100644 --- a/trunk/drivers/md/dm-log-userspace-base.c +++ b/trunk/drivers/md/dm-log-userspace-base.c @@ -21,7 +21,6 @@ struct log_c { struct dm_target *ti; uint32_t region_size; region_t region_count; - uint64_t luid; char uuid[DM_UUID_LEN]; char *usr_argv_str; @@ -64,7 +63,7 @@ static int userspace_do_request(struct log_c *lc, const char *uuid, * restored. */ retry: - r = dm_consult_userspace(uuid, lc->luid, request_type, data, + r = dm_consult_userspace(uuid, request_type, data, data_size, rdata, rdata_size); if (r != -ESRCH) @@ -75,15 +74,14 @@ static int userspace_do_request(struct log_c *lc, const char *uuid, set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(2*HZ); DMWARN("Attempting to contact userspace log server..."); - r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_CTR, - lc->usr_argv_str, + r = dm_consult_userspace(uuid, DM_ULOG_CTR, lc->usr_argv_str, strlen(lc->usr_argv_str) + 1, NULL, NULL); if (!r) break; } DMINFO("Reconnected to userspace log server... DM_ULOG_CTR complete"); - r = dm_consult_userspace(uuid, lc->luid, DM_ULOG_RESUME, NULL, + r = dm_consult_userspace(uuid, DM_ULOG_RESUME, NULL, 0, NULL, NULL); if (!r) goto retry; @@ -113,9 +111,10 @@ static int build_constructor_string(struct dm_target *ti, return -ENOMEM; } - str_size = sprintf(str, "%llu", (unsigned long long)ti->len); - for (i = 0; i < argc; i++) - str_size += sprintf(str + str_size, " %s", argv[i]); + for (i = 0, str_size = 0; i < argc; i++) + str_size += sprintf(str + str_size, "%s ", argv[i]); + str_size += sprintf(str + str_size, "%llu", + (unsigned long long)ti->len); *ctr_str = str; return str_size; @@ -155,9 +154,6 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, return -ENOMEM; } - /* The ptr value is sufficient for local unique id */ - lc->luid = (uint64_t)lc; - lc->ti = ti; if (strlen(argv[0]) > (DM_UUID_LEN - 1)) { @@ -177,7 +173,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, } /* Send table string */ - r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_CTR, + r = dm_consult_userspace(lc->uuid, DM_ULOG_CTR, ctr_str, str_size, NULL, NULL); if (r == -ESRCH) { @@ -187,7 +183,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti, /* Since the region size does not change, get it now */ rdata_size = sizeof(rdata); - r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_GET_REGION_SIZE, + r = dm_consult_userspace(lc->uuid, DM_ULOG_GET_REGION_SIZE, NULL, 0, (char *)&rdata, &rdata_size); if (r) { @@ -216,7 +212,7 @@ static void userspace_dtr(struct dm_dirty_log *log) int r; struct log_c *lc = log->context; - r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_DTR, + r = dm_consult_userspace(lc->uuid, DM_ULOG_DTR, NULL, 0, NULL, NULL); @@ -231,7 +227,7 @@ static int userspace_presuspend(struct dm_dirty_log *log) int r; struct log_c *lc = log->context; - r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_PRESUSPEND, + r = dm_consult_userspace(lc->uuid, DM_ULOG_PRESUSPEND, NULL, 0, NULL, NULL); @@ -243,7 +239,7 @@ static int userspace_postsuspend(struct dm_dirty_log *log) int r; struct log_c *lc = log->context; - r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_POSTSUSPEND, + r = dm_consult_userspace(lc->uuid, DM_ULOG_POSTSUSPEND, NULL, 0, NULL, NULL); @@ -256,7 +252,7 @@ static int userspace_resume(struct dm_dirty_log *log) struct log_c *lc = log->context; lc->in_sync_hint = 0; - r = dm_consult_userspace(lc->uuid, lc->luid, DM_ULOG_RESUME, + r = dm_consult_userspace(lc->uuid, DM_ULOG_RESUME, NULL, 0, NULL, NULL); @@ -565,7 +561,6 @@ static int userspace_status(struct dm_dirty_log *log, status_type_t status_type, char *result, unsigned maxlen) { int r = 0; - char *table_args; size_t sz = (size_t)maxlen; struct log_c *lc = log->context; @@ -582,12 +577,8 @@ static int userspace_status(struct dm_dirty_log *log, status_type_t status_type, break; case STATUSTYPE_TABLE: sz = 0; - table_args = strstr(lc->usr_argv_str, " "); - BUG_ON(!table_args); /* There will always be a ' ' */ - table_args++; - - DMEMIT("%s %u %s %s ", log->type->name, lc->usr_argc, - lc->uuid, table_args); + DMEMIT("%s %u %s %s", log->type->name, lc->usr_argc + 1, + lc->uuid, lc->usr_argv_str); break; } return (r) ? 0 : (int)sz; diff --git a/trunk/drivers/md/dm-log-userspace-transfer.c b/trunk/drivers/md/dm-log-userspace-transfer.c index ba0edad2d048..8ce74d95ae4d 100644 --- a/trunk/drivers/md/dm-log-userspace-transfer.c +++ b/trunk/drivers/md/dm-log-userspace-transfer.c @@ -147,8 +147,7 @@ static void cn_ulog_callback(void *data) /** * dm_consult_userspace - * @uuid: log's universal unique identifier (must be DM_UUID_LEN in size) - * @luid: log's local unique identifier + * @uuid: log's uuid (must be DM_UUID_LEN in size) * @request_type: found in include/linux/dm-log-userspace.h * @data: data to tx to the server * @data_size: size of data in bytes @@ -164,7 +163,7 @@ static void cn_ulog_callback(void *data) * * Returns: 0 on success, -EXXX on failure **/ -int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type, +int dm_consult_userspace(const char *uuid, int request_type, char *data, size_t data_size, char *rdata, size_t *rdata_size) { @@ -191,7 +190,6 @@ int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type, memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - overhead_size); memcpy(tfr->uuid, uuid, DM_UUID_LEN); - tfr->luid = luid; tfr->seq = dm_ulog_seq++; /* diff --git a/trunk/drivers/md/dm-log-userspace-transfer.h b/trunk/drivers/md/dm-log-userspace-transfer.h index 04ee874f9153..c26d8e4e2710 100644 --- a/trunk/drivers/md/dm-log-userspace-transfer.h +++ b/trunk/drivers/md/dm-log-userspace-transfer.h @@ -11,7 +11,7 @@ int dm_ulog_tfr_init(void); void dm_ulog_tfr_exit(void); -int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type, +int dm_consult_userspace(const char *uuid, int request_type, char *data, size_t data_size, char *rdata, size_t *rdata_size); diff --git a/trunk/drivers/md/dm-raid1.c b/trunk/drivers/md/dm-raid1.c index 33f179e66bf5..9726577cde49 100644 --- a/trunk/drivers/md/dm-raid1.c +++ b/trunk/drivers/md/dm-raid1.c @@ -648,13 +648,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) */ dm_rh_inc_pending(ms->rh, &sync); dm_rh_inc_pending(ms->rh, &nosync); - - /* - * If the flush fails on a previous call and succeeds here, - * we must not reset the log_failure variable. We need - * userspace interaction to do that. - */ - ms->log_failure = dm_rh_flush(ms->rh) ? 1 : ms->log_failure; + ms->log_failure = dm_rh_flush(ms->rh) ? 1 : 0; /* * Dispatch io. diff --git a/trunk/drivers/md/dm-snap-persistent.c b/trunk/drivers/md/dm-snap-persistent.c index d5b2e08750d5..6e3fe4f14934 100644 --- a/trunk/drivers/md/dm-snap-persistent.c +++ b/trunk/drivers/md/dm-snap-persistent.c @@ -105,13 +105,6 @@ struct pstore { */ void *zero_area; - /* - * An area used for header. The header can be written - * concurrently with metadata (when invalidating the snapshot), - * so it needs a separate buffer. - */ - void *header_area; - /* * Used to keep track of which metadata area the data in * 'chunk' refers to. @@ -155,27 +148,16 @@ static int alloc_area(struct pstore *ps) */ ps->area = vmalloc(len); if (!ps->area) - goto err_area; + return r; ps->zero_area = vmalloc(len); - if (!ps->zero_area) - goto err_zero_area; + if (!ps->zero_area) { + vfree(ps->area); + return r; + } memset(ps->zero_area, 0, len); - ps->header_area = vmalloc(len); - if (!ps->header_area) - goto err_header_area; - return 0; - -err_header_area: - vfree(ps->zero_area); - -err_zero_area: - vfree(ps->area); - -err_area: - return r; } static void free_area(struct pstore *ps) @@ -187,10 +169,6 @@ static void free_area(struct pstore *ps) if (ps->zero_area) vfree(ps->zero_area); ps->zero_area = NULL; - - if (ps->header_area) - vfree(ps->header_area); - ps->header_area = NULL; } struct mdata_req { @@ -210,8 +188,7 @@ static void do_metadata(struct work_struct *work) /* * Read or write a chunk aligned and sized block of data from a device. */ -static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, - int metadata) +static int chunk_io(struct pstore *ps, chunk_t chunk, int rw, int metadata) { struct dm_io_region where = { .bdev = ps->store->cow->bdev, @@ -221,7 +198,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, struct dm_io_request io_req = { .bi_rw = rw, .mem.type = DM_IO_VMA, - .mem.ptr.vma = area, + .mem.ptr.vma = ps->area, .client = ps->io_client, .notify.fn = NULL, }; @@ -263,7 +240,7 @@ static int area_io(struct pstore *ps, int rw) chunk = area_location(ps, ps->current_area); - r = chunk_io(ps, ps->area, chunk, rw, 0); + r = chunk_io(ps, chunk, rw, 0); if (r) return r; @@ -277,7 +254,20 @@ static void zero_memory_area(struct pstore *ps) static int zero_disk_area(struct pstore *ps, chunk_t area) { - return chunk_io(ps, ps->zero_area, area_location(ps, area), WRITE, 0); + struct dm_io_region where = { + .bdev = ps->store->cow->bdev, + .sector = ps->store->chunk_size * area_location(ps, area), + .count = ps->store->chunk_size, + }; + struct dm_io_request io_req = { + .bi_rw = WRITE, + .mem.type = DM_IO_VMA, + .mem.ptr.vma = ps->zero_area, + .client = ps->io_client, + .notify.fn = NULL, + }; + + return dm_io(&io_req, 1, &where, NULL); } static int read_header(struct pstore *ps, int *new_snapshot) @@ -286,7 +276,6 @@ static int read_header(struct pstore *ps, int *new_snapshot) struct disk_header *dh; chunk_t chunk_size; int chunk_size_supplied = 1; - char *chunk_err; /* * Use default chunk size (or hardsect_size, if larger) if none supplied @@ -308,11 +297,11 @@ static int read_header(struct pstore *ps, int *new_snapshot) if (r) return r; - r = chunk_io(ps, ps->header_area, 0, READ, 1); + r = chunk_io(ps, 0, READ, 1); if (r) goto bad; - dh = ps->header_area; + dh = (struct disk_header *) ps->area; if (le32_to_cpu(dh->magic) == 0) { *new_snapshot = 1; @@ -330,25 +319,20 @@ static int read_header(struct pstore *ps, int *new_snapshot) ps->version = le32_to_cpu(dh->version); chunk_size = le32_to_cpu(dh->chunk_size); - if (ps->store->chunk_size == chunk_size) + if (!chunk_size_supplied || ps->store->chunk_size == chunk_size) return 0; - if (chunk_size_supplied) - DMWARN("chunk size %llu in device metadata overrides " - "table chunk size of %llu.", - (unsigned long long)chunk_size, - (unsigned long long)ps->store->chunk_size); + DMWARN("chunk size %llu in device metadata overrides " + "table chunk size of %llu.", + (unsigned long long)chunk_size, + (unsigned long long)ps->store->chunk_size); /* We had a bogus chunk_size. Fix stuff up. */ free_area(ps); - r = dm_exception_store_set_chunk_size(ps->store, chunk_size, - &chunk_err); - if (r) { - DMERR("invalid on-disk chunk size %llu: %s.", - (unsigned long long)chunk_size, chunk_err); - return r; - } + ps->store->chunk_size = chunk_size; + ps->store->chunk_mask = chunk_size - 1; + ps->store->chunk_shift = ffs(chunk_size) - 1; r = dm_io_client_resize(sectors_to_pages(ps->store->chunk_size), ps->io_client); @@ -367,15 +351,15 @@ static int write_header(struct pstore *ps) { struct disk_header *dh; - memset(ps->header_area, 0, ps->store->chunk_size << SECTOR_SHIFT); + memset(ps->area, 0, ps->store->chunk_size << SECTOR_SHIFT); - dh = ps->header_area; + dh = (struct disk_header *) ps->area; dh->magic = cpu_to_le32(SNAP_MAGIC); dh->valid = cpu_to_le32(ps->valid); dh->version = cpu_to_le32(ps->version); dh->chunk_size = cpu_to_le32(ps->store->chunk_size); - return chunk_io(ps, ps->header_area, 0, WRITE, 1); + return chunk_io(ps, 0, WRITE, 1); } /* @@ -695,8 +679,6 @@ static int persistent_ctr(struct dm_exception_store *store, ps->valid = 1; ps->version = SNAPSHOT_DISK_VERSION; ps->area = NULL; - ps->zero_area = NULL; - ps->header_area = NULL; ps->next_free = 2; /* skipping the header and first area */ ps->current_committed = 0; diff --git a/trunk/drivers/md/dm-snap.c b/trunk/drivers/md/dm-snap.c index 57f1bf7f3b7a..d573165cd2b7 100644 --- a/trunk/drivers/md/dm-snap.c +++ b/trunk/drivers/md/dm-snap.c @@ -1176,15 +1176,6 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, return 0; } -static int snapshot_iterate_devices(struct dm_target *ti, - iterate_devices_callout_fn fn, void *data) -{ - struct dm_snapshot *snap = ti->private; - - return fn(ti, snap->origin, 0, ti->len, data); -} - - /*----------------------------------------------------------------- * Origin methods *---------------------------------------------------------------*/ @@ -1419,29 +1410,20 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, return 0; } -static int origin_iterate_devices(struct dm_target *ti, - iterate_devices_callout_fn fn, void *data) -{ - struct dm_dev *dev = ti->private; - - return fn(ti, dev, 0, ti->len, data); -} - static struct target_type origin_target = { .name = "snapshot-origin", - .version = {1, 7, 0}, + .version = {1, 6, 0}, .module = THIS_MODULE, .ctr = origin_ctr, .dtr = origin_dtr, .map = origin_map, .resume = origin_resume, .status = origin_status, - .iterate_devices = origin_iterate_devices, }; static struct target_type snapshot_target = { .name = "snapshot", - .version = {1, 7, 0}, + .version = {1, 6, 0}, .module = THIS_MODULE, .ctr = snapshot_ctr, .dtr = snapshot_dtr, @@ -1449,7 +1431,6 @@ static struct target_type snapshot_target = { .end_io = snapshot_end_io, .resume = snapshot_resume, .status = snapshot_status, - .iterate_devices = snapshot_iterate_devices, }; static int __init dm_snapshot_init(void) diff --git a/trunk/drivers/md/dm-stripe.c b/trunk/drivers/md/dm-stripe.c index 3e563d251733..4e0e5937e42a 100644 --- a/trunk/drivers/md/dm-stripe.c +++ b/trunk/drivers/md/dm-stripe.c @@ -329,19 +329,9 @@ static int stripe_iterate_devices(struct dm_target *ti, return ret; } -static void stripe_io_hints(struct dm_target *ti, - struct queue_limits *limits) -{ - struct stripe_c *sc = ti->private; - unsigned chunk_size = (sc->chunk_mask + 1) << 9; - - blk_limits_io_min(limits, chunk_size); - limits->io_opt = chunk_size * sc->stripes; -} - static struct target_type stripe_target = { .name = "striped", - .version = {1, 3, 0}, + .version = {1, 2, 0}, .module = THIS_MODULE, .ctr = stripe_ctr, .dtr = stripe_dtr, @@ -349,7 +339,6 @@ static struct target_type stripe_target = { .end_io = stripe_end_io, .status = stripe_status, .iterate_devices = stripe_iterate_devices, - .io_hints = stripe_io_hints, }; int __init dm_stripe_init(void) diff --git a/trunk/drivers/md/dm-table.c b/trunk/drivers/md/dm-table.c index 1a6cb3c7822e..d952b3441913 100644 --- a/trunk/drivers/md/dm-table.c +++ b/trunk/drivers/md/dm-table.c @@ -343,10 +343,10 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md) } /* - * If possible, this checks an area of a destination device is invalid. + * If possible, this checks an area of a destination device is valid. */ -static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int device_area_is_valid(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { struct queue_limits *limits = data; struct block_device *bdev = dev->bdev; @@ -357,40 +357,36 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev, char b[BDEVNAME_SIZE]; if (!dev_size) - return 0; + return 1; if ((start >= dev_size) || (start + len > dev_size)) { - DMWARN("%s: %s too small for target: " - "start=%llu, len=%llu, dev_size=%llu", - dm_device_name(ti->table->md), bdevname(bdev, b), - (unsigned long long)start, - (unsigned long long)len, - (unsigned long long)dev_size); - return 1; + DMWARN("%s: %s too small for target", + dm_device_name(ti->table->md), bdevname(bdev, b)); + return 0; } if (logical_block_size_sectors <= 1) - return 0; + return 1; if (start & (logical_block_size_sectors - 1)) { DMWARN("%s: start=%llu not aligned to h/w " - "logical block size %u of %s", + "logical block size %hu of %s", dm_device_name(ti->table->md), (unsigned long long)start, limits->logical_block_size, bdevname(bdev, b)); - return 1; + return 0; } if (len & (logical_block_size_sectors - 1)) { DMWARN("%s: len=%llu not aligned to h/w " - "logical block size %u of %s", + "logical block size %hu of %s", dm_device_name(ti->table->md), (unsigned long long)len, limits->logical_block_size, bdevname(bdev, b)); - return 1; + return 0; } - return 0; + return 1; } /* @@ -500,15 +496,8 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev, } if (blk_stack_limits(limits, &q->limits, start << 9) < 0) - DMWARN("%s: target device %s is misaligned: " - "physical_block_size=%u, logical_block_size=%u, " - "alignment_offset=%u, start=%llu", - dm_device_name(ti->table->md), bdevname(bdev, b), - q->limits.physical_block_size, - q->limits.logical_block_size, - q->limits.alignment_offset, - (unsigned long long) start << 9); - + DMWARN("%s: target device %s is misaligned", + dm_device_name(ti->table->md), bdevname(bdev, b)); /* * Check if merge fn is supported. @@ -709,7 +698,7 @@ static int validate_hardware_logical_block_alignment(struct dm_table *table, if (remaining) { DMWARN("%s: table line %u (start sect %llu len %llu) " - "not aligned to h/w logical block size %u", + "not aligned to h/w logical block size %hu", dm_device_name(table->md), i, (unsigned long long) ti->begin, (unsigned long long) ti->len, @@ -1007,16 +996,12 @@ int dm_calculate_queue_limits(struct dm_table *table, ti->type->iterate_devices(ti, dm_set_device_limits, &ti_limits); - /* Set I/O hints portion of queue limits */ - if (ti->type->io_hints) - ti->type->io_hints(ti, &ti_limits); - /* * Check each device area is consistent with the target's * overall queue limits. */ - if (ti->type->iterate_devices(ti, device_area_is_invalid, - &ti_limits)) + if (!ti->type->iterate_devices(ti, device_area_is_valid, + &ti_limits)) return -EINVAL; combine_limits: diff --git a/trunk/drivers/md/dm.c b/trunk/drivers/md/dm.c index b4845b14740d..8a311ea0d441 100644 --- a/trunk/drivers/md/dm.c +++ b/trunk/drivers/md/dm.c @@ -738,22 +738,16 @@ static void rq_completed(struct mapped_device *md, int run_queue) dm_put(md); } -static void free_rq_clone(struct request *clone) -{ - struct dm_rq_target_io *tio = clone->end_io_data; - - blk_rq_unprep_clone(clone); - free_rq_tio(tio); -} - static void dm_unprep_request(struct request *rq) { struct request *clone = rq->special; + struct dm_rq_target_io *tio = clone->end_io_data; rq->special = NULL; rq->cmd_flags &= ~REQ_DONTPREP; - free_rq_clone(clone); + blk_rq_unprep_clone(clone); + free_rq_tio(tio); } /* @@ -831,7 +825,8 @@ static void dm_end_request(struct request *clone, int error) rq->sense_len = clone->sense_len; } - free_rq_clone(clone); + BUG_ON(clone->bio); + free_rq_tio(tio); blk_end_request_all(rq, error); diff --git a/trunk/drivers/media/dvb/siano/Kconfig b/trunk/drivers/media/dvb/siano/Kconfig index 8c1aed77ea30..88847d1dcbb5 100644 --- a/trunk/drivers/media/dvb/siano/Kconfig +++ b/trunk/drivers/media/dvb/siano/Kconfig @@ -2,33 +2,25 @@ # Siano Mobile Silicon Digital TV device configuration # -config SMS_SIANO_MDTV - tristate "Siano SMS1xxx based MDTV receiver" - depends on DVB_CORE && INPUT +config DVB_SIANO_SMS1XXX + tristate "Siano SMS1XXX USB dongle support" + depends on DVB_CORE && USB && INPUT ---help--- - Choose Y or M here if you have MDTV receiver with a Siano chipset. + Choose Y here if you have a USB dongle with a SMS1XXX chipset. - To compile this driver as a module, choose M here - (The module will be called smsmdtv). + To compile this driver as a module, choose M here: the + module will be called sms1xxx. - Further documentation on this driver can be found on the WWW - at http://www.siano-ms.com/ - -if SMS_SIANO_MDTV -menu "Siano module components" +config DVB_SIANO_SMS1XXX_SMS_IDS + bool "Enable support for Siano Mobile Silicon default USB IDs" + depends on DVB_SIANO_SMS1XXX + default y + ---help--- + Choose Y here if you have a USB dongle with a SMS1XXX chipset + that uses Siano Mobile Silicon's default usb vid:pid. -# Hardware interfaces support + Choose N here if you would prefer to use Siano's external driver. -config SMS_USB_DRV - tristate "USB interface support" - depends on DVB_CORE && USB - ---help--- - Choose if you would like to have Siano's support for USB interface + Further documentation on this driver can be found on the WWW at + . -config SMS_SDIO_DRV - tristate "SDIO interface support" - depends on DVB_CORE && MMC - ---help--- - Choose if you would like to have Siano's support for SDIO interface -endmenu -endif # SMS_SIANO_MDTV diff --git a/trunk/drivers/media/dvb/siano/Makefile b/trunk/drivers/media/dvb/siano/Makefile index c54140b5ab5a..c6644d909433 100644 --- a/trunk/drivers/media/dvb/siano/Makefile +++ b/trunk/drivers/media/dvb/siano/Makefile @@ -1,9 +1,8 @@ +sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o -smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o - -obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o -obj-$(CONFIG_SMS_USB_DRV) += smsusb.o -obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o +obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o +obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o +obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsdvb.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core diff --git a/trunk/drivers/media/dvb/siano/smsdvb.c b/trunk/drivers/media/dvb/siano/smsdvb.c index 266033ae2784..3ee1c3902c56 100644 --- a/trunk/drivers/media/dvb/siano/smsdvb.c +++ b/trunk/drivers/media/dvb/siano/smsdvb.c @@ -325,16 +325,6 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, 0 : -ETIME; } -static inline int led_feedback(struct smsdvb_client_t *client) -{ - if (client->fe_status & FE_HAS_LOCK) - return sms_board_led_feedback(client->coredev, - (client->sms_stat_dvb.ReceptionData.BER - == 0) ? SMS_LED_HI : SMS_LED_LO); - else - return sms_board_led_feedback(client->coredev, SMS_LED_OFF); -} - static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) { struct smsdvb_client_t *client; @@ -342,8 +332,6 @@ static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) *stat = client->fe_status; - led_feedback(client); - return 0; } @@ -354,8 +342,6 @@ static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) *ber = client->sms_stat_dvb.ReceptionData.BER; - led_feedback(client); - return 0; } @@ -373,8 +359,6 @@ static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) (client->sms_stat_dvb.ReceptionData.InBandPwr + 95) * 3 / 2; - led_feedback(client); - return 0; } @@ -385,8 +369,6 @@ static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) *snr = client->sms_stat_dvb.ReceptionData.SNR; - led_feedback(client); - return 0; } @@ -397,8 +379,6 @@ static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; - led_feedback(client); - return 0; } @@ -424,8 +404,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, u32 Data[3]; } Msg; - int ret; - client->fe_status = FE_HAS_SIGNAL; client->event_fe_state = -1; client->event_unc_state = -1; @@ -448,23 +426,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, case BANDWIDTH_AUTO: return -EOPNOTSUPP; default: return -EINVAL; } - /* Disable LNA, if any. An error is returned if no LNA is present */ - ret = sms_board_lna_control(client->coredev, 0); - if (ret == 0) { - fe_status_t status; - - /* tune with LNA off at first */ - ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), - &client->tune_done); - - smsdvb_read_status(fe, &status); - - if (status & FE_HAS_LOCK) - return ret; - - /* previous tune didnt lock - enable LNA and tune again */ - sms_board_lna_control(client->coredev, 1); - } return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), &client->tune_done); @@ -490,8 +451,6 @@ static int smsdvb_init(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); - sms_board_power(client->coredev, 1); - sms_board_dvb3_event(client, DVB3_EVENT_INIT); return 0; } @@ -501,9 +460,6 @@ static int smsdvb_sleep(struct dvb_frontend *fe) struct smsdvb_client_t *client = container_of(fe, struct smsdvb_client_t, frontend); - sms_board_led_feedback(client->coredev, SMS_LED_OFF); - sms_board_power(client->coredev, 0); - sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); return 0; diff --git a/trunk/drivers/media/dvb/siano/smssdio.c b/trunk/drivers/media/dvb/siano/smssdio.c index d1d652e7f890..dfaa49a53f32 100644 --- a/trunk/drivers/media/dvb/siano/smssdio.c +++ b/trunk/drivers/media/dvb/siano/smssdio.c @@ -46,7 +46,6 @@ #define SMSSDIO_DATA 0x00 #define SMSSDIO_INT 0x04 -#define SMSSDIO_BLOCK_SIZE 128 static const struct sdio_device_id smssdio_ids[] = { {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), @@ -86,8 +85,7 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size) sdio_claim_host(smsdev->func); while (size >= smsdev->func->cur_blksize) { - ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA, - buffer, smsdev->func->cur_blksize); + ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1); if (ret) goto out; @@ -96,8 +94,8 @@ static int smssdio_sendrequest(void *context, void *buffer, size_t size) } if (size) { - ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA, - buffer, size); + ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA, + buffer, size); } out: @@ -127,23 +125,23 @@ static void smssdio_interrupt(struct sdio_func *func) */ isr = sdio_readb(func, SMSSDIO_INT, &ret); if (ret) { - sms_err("Unable to read interrupt register!\n"); + dev_err(&smsdev->func->dev, + "Unable to read interrupt register!\n"); return; } if (smsdev->split_cb == NULL) { cb = smscore_getbuffer(smsdev->coredev); if (!cb) { - sms_err("Unable to allocate data buffer!\n"); + dev_err(&smsdev->func->dev, + "Unable to allocate data buffer!\n"); return; } - ret = sdio_memcpy_fromio(smsdev->func, - cb->p, - SMSSDIO_DATA, - SMSSDIO_BLOCK_SIZE); + ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); if (ret) { - sms_err("Error %d reading initial block!\n", ret); + dev_err(&smsdev->func->dev, + "Error %d reading initial block!\n", ret); return; } @@ -154,10 +152,7 @@ static void smssdio_interrupt(struct sdio_func *func) return; } - if (hdr->msgLength > smsdev->func->cur_blksize) - size = hdr->msgLength - smsdev->func->cur_blksize; - else - size = 0; + size = hdr->msgLength - smsdev->func->cur_blksize; } else { cb = smsdev->split_cb; hdr = cb->p; @@ -167,24 +162,23 @@ static void smssdio_interrupt(struct sdio_func *func) smsdev->split_cb = NULL; } - if (size) { + if (hdr->msgLength > smsdev->func->cur_blksize) { void *buffer; - buffer = cb->p + (hdr->msgLength - size); - size = ALIGN(size, SMSSDIO_BLOCK_SIZE); + size = ALIGN(size, 128); + buffer = cb->p + hdr->msgLength; - BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); + BUG_ON(smsdev->func->cur_blksize != 128); /* * First attempt to transfer all of it in one go... */ - ret = sdio_memcpy_fromio(smsdev->func, - buffer, - SMSSDIO_DATA, - size); + ret = sdio_read_blocks(smsdev->func, buffer, + SMSSDIO_DATA, size / 128); if (ret && ret != -EINVAL) { smscore_putbuffer(smsdev->coredev, cb); - sms_err("Error %d reading data from card!\n", ret); + dev_err(&smsdev->func->dev, + "Error %d reading data from card!\n", ret); return; } @@ -197,12 +191,12 @@ static void smssdio_interrupt(struct sdio_func *func) */ if (ret == -EINVAL) { while (size) { - ret = sdio_memcpy_fromio(smsdev->func, - buffer, SMSSDIO_DATA, - smsdev->func->cur_blksize); + ret = sdio_read_blocks(smsdev->func, + buffer, SMSSDIO_DATA, 1); if (ret) { smscore_putbuffer(smsdev->coredev, cb); - sms_err("Error %d reading " + dev_err(&smsdev->func->dev, + "Error %d reading " "data from card!\n", ret); return; } @@ -275,7 +269,7 @@ static int smssdio_probe(struct sdio_func *func, if (ret) goto release; - ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE); + ret = sdio_set_block_size(func, 128); if (ret) goto disable; diff --git a/trunk/drivers/media/video/em28xx/em28xx-cards.c b/trunk/drivers/media/video/em28xx/em28xx-cards.c index 1c2e544eda73..ed281f565945 100644 --- a/trunk/drivers/media/video/em28xx/em28xx-cards.c +++ b/trunk/drivers/media/video/em28xx/em28xx-cards.c @@ -1730,25 +1730,6 @@ static inline void em28xx_set_model(struct em28xx *dev) EM28XX_I2C_FREQ_100_KHZ; } - -/* FIXME: Should be replaced by a proper mt9m111 driver */ -static int em28xx_initialize_mt9m111(struct em28xx *dev) -{ - int i; - unsigned char regs[][3] = { - { 0x0d, 0x00, 0x01, }, /* reset and use defaults */ - { 0x0d, 0x00, 0x00, }, - { 0x0a, 0x00, 0x21, }, - { 0x21, 0x04, 0x00, }, /* full readout speed, no row/col skipping */ - }; - - for (i = 0; i < ARRAY_SIZE(regs); i++) - i2c_master_send(&dev->i2c_client, ®s[i][0], 3); - - return 0; -} - - /* FIXME: Should be replaced by a proper mt9m001 driver */ static int em28xx_initialize_mt9m001(struct em28xx *dev) { @@ -1777,7 +1758,7 @@ static int em28xx_initialize_mt9m001(struct em28xx *dev) /* HINT method: webcam I2C chips * - * This method works for webcams with Micron sensors + * This method work for webcams with Micron sensors */ static int em28xx_hint_sensor(struct em28xx *dev) { @@ -1823,23 +1804,6 @@ static int em28xx_hint_sensor(struct em28xx *dev) dev->vinctl = 0x00; break; - - case 0x143a: /* MT9M111 as found in the ECS G200 */ - dev->model = EM2750_BOARD_UNKNOWN; - em28xx_set_model(dev); - - sensor_name = "mt9m111"; - dev->board.xclk = EM28XX_XCLK_FREQUENCY_48MHZ; - dev->em28xx_sensor = EM28XX_MT9M111; - em28xx_initialize_mt9m111(dev); - dev->sensor_xres = 640; - dev->sensor_yres = 512; - - dev->vinmode = 0x0a; - dev->vinctl = 0x00; - - break; - case 0x8431: dev->model = EM2750_BOARD_UNKNOWN; em28xx_set_model(dev); @@ -1856,7 +1820,7 @@ static int em28xx_hint_sensor(struct em28xx *dev) break; default: - printk("Unknown Micron Sensor 0x%04x\n", version); + printk("Unknown Micron Sensor 0x%04x\n", be16_to_cpu(version)); return -EINVAL; } @@ -2382,9 +2346,7 @@ void em28xx_card_setup(struct em28xx *dev) } em28xx_tuner_setup(dev); - - if(!disable_ir) - em28xx_ir_init(dev); + em28xx_ir_init(dev); } diff --git a/trunk/drivers/media/video/em28xx/em28xx.h b/trunk/drivers/media/video/em28xx/em28xx.h index a2add61f7d59..8c2dc38bca9f 100644 --- a/trunk/drivers/media/video/em28xx/em28xx.h +++ b/trunk/drivers/media/video/em28xx/em28xx.h @@ -367,7 +367,6 @@ enum em28xx_sensor { EM28XX_NOSENSOR = 0, EM28XX_MT9V011, EM28XX_MT9M001, - EM28XX_MT9M111, }; enum em28xx_adecoder { diff --git a/trunk/drivers/media/video/gspca/Kconfig b/trunk/drivers/media/video/gspca/Kconfig index e994dcac43ff..34f46f2bc040 100644 --- a/trunk/drivers/media/video/gspca/Kconfig +++ b/trunk/drivers/media/video/gspca/Kconfig @@ -114,7 +114,7 @@ config USB_GSPCA_SN9C20X config USB_GSPCA_SN9C20X_EVDEV bool "Enable evdev support" - depends on USB_GSPCA_SN9C20X && INPUT + depends on USB_GSPCA_SN9C20X ---help--- Say Y here in order to enable evdev support for sn9c20x webcam button. diff --git a/trunk/drivers/media/video/zr364xx.c b/trunk/drivers/media/video/zr364xx.c index 2622a6e63da1..fc976f42f432 100644 --- a/trunk/drivers/media/video/zr364xx.c +++ b/trunk/drivers/media/video/zr364xx.c @@ -695,7 +695,7 @@ static int zr364xx_release(struct file *file) for (i = 0; i < 2; i++) { err = send_control_msg(udev, 1, init[cam->method][i].value, - 0, init[cam->method][i].bytes, + 0, init[i][cam->method].bytes, init[cam->method][i].size); if (err < 0) { dev_err(&udev->dev, "error during release sequence\n"); diff --git a/trunk/drivers/mtd/devices/m25p80.c b/trunk/drivers/mtd/devices/m25p80.c index 10ed195c0c1c..ae5fe91867e1 100644 --- a/trunk/drivers/mtd/devices/m25p80.c +++ b/trunk/drivers/mtd/devices/m25p80.c @@ -736,7 +736,7 @@ static int __devinit m25p_probe(struct spi_device *spi) flash->partitioned = 1; return add_mtd_partitions(&flash->mtd, parts, nr_parts); } - } else if (data && data->nr_parts) + } else if (data->nr_parts) dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", data->nr_parts, data->name); diff --git a/trunk/drivers/mtd/nftlcore.c b/trunk/drivers/mtd/nftlcore.c index 1002e1882996..fb86cacd5bdb 100644 --- a/trunk/drivers/mtd/nftlcore.c +++ b/trunk/drivers/mtd/nftlcore.c @@ -135,17 +135,16 @@ static void nftl_remove_dev(struct mtd_blktrans_dev *dev) int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf) { - loff_t mask = mtd->writesize - 1; struct mtd_oob_ops ops; int res; ops.mode = MTD_OOB_PLACE; - ops.ooboffs = offs & mask; + ops.ooboffs = offs & (mtd->writesize - 1); ops.ooblen = len; ops.oobbuf = buf; ops.datbuf = NULL; - res = mtd->read_oob(mtd, offs & ~mask, &ops); + res = mtd->read_oob(mtd, offs & ~(mtd->writesize - 1), &ops); *retlen = ops.oobretlen; return res; } @@ -156,17 +155,16 @@ int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf) { - loff_t mask = mtd->writesize - 1; struct mtd_oob_ops ops; int res; ops.mode = MTD_OOB_PLACE; - ops.ooboffs = offs & mask; + ops.ooboffs = offs & (mtd->writesize - 1); ops.ooblen = len; ops.oobbuf = buf; ops.datbuf = NULL; - res = mtd->write_oob(mtd, offs & ~mask, &ops); + res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); *retlen = ops.oobretlen; return res; } @@ -179,18 +177,17 @@ int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, static int nftl_write(struct mtd_info *mtd, loff_t offs, size_t len, size_t *retlen, uint8_t *buf, uint8_t *oob) { - loff_t mask = mtd->writesize - 1; struct mtd_oob_ops ops; int res; ops.mode = MTD_OOB_PLACE; - ops.ooboffs = offs & mask; + ops.ooboffs = offs; ops.ooblen = mtd->oobsize; ops.oobbuf = oob; ops.datbuf = buf; ops.len = len; - res = mtd->write_oob(mtd, offs & ~mask, &ops); + res = mtd->write_oob(mtd, offs & ~(mtd->writesize - 1), &ops); *retlen = ops.retlen; return res; } diff --git a/trunk/drivers/net/gianfar.c b/trunk/drivers/net/gianfar.c index a00ec639c380..e212f2c5448b 100644 --- a/trunk/drivers/net/gianfar.c +++ b/trunk/drivers/net/gianfar.c @@ -491,7 +491,6 @@ static int gfar_remove(struct of_device *ofdev) dev_set_drvdata(&ofdev->dev, NULL); - unregister_netdev(priv->ndev); iounmap(priv->regs); free_netdev(priv->ndev); diff --git a/trunk/drivers/net/wireless/ipw2x00/ipw2200.c b/trunk/drivers/net/wireless/ipw2x00/ipw2200.c index f593fbbb4e52..6dcac73b4d29 100644 --- a/trunk/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/trunk/drivers/net/wireless/ipw2x00/ipw2200.c @@ -2874,27 +2874,45 @@ static int ipw_fw_dma_add_command_block(struct ipw_priv *priv, return 0; } -static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address, - int nr, u32 dest_address, u32 len) +static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, + u32 src_phys, u32 dest_address, u32 length) { - int ret, i; - u32 size; - + u32 bytes_left = length; + u32 src_offset = 0; + u32 dest_offset = 0; + int status = 0; IPW_DEBUG_FW(">> \n"); - IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n", - nr, dest_address, len); - - for (i = 0; i < nr; i++) { - size = min_t(u32, len - i * CB_MAX_LENGTH, CB_MAX_LENGTH); - ret = ipw_fw_dma_add_command_block(priv, src_address[i], - dest_address + - i * CB_MAX_LENGTH, size, - 0, 0); - if (ret) { + IPW_DEBUG_FW_INFO("src_phys=0x%x dest_address=0x%x length=0x%x\n", + src_phys, dest_address, length); + while (bytes_left > CB_MAX_LENGTH) { + status = ipw_fw_dma_add_command_block(priv, + src_phys + src_offset, + dest_address + + dest_offset, + CB_MAX_LENGTH, 0, 0); + if (status) { IPW_DEBUG_FW_INFO(": Failed\n"); return -1; } else IPW_DEBUG_FW_INFO(": Added new cb\n"); + + src_offset += CB_MAX_LENGTH; + dest_offset += CB_MAX_LENGTH; + bytes_left -= CB_MAX_LENGTH; + } + + /* add the buffer tail */ + if (bytes_left > 0) { + status = + ipw_fw_dma_add_command_block(priv, src_phys + src_offset, + dest_address + dest_offset, + bytes_left, 0, 0); + if (status) { + IPW_DEBUG_FW_INFO(": Failed on the buffer tail\n"); + return -1; + } else + IPW_DEBUG_FW_INFO + (": Adding new cb - the buffer tail\n"); } IPW_DEBUG_FW("<< \n"); @@ -3142,91 +3160,59 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) { - int ret = -1; + int rc = -1; int offset = 0; struct fw_chunk *chunk; - int total_nr = 0; - int i; - struct pci_pool *pool; - u32 *virts[CB_NUMBER_OF_ELEMENTS_SMALL]; - dma_addr_t phys[CB_NUMBER_OF_ELEMENTS_SMALL]; + dma_addr_t shared_phys; + u8 *shared_virt; IPW_DEBUG_TRACE("<< : \n"); + shared_virt = pci_alloc_consistent(priv->pci_dev, len, &shared_phys); - pool = pci_pool_create("ipw2200", priv->pci_dev, CB_MAX_LENGTH, 0, 0); - if (!pool) { - IPW_ERROR("pci_pool_create failed\n"); + if (!shared_virt) return -ENOMEM; - } + + memmove(shared_virt, data, len); /* Start the Dma */ - ret = ipw_fw_dma_enable(priv); + rc = ipw_fw_dma_enable(priv); /* the DMA is already ready this would be a bug. */ BUG_ON(priv->sram_desc.last_cb_index > 0); do { - u32 chunk_len; - u8 *start; - int size; - int nr = 0; - chunk = (struct fw_chunk *)(data + offset); offset += sizeof(struct fw_chunk); - chunk_len = le32_to_cpu(chunk->length); - start = data + offset; - - nr = (chunk_len + CB_MAX_LENGTH - 1) / CB_MAX_LENGTH; - for (i = 0; i < nr; i++) { - virts[total_nr] = pci_pool_alloc(pool, GFP_KERNEL, - &phys[total_nr]); - if (!virts[total_nr]) { - ret = -ENOMEM; - goto out; - } - size = min_t(u32, chunk_len - i * CB_MAX_LENGTH, - CB_MAX_LENGTH); - memcpy(virts[total_nr], start, size); - start += size; - total_nr++; - /* We don't support fw chunk larger than 64*8K */ - BUG_ON(total_nr > CB_NUMBER_OF_ELEMENTS_SMALL); - } - /* build DMA packet and queue up for sending */ /* dma to chunk->address, the chunk->length bytes from data + * offeset*/ /* Dma loading */ - ret = ipw_fw_dma_add_buffer(priv, &phys[total_nr - nr], - nr, le32_to_cpu(chunk->address), - chunk_len); - if (ret) { + rc = ipw_fw_dma_add_buffer(priv, shared_phys + offset, + le32_to_cpu(chunk->address), + le32_to_cpu(chunk->length)); + if (rc) { IPW_DEBUG_INFO("dmaAddBuffer Failed\n"); goto out; } - offset += chunk_len; + offset += le32_to_cpu(chunk->length); } while (offset < len); /* Run the DMA and wait for the answer */ - ret = ipw_fw_dma_kick(priv); - if (ret) { + rc = ipw_fw_dma_kick(priv); + if (rc) { IPW_ERROR("dmaKick Failed\n"); goto out; } - ret = ipw_fw_dma_wait(priv); - if (ret) { + rc = ipw_fw_dma_wait(priv); + if (rc) { IPW_ERROR("dmaWaitSync Failed\n"); goto out; } - out: - for (i = 0; i < total_nr; i++) - pci_pool_free(pool, virts[i], phys[i]); - - pci_pool_destroy(pool); - - return ret; + out: + pci_free_consistent(priv->pci_dev, len, shared_virt, shared_phys); + return rc; } /* stop nic */ diff --git a/trunk/drivers/pci/iov.c b/trunk/drivers/pci/iov.c index e03fe98f0619..e3a87210e947 100644 --- a/trunk/drivers/pci/iov.c +++ b/trunk/drivers/pci/iov.c @@ -597,29 +597,6 @@ int pci_iov_resource_bar(struct pci_dev *dev, int resno, 4 * (resno - PCI_IOV_RESOURCES); } -/** - * pci_sriov_resource_alignment - get resource alignment for VF BAR - * @dev: the PCI device - * @resno: the resource number - * - * Returns the alignment of the VF BAR found in the SR-IOV capability. - * This is not the same as the resource size which is defined as - * the VF BAR size multiplied by the number of VFs. The alignment - * is just the VF BAR size. - */ -int pci_sriov_resource_alignment(struct pci_dev *dev, int resno) -{ - struct resource tmp; - enum pci_bar_type type; - int reg = pci_iov_resource_bar(dev, resno, &type); - - if (!reg) - return 0; - - __pci_read_base(dev, type, &tmp, reg); - return resource_alignment(&tmp); -} - /** * pci_restore_iov_state - restore the state of the IOV capability * @dev: the PCI device diff --git a/trunk/drivers/pci/pci.h b/trunk/drivers/pci/pci.h index 5ff4d25bf0e9..f73bcbedf37c 100644 --- a/trunk/drivers/pci/pci.h +++ b/trunk/drivers/pci/pci.h @@ -243,7 +243,6 @@ extern int pci_iov_init(struct pci_dev *dev); extern void pci_iov_release(struct pci_dev *dev); extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); -extern int pci_sriov_resource_alignment(struct pci_dev *dev, int resno); extern void pci_restore_iov_state(struct pci_dev *dev); extern int pci_iov_bus_range(struct pci_bus *bus); @@ -299,16 +298,4 @@ static inline int pci_ats_enabled(struct pci_dev *dev) } #endif /* CONFIG_PCI_IOV */ -static inline int pci_resource_alignment(struct pci_dev *dev, - struct resource *res) -{ -#ifdef CONFIG_PCI_IOV - int resno = res - dev->resource; - - if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END) - return pci_sriov_resource_alignment(dev, resno); -#endif - return resource_alignment(res); -} - #endif /* DRIVERS_PCI_H */ diff --git a/trunk/drivers/pci/setup-bus.c b/trunk/drivers/pci/setup-bus.c index 7c443b4583ab..b636e245445d 100644 --- a/trunk/drivers/pci/setup-bus.c +++ b/trunk/drivers/pci/setup-bus.c @@ -25,7 +25,7 @@ #include #include #include -#include "pci.h" + static void pbus_assign_resources_sorted(const struct pci_bus *bus) { @@ -384,7 +384,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long continue; r_size = resource_size(r); /* For bridges size != alignment */ - align = pci_resource_alignment(dev, r); + align = resource_alignment(r); order = __ffs(align) - 20; if (order > 11) { dev_warn(&dev->dev, "BAR %d bad alignment %llx: " diff --git a/trunk/drivers/pci/setup-res.c b/trunk/drivers/pci/setup-res.c index 88cdd1a937d6..1898c7b47907 100644 --- a/trunk/drivers/pci/setup-res.c +++ b/trunk/drivers/pci/setup-res.c @@ -144,7 +144,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev, size = resource_size(res); min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; - align = pci_resource_alignment(dev, res); + align = resource_alignment(res); /* First, try exact prefetching match.. */ ret = pci_bus_alloc_resource(bus, res, size, align, min, @@ -178,7 +178,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno) struct pci_bus *bus; int ret; - align = pci_resource_alignment(dev, res); + align = resource_alignment(res); if (!align) { dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus " "alignment) %pR flags %#lx\n", @@ -259,7 +259,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) if (!(r->flags) || r->parent) continue; - r_align = pci_resource_alignment(dev, r); + r_align = resource_alignment(r); if (!r_align) { dev_warn(&dev->dev, "BAR %d: bogus alignment " "%pR flags %#lx\n", @@ -271,7 +271,7 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head) struct resource_list *ln = list->next; if (ln) - align = pci_resource_alignment(ln->dev, ln->res); + align = resource_alignment(ln->res); if (r_align > align) { tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); diff --git a/trunk/drivers/platform/x86/toshiba_acpi.c b/trunk/drivers/platform/x86/toshiba_acpi.c index 51c0a8bee414..81d31ea507d1 100644 --- a/trunk/drivers/platform/x86/toshiba_acpi.c +++ b/trunk/drivers/platform/x86/toshiba_acpi.c @@ -335,7 +335,6 @@ static void bt_rfkill_poll(struct rfkill *rfkill, void *data) if (hci_result != HCI_SUCCESS) { /* Can't do anything useful */ mutex_unlock(&dev->mutex); - return; } new_rfk_state = value; diff --git a/trunk/fs/autofs4/expire.c b/trunk/fs/autofs4/expire.c index 3da18d453488..aa39ae83f019 100644 --- a/trunk/fs/autofs4/expire.c +++ b/trunk/fs/autofs4/expire.c @@ -77,7 +77,7 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) } /* Update the expiry counter if fs is busy */ - if (!may_umount_tree(path.mnt)) { + if (!may_umount_tree(mnt)) { struct autofs_info *ino = autofs4_dentry_ino(top); ino->last_used = jiffies; goto done; diff --git a/trunk/fs/compat.c b/trunk/fs/compat.c index 6d6f98fe64a0..94502dab972a 100644 --- a/trunk/fs/compat.c +++ b/trunk/fs/compat.c @@ -1485,15 +1485,20 @@ int compat_do_execve(char * filename, if (!bprm) goto out_files; - retval = prepare_bprm_creds(bprm); - if (retval) + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(¤t->cred_guard_mutex)) goto out_free; + current->in_execve = 1; + + retval = -ENOMEM; + bprm->cred = prepare_exec_creds(); + if (!bprm->cred) + goto out_unlock; retval = check_unsafe_exec(bprm); if (retval < 0) - goto out_free; + goto out_unlock; clear_in_exec = retval; - current->in_execve = 1; file = open_exec(filename); retval = PTR_ERR(file); @@ -1542,6 +1547,7 @@ int compat_do_execve(char * filename, /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; + mutex_unlock(¤t->cred_guard_mutex); acct_update_integrals(current); free_bprm(bprm); if (displaced) @@ -1561,7 +1567,10 @@ int compat_do_execve(char * filename, out_unmark: if (clear_in_exec) current->fs->in_exec = 0; + +out_unlock: current->in_execve = 0; + mutex_unlock(¤t->cred_guard_mutex); out_free: free_bprm(bprm); diff --git a/trunk/fs/exec.c b/trunk/fs/exec.c index 172ceb6edde4..fb4f3cdda78c 100644 --- a/trunk/fs/exec.c +++ b/trunk/fs/exec.c @@ -1015,35 +1015,6 @@ int flush_old_exec(struct linux_binprm * bprm) EXPORT_SYMBOL(flush_old_exec); -/* - * Prepare credentials and lock ->cred_guard_mutex. - * install_exec_creds() commits the new creds and drops the lock. - * Or, if exec fails before, free_bprm() should release ->cred and - * and unlock. - */ -int prepare_bprm_creds(struct linux_binprm *bprm) -{ - if (mutex_lock_interruptible(¤t->cred_guard_mutex)) - return -ERESTARTNOINTR; - - bprm->cred = prepare_exec_creds(); - if (likely(bprm->cred)) - return 0; - - mutex_unlock(¤t->cred_guard_mutex); - return -ENOMEM; -} - -void free_bprm(struct linux_binprm *bprm) -{ - free_arg_pages(bprm); - if (bprm->cred) { - mutex_unlock(¤t->cred_guard_mutex); - abort_creds(bprm->cred); - } - kfree(bprm); -} - /* * install the new credentials for this executable */ @@ -1053,13 +1024,12 @@ void install_exec_creds(struct linux_binprm *bprm) commit_creds(bprm->cred); bprm->cred = NULL; - /* - * cred_guard_mutex must be held at least to this point to prevent + + /* cred_guard_mutex must be held at least to this point to prevent * ptrace_attach() from altering our determination of the task's - * credentials; any time after this it may be unlocked. - */ + * credentials; any time after this it may be unlocked */ + security_bprm_committed_creds(bprm); - mutex_unlock(¤t->cred_guard_mutex); } EXPORT_SYMBOL(install_exec_creds); @@ -1276,6 +1246,14 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) EXPORT_SYMBOL(search_binary_handler); +void free_bprm(struct linux_binprm *bprm) +{ + free_arg_pages(bprm); + if (bprm->cred) + abort_creds(bprm->cred); + kfree(bprm); +} + /* * sys_execve() executes a new program. */ @@ -1299,15 +1277,20 @@ int do_execve(char * filename, if (!bprm) goto out_files; - retval = prepare_bprm_creds(bprm); - if (retval) + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(¤t->cred_guard_mutex)) goto out_free; + current->in_execve = 1; + + retval = -ENOMEM; + bprm->cred = prepare_exec_creds(); + if (!bprm->cred) + goto out_unlock; retval = check_unsafe_exec(bprm); if (retval < 0) - goto out_free; + goto out_unlock; clear_in_exec = retval; - current->in_execve = 1; file = open_exec(filename); retval = PTR_ERR(file); @@ -1357,6 +1340,7 @@ int do_execve(char * filename, /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; + mutex_unlock(¤t->cred_guard_mutex); acct_update_integrals(current); free_bprm(bprm); if (displaced) @@ -1376,7 +1360,10 @@ int do_execve(char * filename, out_unmark: if (clear_in_exec) current->fs->in_exec = 0; + +out_unlock: current->in_execve = 0; + mutex_unlock(¤t->cred_guard_mutex); out_free: free_bprm(bprm); diff --git a/trunk/fs/ext2/namei.c b/trunk/fs/ext2/namei.c index 78d9b925fc94..e1dedb0f7873 100644 --- a/trunk/fs/ext2/namei.c +++ b/trunk/fs/ext2/namei.c @@ -362,10 +362,6 @@ static int ext2_rename (struct inode * old_dir, struct dentry * old_dentry, if (dir_de) { if (old_dir != new_dir) ext2_set_link(old_inode, dir_de, dir_page, new_dir, 0); - else { - kunmap(dir_page); - page_cache_release(dir_page); - } inode_dec_link_count(old_dir); } return 0; diff --git a/trunk/fs/jffs2/wbuf.c b/trunk/fs/jffs2/wbuf.c index 5ef7bac265e5..d9a721e6db70 100644 --- a/trunk/fs/jffs2/wbuf.c +++ b/trunk/fs/jffs2/wbuf.c @@ -1268,20 +1268,10 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { if (!c->wbuf) return -ENOMEM; -#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY - c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL); - if (!c->wbuf_verify) { - kfree(c->wbuf); - return -ENOMEM; - } -#endif return 0; } void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) { -#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY - kfree(c->wbuf_verify); -#endif kfree(c->wbuf); } diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 1f13751693a5..f3c5b278895a 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -1542,31 +1542,28 @@ int may_open(struct path *path, int acc_mode, int flag) * An append-only file must be opened in append mode for writing. */ if (IS_APPEND(inode)) { - error = -EPERM; if ((flag & FMODE_WRITE) && !(flag & O_APPEND)) - goto err_out; + return -EPERM; if (flag & O_TRUNC) - goto err_out; + return -EPERM; } /* O_NOATIME can only be set by the owner or superuser */ if (flag & O_NOATIME) - if (!is_owner_or_cap(inode)) { - error = -EPERM; - goto err_out; - } + if (!is_owner_or_cap(inode)) + return -EPERM; /* * Ensure there are no outstanding leases on the file. */ error = break_lease(inode, flag); if (error) - goto err_out; + return error; if (flag & O_TRUNC) { error = get_write_access(inode); if (error) - goto err_out; + return error; /* * Refuse to truncate files with mandatory locks held on them. @@ -1584,17 +1581,12 @@ int may_open(struct path *path, int acc_mode, int flag) } put_write_access(inode); if (error) - goto err_out; + return error; } else if (flag & FMODE_WRITE) vfs_dq_init(inode); return 0; -err_out: - ima_counts_put(path, acc_mode ? - acc_mode & (MAY_READ | MAY_WRITE | MAY_EXEC) : - ACC_MODE(flag) & (MAY_READ | MAY_WRITE)); - return error; } /* diff --git a/trunk/fs/nilfs2/btnode.c b/trunk/fs/nilfs2/btnode.c index c668bca579c1..7e0b61be212e 100644 --- a/trunk/fs/nilfs2/btnode.c +++ b/trunk/fs/nilfs2/btnode.c @@ -209,7 +209,6 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc, * We cannot call radix_tree_preload for the kernels older * than 2.6.23, because it is not exported for modules. */ -retry: err = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM); if (err) goto failed_unlock; @@ -220,6 +219,7 @@ int nilfs_btnode_prepare_change_key(struct address_space *btnc, (unsigned long long)oldkey, (unsigned long long)newkey); +retry: spin_lock_irq(&btnc->tree_lock); err = radix_tree_insert(&btnc->page_tree, newkey, obh->b_page); spin_unlock_irq(&btnc->tree_lock); diff --git a/trunk/fs/notify/inotify/inotify_user.c b/trunk/fs/notify/inotify/inotify_user.c index dcd2040d330c..0e781bc88d1e 100644 --- a/trunk/fs/notify/inotify/inotify_user.c +++ b/trunk/fs/notify/inotify/inotify_user.c @@ -154,8 +154,7 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group, event = fsnotify_peek_notify_event(group); - if (event->name_len) - event_size += roundup(event->name_len + 1, event_size); + event_size += roundup(event->name_len, event_size); if (event_size > count) return ERR_PTR(-EINVAL); @@ -181,7 +180,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, struct fsnotify_event_private_data *fsn_priv; struct inotify_event_private_data *priv; size_t event_size = sizeof(struct inotify_event); - size_t name_len = 0; + size_t name_len; /* we get the inotify watch descriptor from the event private data */ spin_lock(&event->lock); @@ -197,12 +196,10 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group, inotify_free_event_priv(fsn_priv); } - /* - * round up event->name_len so it is a multiple of event_size + /* round up event->name_len so it is a multiple of event_size * plus an extra byte for the terminating '\0'. */ - if (event->name_len) - name_len = roundup(event->name_len + 1, event_size); + name_len = roundup(event->name_len + 1, event_size); inotify_event.len = name_len; inotify_event.mask = inotify_mask_to_arg(event->mask); @@ -328,9 +325,8 @@ static long inotify_ioctl(struct file *file, unsigned int cmd, list_for_each_entry(holder, &group->notification_list, event_list) { event = holder->event; send_len += sizeof(struct inotify_event); - if (event->name_len) - send_len += roundup(event->name_len + 1, - sizeof(struct inotify_event)); + send_len += roundup(event->name_len, + sizeof(struct inotify_event)); } mutex_unlock(&group->notification_mutex); ret = put_user(send_len, (int __user *) p); @@ -591,10 +587,6 @@ static int inotify_new_watch(struct fsnotify_group *group, /* match the ref from fsnotify_init_markentry() */ fsnotify_put_mark(&tmp_ientry->fsn_entry); - /* if this mark added a new event update the group mask */ - if (mask & ~group->mask) - fsnotify_recalc_group_mask(group); - out_err: if (ret < 0) kmem_cache_free(inotify_inode_mark_cachep, tmp_ientry); diff --git a/trunk/fs/ocfs2/aops.c b/trunk/fs/ocfs2/aops.c index 8a1e61545f41..b401654011a2 100644 --- a/trunk/fs/ocfs2/aops.c +++ b/trunk/fs/ocfs2/aops.c @@ -1747,8 +1747,8 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, * we know zeros will only be needed in the first and/or last cluster. */ if (clusters_to_alloc || extents_to_split || - (wc->w_clen && (wc->w_desc[0].c_needs_zero || - wc->w_desc[wc->w_clen - 1].c_needs_zero))) + wc->w_desc[0].c_needs_zero || + wc->w_desc[wc->w_clen - 1].c_needs_zero) cluster_of_pages = 1; else cluster_of_pages = 0; diff --git a/trunk/fs/ocfs2/dcache.c b/trunk/fs/ocfs2/dcache.c index b4957c7d9fe2..2f28b7de2c8d 100644 --- a/trunk/fs/ocfs2/dcache.c +++ b/trunk/fs/ocfs2/dcache.c @@ -85,17 +85,6 @@ static int ocfs2_dentry_revalidate(struct dentry *dentry, goto bail; } - /* - * If the last lookup failed to create dentry lock, let us - * redo it. - */ - if (!dentry->d_fsdata) { - mlog(0, "Inode %llu doesn't have dentry lock, " - "returning false\n", - (unsigned long long)OCFS2_I(inode)->ip_blkno); - goto bail; - } - ret = 1; bail: diff --git a/trunk/fs/xfs/linux-2.6/xfs_ioctl32.c b/trunk/fs/xfs/linux-2.6/xfs_ioctl32.c index eafcc7c18706..0882d166239a 100644 --- a/trunk/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/trunk/fs/xfs/linux-2.6/xfs_ioctl32.c @@ -619,7 +619,7 @@ xfs_file_compat_ioctl( case XFS_IOC_GETVERSION_32: cmd = _NATIVE_IOC(cmd, long); return xfs_file_ioctl(filp, cmd, p); - case XFS_IOC_SWAPEXT_32: { + case XFS_IOC_SWAPEXT: { struct xfs_swapext sxp; struct compat_xfs_swapext __user *sxu = arg; diff --git a/trunk/include/crypto/algapi.h b/trunk/include/crypto/algapi.h index 5a2bd1cc9656..010545436efa 100644 --- a/trunk/include/crypto/algapi.h +++ b/trunk/include/crypto/algapi.h @@ -137,7 +137,6 @@ struct crypto_instance *crypto_alloc_instance(const char *name, void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen); int crypto_enqueue_request(struct crypto_queue *queue, struct crypto_async_request *request); -void *__crypto_dequeue_request(struct crypto_queue *queue, unsigned int offset); struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue); int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm); diff --git a/trunk/include/crypto/internal/skcipher.h b/trunk/include/crypto/internal/skcipher.h index 3a748a6bf772..2ba42cd7d6aa 100644 --- a/trunk/include/crypto/internal/skcipher.h +++ b/trunk/include/crypto/internal/skcipher.h @@ -79,8 +79,8 @@ static inline int skcipher_enqueue_givcrypt( static inline struct skcipher_givcrypt_request *skcipher_dequeue_givcrypt( struct crypto_queue *queue) { - return __crypto_dequeue_request( - queue, offsetof(struct skcipher_givcrypt_request, creq.base)); + return container_of(ablkcipher_dequeue_request(queue), + struct skcipher_givcrypt_request, creq); } static inline void *skcipher_givcrypt_reqctx( diff --git a/trunk/include/linux/binfmts.h b/trunk/include/linux/binfmts.h index 2046b5b8af48..61ee18c1bdb4 100644 --- a/trunk/include/linux/binfmts.h +++ b/trunk/include/linux/binfmts.h @@ -117,7 +117,6 @@ extern int setup_arg_pages(struct linux_binprm * bprm, int executable_stack); extern int bprm_mm_init(struct linux_binprm *bprm); extern int copy_strings_kernel(int argc,char ** argv,struct linux_binprm *bprm); -extern int prepare_bprm_creds(struct linux_binprm *bprm); extern void install_exec_creds(struct linux_binprm *bprm); extern void do_coredump(long signr, int exit_code, struct pt_regs *regs); extern int set_binfmt(struct linux_binfmt *new); diff --git a/trunk/include/linux/device-mapper.h b/trunk/include/linux/device-mapper.h index df7607e6dce8..655e7721580a 100644 --- a/trunk/include/linux/device-mapper.h +++ b/trunk/include/linux/device-mapper.h @@ -91,9 +91,6 @@ typedef int (*dm_iterate_devices_fn) (struct dm_target *ti, iterate_devices_callout_fn fn, void *data); -typedef void (*dm_io_hints_fn) (struct dm_target *ti, - struct queue_limits *limits); - /* * Returns: * 0: The target can handle the next I/O immediately. @@ -154,7 +151,6 @@ struct target_type { dm_merge_fn merge; dm_busy_fn busy; dm_iterate_devices_fn iterate_devices; - dm_io_hints_fn io_hints; /* For internal device-mapper use. */ struct list_head list; diff --git a/trunk/include/linux/dm-log-userspace.h b/trunk/include/linux/dm-log-userspace.h index 8a1f972c0fe9..642e3017b51f 100644 --- a/trunk/include/linux/dm-log-userspace.h +++ b/trunk/include/linux/dm-log-userspace.h @@ -371,18 +371,7 @@ (DM_ULOG_REQUEST_MASK & (request_type)) struct dm_ulog_request { - /* - * The local unique identifier (luid) and the universally unique - * identifier (uuid) are used to tie a request to a specific - * mirror log. A single machine log could probably make due with - * just the 'luid', but a cluster-aware log must use the 'uuid' and - * the 'luid'. The uuid is what is required for node to node - * communication concerning a particular log, but the 'luid' helps - * differentiate between logs that are being swapped and have the - * same 'uuid'. (Think "live" and "inactive" device-mapper tables.) - */ - uint64_t luid; - char uuid[DM_UUID_LEN]; + char uuid[DM_UUID_LEN]; /* Ties a request to a specific mirror log */ char padding[7]; /* Padding because DM_UUID_LEN = 129 */ int32_t error; /* Used to report back processing errors */ diff --git a/trunk/include/linux/lmb.h b/trunk/include/linux/lmb.h index 2442e3f3d033..c46c89505dac 100644 --- a/trunk/include/linux/lmb.h +++ b/trunk/include/linux/lmb.h @@ -51,7 +51,7 @@ extern u64 __init lmb_alloc_base(u64 size, extern u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr); extern u64 __init lmb_phys_mem_size(void); -extern u64 lmb_end_of_DRAM(void); +extern u64 __init lmb_end_of_DRAM(void); extern void __init lmb_enforce_memory_limit(u64 memory_limit); extern int __init lmb_is_reserved(u64 addr); extern int lmb_find(struct lmb_property *res); diff --git a/trunk/include/linux/tty.h b/trunk/include/linux/tty.h index 0d3974f59c53..e8c6c9136c97 100644 --- a/trunk/include/linux/tty.h +++ b/trunk/include/linux/tty.h @@ -23,7 +23,7 @@ */ #define NR_UNIX98_PTY_DEFAULT 4096 /* Default maximum for Unix98 ptys */ #define NR_UNIX98_PTY_MAX (1 << MINORBITS) /* Absolute limit */ -#define NR_LDISCS 20 +#define NR_LDISCS 19 /* line disciplines */ #define N_TTY 0 @@ -47,8 +47,6 @@ #define N_SLCAN 17 /* Serial / USB serial CAN Adaptors */ #define N_PPS 18 /* Pulse per Second */ -#define N_V253 19 /* Codec control over voice modem */ - /* * This character is the same as _POSIX_VDISABLE: it cannot be used as * a c_cc[] character, but indicates that a particular special character diff --git a/trunk/include/linux/workqueue.h b/trunk/include/linux/workqueue.h index 6273fa97b527..13e1adf55c4c 100644 --- a/trunk/include/linux/workqueue.h +++ b/trunk/include/linux/workqueue.h @@ -240,21 +240,6 @@ static inline int cancel_delayed_work(struct delayed_work *work) return ret; } -/* - * Like above, but uses del_timer() instead of del_timer_sync(). This means, - * if it returns 0 the timer function may be running and the queueing is in - * progress. - */ -static inline int __cancel_delayed_work(struct delayed_work *work) -{ - int ret; - - ret = del_timer(&work->timer); - if (ret) - work_clear_pending(&work->work); - return ret; -} - extern int cancel_delayed_work_sync(struct delayed_work *work); /* Obsolete. use cancel_delayed_work_sync() */ diff --git a/trunk/include/net/pkt_sched.h b/trunk/include/net/pkt_sched.h index 82a3191375f5..7eafb8d54470 100644 --- a/trunk/include/net/pkt_sched.h +++ b/trunk/include/net/pkt_sched.h @@ -61,8 +61,8 @@ psched_tdiff_bounded(psched_time_t tv1, psched_time_t tv2, psched_time_t bound) } struct qdisc_watchdog { - struct hrtimer timer; - struct Qdisc *qdisc; + struct tasklet_hrtimer timer; + struct Qdisc *qdisc; }; extern void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc); diff --git a/trunk/include/sound/ac97_codec.h b/trunk/include/sound/ac97_codec.h index 3dae3f799b9b..251fc1cd5002 100644 --- a/trunk/include/sound/ac97_codec.h +++ b/trunk/include/sound/ac97_codec.h @@ -32,9 +32,6 @@ #include "control.h" #include "info.h" -/* maximum number of devices on the AC97 bus */ -#define AC97_BUS_MAX_DEVICES 4 - /* * AC'97 codec registers */ @@ -645,10 +642,4 @@ int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime); /* ad hoc AC97 device driver access */ extern struct bus_type ac97_bus_type; -/* AC97 platform_data adding function */ -static inline void snd_ac97_dev_add_pdata(struct snd_ac97 *ac97, void *data) -{ - ac97->dev.platform_data = data; -} - #endif /* __SOUND_AC97_CODEC_H */ diff --git a/trunk/include/sound/memalloc.h b/trunk/include/sound/memalloc.h index c42506212649..7ccce94a5255 100644 --- a/trunk/include/sound/memalloc.h +++ b/trunk/include/sound/memalloc.h @@ -47,11 +47,7 @@ struct snd_dma_device { #define SNDRV_DMA_TYPE_UNKNOWN 0 /* not defined */ #define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */ #define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */ -#ifdef CONFIG_SND_DMA_SGBUF #define SNDRV_DMA_TYPE_DEV_SG 3 /* generic device SG-buffer */ -#else -#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */ -#endif /* * info for buffer allocation @@ -64,7 +60,6 @@ struct snd_dma_buffer { void *private_data; /* private for allocator; don't touch */ }; -#ifdef CONFIG_SND_DMA_SGBUF /* * Scatter-Gather generic device pages */ @@ -112,7 +107,6 @@ static inline void *snd_sgbuf_get_ptr(struct snd_sg_buf *sgbuf, size_t offset) { return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE; } -#endif /* CONFIG_SND_DMA_SGBUF */ /* allocate/release a buffer */ int snd_dma_alloc_pages(int type, struct device *dev, size_t size, diff --git a/trunk/include/sound/pcm.h b/trunk/include/sound/pcm.h index 1691c7fe35af..23893523dc8c 100644 --- a/trunk/include/sound/pcm.h +++ b/trunk/include/sound/pcm.h @@ -902,7 +902,6 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size); int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream); -#ifdef CONFIG_SND_DMA_SGBUF /* * SG-buffer handling */ @@ -928,28 +927,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, unsigned int ofs, unsigned int size); -#else /* !SND_DMA_SGBUF */ -/* - * fake using a continuous buffer - */ -static inline dma_addr_t -snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) -{ - return substream->runtime->dma_addr + ofs; -} - -static inline void * -snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) -{ - return substream->runtime->dma_area + ofs; -} - -#define snd_pcm_sgbuf_ops_page NULL - -#define snd_pcm_sgbuf_get_chunk_size(subs, ofs, size) (size) - -#endif /* SND_DMA_SGBUF */ - /* handle mmap counter - PCM mmap callback should handle this counter properly */ static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) { diff --git a/trunk/include/sound/sh_fsi.h b/trunk/include/sound/sh_fsi.h deleted file mode 100644 index c0227361a876..000000000000 --- a/trunk/include/sound/sh_fsi.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __SOUND_FSI_H -#define __SOUND_FSI_H - -/* - * Fifo-attached Serial Interface (FSI) support for SH7724 - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* flags format - - * 0xABCDEEFF - * - * A: channel size for TDM (input) - * B: channel size for TDM (ooutput) - * C: inversion - * D: mode - * E: input format - * F: output format - */ - -#include -#include - -/* TDM channel */ -#define SH_FSI_SET_CH_I(x) ((x & 0xF) << 28) -#define SH_FSI_SET_CH_O(x) ((x & 0xF) << 24) - -#define SH_FSI_CH_IMASK 0xF0000000 -#define SH_FSI_CH_OMASK 0x0F000000 -#define SH_FSI_GET_CH_I(x) ((x & SH_FSI_CH_IMASK) >> 28) -#define SH_FSI_GET_CH_O(x) ((x & SH_FSI_CH_OMASK) >> 24) - -/* clock inversion */ -#define SH_FSI_INVERSION_MASK 0x00F00000 -#define SH_FSI_LRM_INV (1 << 20) -#define SH_FSI_BRM_INV (1 << 21) -#define SH_FSI_LRS_INV (1 << 22) -#define SH_FSI_BRS_INV (1 << 23) - -/* mode */ -#define SH_FSI_MODE_MASK 0x000F0000 -#define SH_FSI_IN_SLAVE_MODE (1 << 16) /* default master mode */ -#define SH_FSI_OUT_SLAVE_MODE (1 << 17) /* default master mode */ - -/* DI format */ -#define SH_FSI_FMT_MASK 0x000000FF -#define SH_FSI_IFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 8) -#define SH_FSI_OFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 0) -#define SH_FSI_GET_IFMT(x) ((x >> 8) & SH_FSI_FMT_MASK) -#define SH_FSI_GET_OFMT(x) ((x >> 0) & SH_FSI_FMT_MASK) - -#define SH_FSI_FMT_MONO (1 << 0) -#define SH_FSI_FMT_MONO_DELAY (1 << 1) -#define SH_FSI_FMT_PCM (1 << 2) -#define SH_FSI_FMT_I2S (1 << 3) -#define SH_FSI_FMT_TDM (1 << 4) -#define SH_FSI_FMT_TDM_DELAY (1 << 5) - -#define SH_FSI_IFMT_TDM_CH(x) \ - (SH_FSI_IFMT(TDM) | SH_FSI_SET_CH_I(x)) -#define SH_FSI_IFMT_TDM_DELAY_CH(x) \ - (SH_FSI_IFMT(TDM_DELAY) | SH_FSI_SET_CH_I(x)) - -#define SH_FSI_OFMT_TDM_CH(x) \ - (SH_FSI_OFMT(TDM) | SH_FSI_SET_CH_O(x)) -#define SH_FSI_OFMT_TDM_DELAY_CH(x) \ - (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x)) - -struct sh_fsi_platform_info { - unsigned long porta_flags; - unsigned long portb_flags; -}; - -extern struct snd_soc_dai fsi_soc_dai[2]; -extern struct snd_soc_platform fsi_soc_platform; - -#endif /* __SOUND_FSI_H */ diff --git a/trunk/include/sound/soc-dai.h b/trunk/include/sound/soc-dai.h index 97ca9af414dc..352d7eee9b6d 100644 --- a/trunk/include/sound/soc-dai.h +++ b/trunk/include/sound/soc-dai.h @@ -27,8 +27,8 @@ struct snd_pcm_substream; #define SND_SOC_DAIFMT_I2S 0 /* I2S mode */ #define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */ #define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */ -#define SND_SOC_DAIFMT_DSP_A 3 /* L data MSB after FRM LRC */ -#define SND_SOC_DAIFMT_DSP_B 4 /* L data MSB during FRM LRC */ +#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM LRC */ +#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM LRC */ #define SND_SOC_DAIFMT_AC97 5 /* AC97 */ /* left and right justified also known as MSB and LSB respectively */ @@ -38,7 +38,7 @@ struct snd_pcm_substream; /* * DAI Clock gating. * - * DAI bit clocks can be be gated (disabled) when the DAI is not + * DAI bit clocks can be be gated (disabled) when not the DAI is not * sending or receiving PCM data in a frame. This can be used to save power. */ #define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */ @@ -51,21 +51,21 @@ struct snd_pcm_substream; * format. */ #define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */ -#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal BCLK + inv FRM */ -#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert BCLK + nor FRM */ -#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert BCLK + FRM */ +#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */ +#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */ +#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */ /* * DAI hardware clock masters. * * This is wrt the codec, the inverse is true for the interface - * i.e. if the codec is clk and FRM master then the interface is + * i.e. if the codec is clk and frm master then the interface is * clk and frame slave. */ -#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & FRM master */ -#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & FRM master */ +#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */ +#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */ #define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */ -#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & FRM slave */ +#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */ #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 @@ -78,13 +78,7 @@ struct snd_pcm_substream; #define SND_SOC_CLOCK_IN 0 #define SND_SOC_CLOCK_OUT 1 -#define SND_SOC_STD_AC97_FMTS (SNDRV_PCM_FMTBIT_S8 |\ - SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S16_BE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S20_3BE |\ - SNDRV_PCM_FMTBIT_S24_3LE |\ - SNDRV_PCM_FMTBIT_S24_3BE |\ +#define SND_SOC_STD_AC97_FMTS (SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S32_LE |\ SNDRV_PCM_FMTBIT_S32_BE) @@ -112,7 +106,7 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); + unsigned int mask, int slots); int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate); @@ -122,12 +116,12 @@ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); /* * Digital Audio Interface. * - * Describes the Digital Audio Interface in terms of its ALSA, DAI and AC97 - * operations and capabilities. Codec and platform drivers will register this + * Describes the Digital Audio Interface in terms of it's ALSA, DAI and AC97 + * operations an capabilities. Codec and platfom drivers will register a this * structure for every DAI they have. * * This structure covers the clocking, formating and ALSA operations for each - * interface. + * interface a */ struct snd_soc_dai_ops { /* @@ -146,8 +140,7 @@ struct snd_soc_dai_ops { */ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); int (*set_tdm_slot)(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, - int slots, int slot_width); + unsigned int mask, int slots); int (*set_tristate)(struct snd_soc_dai *dai, int tristate); /* @@ -186,7 +179,6 @@ struct snd_soc_dai { int ac97_control; struct device *dev; - void *ac97_pdata; /* platform_data for the ac97 codec */ /* DAI callbacks */ int (*probe)(struct platform_device *pdev, diff --git a/trunk/include/sound/soc-dapm.h b/trunk/include/sound/soc-dapm.h index c1410e3191e3..ec8a45f9a069 100644 --- a/trunk/include/sound/soc-dapm.h +++ b/trunk/include/sound/soc-dapm.h @@ -137,12 +137,6 @@ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD} /* stream domain */ -#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \ -{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ - .reg = wreg, .shift = wshift, .invert = winvert } -#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \ -{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ - .reg = wreg, .shift = wshift, .invert = winvert } #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ { .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \ .shift = wshift, .invert = winvert} @@ -285,11 +279,9 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, /* dapm events */ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream, int event); -void snd_soc_dapm_shutdown(struct snd_soc_device *socdev); /* dapm sys fs - used by the core */ int snd_soc_dapm_sys_add(struct device *dev); -void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec); /* dapm audio pin control and status */ int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin); @@ -319,8 +311,6 @@ enum snd_soc_dapm_type { snd_soc_dapm_pre, /* machine specific pre widget - exec first */ snd_soc_dapm_post, /* machine specific post widget - exec last */ snd_soc_dapm_supply, /* power/clock supply */ - snd_soc_dapm_aif_in, /* audio interface input */ - snd_soc_dapm_aif_out, /* audio interface output */ }; /* diff --git a/trunk/include/sound/soc.h b/trunk/include/sound/soc.h index 475cb7ed6bec..cf6111d72b17 100644 --- a/trunk/include/sound/soc.h +++ b/trunk/include/sound/soc.h @@ -135,28 +135,6 @@ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } -#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ - xhandler_get, xhandler_put, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, \ - .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .shift = shift_left, .rshift = shift_right, \ - .max = xmax, .invert = xinvert} } -#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ - xhandler_get, xhandler_put, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ - SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_2r, \ - .get = xhandler_get, .put = xhandler_put, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ - .max = xmax, .invert = xinvert} } #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_bool_ext, \ @@ -205,28 +183,14 @@ struct snd_soc_jack_gpio; #endif typedef int (*hw_write_t)(void *,const char* ,int); +typedef int (*hw_read_t)(void *,char* ,int); extern struct snd_ac97_bus_ops soc_ac97_ops; -enum snd_soc_control_type { - SND_SOC_CUSTOM, - SND_SOC_I2C, - SND_SOC_SPI, -}; - int snd_soc_register_platform(struct snd_soc_platform *platform); void snd_soc_unregister_platform(struct snd_soc_platform *platform); int snd_soc_register_codec(struct snd_soc_codec *codec); void snd_soc_unregister_codec(struct snd_soc_codec *codec); -int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg); -int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control); - -#ifdef CONFIG_PM -int snd_soc_suspend_device(struct device *dev); -int snd_soc_resume_device(struct device *dev); -#endif /* pcm <-> DAI connect */ void snd_soc_free_pcms(struct snd_soc_device *socdev); @@ -252,9 +216,9 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, /* codec register bit access */ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, - unsigned int mask, unsigned int value); + unsigned short mask, unsigned short value); int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, - unsigned int mask, unsigned int value); + unsigned short mask, unsigned short value); int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, struct snd_ac97_bus_ops *ops, int num); @@ -392,10 +356,8 @@ struct snd_soc_codec { int (*write)(struct snd_soc_codec *, unsigned int, unsigned int); int (*display_register)(struct snd_soc_codec *, char *, size_t, unsigned int); - int (*volatile_register)(unsigned int); - int (*readable_register)(unsigned int); hw_write_t hw_write; - unsigned int (*hw_read)(struct snd_soc_codec *, unsigned int); + hw_read_t hw_read; void *reg_cache; short reg_cache_size; short reg_cache_step; @@ -407,6 +369,8 @@ struct snd_soc_codec { enum snd_soc_bias_level bias_level; enum snd_soc_bias_level suspend_bias_level; struct delayed_work delayed_work; + struct list_head up_list; + struct list_head down_list; /* codec DAI's */ struct snd_soc_dai *dai; @@ -415,7 +379,6 @@ struct snd_soc_codec { #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_reg; struct dentry *debugfs_pop_time; - struct dentry *debugfs_dapm; #endif }; diff --git a/trunk/include/sound/uda1380.h b/trunk/include/sound/uda1380.h deleted file mode 100644 index 381319c7000c..000000000000 --- a/trunk/include/sound/uda1380.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * UDA1380 ALSA SoC Codec driver - * - * Copyright 2009 Philipp Zabel - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __UDA1380_H -#define __UDA1380_H - -struct uda1380_platform_data { - int gpio_power; - int gpio_reset; - int dac_clk; -#define UDA1380_DAC_CLK_SYSCLK 0 -#define UDA1380_DAC_CLK_WSPLL 1 -}; - -#endif /* __UDA1380_H */ diff --git a/trunk/include/sound/wm8993.h b/trunk/include/sound/wm8993.h deleted file mode 100644 index 9c661f2f8cda..000000000000 --- a/trunk/include/sound/wm8993.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * linux/sound/wm8993.h -- Platform data for WM8993 - * - * Copyright 2009 Wolfson Microelectronics. PLC. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __LINUX_SND_WM8993_H -#define __LINUX_SND_WM8993_H - -/* Note that EQ1 only contains the enable/disable bit so will be - ignored but is included for simplicity. - */ -struct wm8993_retune_mobile_setting { - const char *name; - unsigned int rate; - u16 config[24]; -}; - -struct wm8993_platform_data { - struct wm8993_retune_mobile_setting *retune_configs; - int num_retune_configs; - - /* LINEOUT can be differential or single ended */ - unsigned int lineout1_diff:1; - unsigned int lineout2_diff:1; - - /* Common mode feedback */ - unsigned int lineout1fb:1; - unsigned int lineout2fb:1; - - /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */ - unsigned int micbias1_lvl:1; - unsigned int micbias2_lvl:1; - - /* Jack detect threashold levels, see datasheet for values */ - unsigned int jd_scthr:2; - unsigned int jd_thr:2; -}; - -#endif diff --git a/trunk/kernel/module.c b/trunk/kernel/module.c index 2d537186191f..eccb561dd8a3 100644 --- a/trunk/kernel/module.c +++ b/trunk/kernel/module.c @@ -1274,10 +1274,6 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect, struct module_notes_attrs *notes_attrs; struct bin_attribute *nattr; - /* failed to create section attributes, so can't create notes */ - if (!mod->sect_attrs) - return; - /* Count notes sections and allocate structures. */ notes = 0; for (i = 0; i < nsect; i++) @@ -2359,7 +2355,8 @@ static noinline struct module *load_module(void __user *umod, if (err < 0) goto unlink; add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); - add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); + if (mod->sect_attrs) + add_notes_attrs(mod, hdr->e_shnum, secstrings, sechdrs); /* Get rid of temporary copy */ vfree(hdr); diff --git a/trunk/kernel/perf_counter.c b/trunk/kernel/perf_counter.c index d7cbc579fc80..f274e1959885 100644 --- a/trunk/kernel/perf_counter.c +++ b/trunk/kernel/perf_counter.c @@ -50,7 +50,7 @@ static atomic_t nr_task_counters __read_mostly; * 1 - disallow cpu counters to unpriv * 2 - disallow kernel profiling to unpriv */ -int sysctl_perf_counter_paranoid __read_mostly = 1; +int sysctl_perf_counter_paranoid __read_mostly; static inline bool perf_paranoid_cpu(void) { @@ -4066,7 +4066,6 @@ perf_counter_alloc(struct perf_counter_attr *attr, hwc->sample_period = attr->sample_period; if (attr->freq && attr->sample_freq) hwc->sample_period = 1; - hwc->last_period = hwc->sample_period; atomic64_set(&hwc->period_left, hwc->sample_period); diff --git a/trunk/mm/nommu.c b/trunk/mm/nommu.c index 66e81e7e9fe9..4bde489ec431 100644 --- a/trunk/mm/nommu.c +++ b/trunk/mm/nommu.c @@ -1352,7 +1352,6 @@ unsigned long do_mmap_pgoff(struct file *file, } vma->vm_region = region; - add_nommu_region(region); /* set up the mapping */ if (file && vma->vm_flags & VM_SHARED) @@ -1362,6 +1361,8 @@ unsigned long do_mmap_pgoff(struct file *file, if (ret < 0) goto error_put_region; + add_nommu_region(region); + /* okay... we have a mapping; now we have to register it */ result = vma->vm_start; diff --git a/trunk/mm/page_alloc.c b/trunk/mm/page_alloc.c index a0de15f46987..5cc986eb9f6f 100644 --- a/trunk/mm/page_alloc.c +++ b/trunk/mm/page_alloc.c @@ -817,15 +817,13 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype) * agressive about taking ownership of free pages */ if (unlikely(current_order >= (pageblock_order >> 1)) || - start_migratetype == MIGRATE_RECLAIMABLE || - page_group_by_mobility_disabled) { + start_migratetype == MIGRATE_RECLAIMABLE) { unsigned long pages; pages = move_freepages_block(zone, page, start_migratetype); /* Claim the whole block if over half of it is free */ - if (pages >= (1 << (pageblock_order-1)) || - page_group_by_mobility_disabled) + if (pages >= (1 << (pageblock_order-1))) set_pageblock_migratetype(page, start_migratetype); diff --git a/trunk/mm/percpu.c b/trunk/mm/percpu.c index 3311c8919f37..5fe37842e0ea 100644 --- a/trunk/mm/percpu.c +++ b/trunk/mm/percpu.c @@ -197,12 +197,7 @@ static unsigned long pcpu_chunk_addr(struct pcpu_chunk *chunk, static bool pcpu_chunk_page_occupied(struct pcpu_chunk *chunk, int page_idx) { - /* - * Any possible cpu id can be used here, so there's no need to - * worry about preemption or cpu hotplug. - */ - return *pcpu_chunk_pagep(chunk, raw_smp_processor_id(), - page_idx) != NULL; + return *pcpu_chunk_pagep(chunk, 0, page_idx) != NULL; } /* set the pointer to a chunk in a page struct */ @@ -302,14 +297,6 @@ static struct pcpu_chunk *pcpu_chunk_addr_search(void *addr) return pcpu_first_chunk; } - /* - * The address is relative to unit0 which might be unused and - * thus unmapped. Offset the address to the unit space of the - * current processor before looking it up in the vmalloc - * space. Note that any possible cpu id can be used here, so - * there's no need to worry about preemption or cpu hotplug. - */ - addr += raw_smp_processor_id() * pcpu_unit_size; return pcpu_get_page_chunk(vmalloc_to_page(addr)); } diff --git a/trunk/mm/slub.c b/trunk/mm/slub.c index b6276753626e..b9f1491a58a1 100644 --- a/trunk/mm/slub.c +++ b/trunk/mm/slub.c @@ -2594,6 +2594,8 @@ static inline int kmem_cache_close(struct kmem_cache *s) */ void kmem_cache_destroy(struct kmem_cache *s) { + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); down_write(&slub_lock); s->refcount--; if (!s->refcount) { @@ -2604,8 +2606,6 @@ void kmem_cache_destroy(struct kmem_cache *s) "still has objects.\n", s->name, __func__); dump_stack(); } - if (s->flags & SLAB_DESTROY_BY_RCU) - rcu_barrier(); sysfs_slab_remove(s); } else up_write(&slub_lock); diff --git a/trunk/net/core/sock.c b/trunk/net/core/sock.c index 76334228ed1c..bbb25be7ddfe 100644 --- a/trunk/net/core/sock.c +++ b/trunk/net/core/sock.c @@ -1025,7 +1025,6 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority, sk->sk_prot = sk->sk_prot_creator = prot; sock_lock_init(sk); sock_net_set(sk, get_net(net)); - atomic_set(&sk->sk_wmem_alloc, 1); } return sk; @@ -1873,6 +1872,7 @@ void sock_init_data(struct socket *sock, struct sock *sk) */ smp_wmb(); atomic_set(&sk->sk_refcnt, 1); + atomic_set(&sk->sk_wmem_alloc, 1); atomic_set(&sk->sk_drops, 0); } EXPORT_SYMBOL(sock_init_data); diff --git a/trunk/net/sched/sch_api.c b/trunk/net/sched/sch_api.c index fdb694e9f759..92e6f3a52c13 100644 --- a/trunk/net/sched/sch_api.c +++ b/trunk/net/sched/sch_api.c @@ -458,7 +458,7 @@ EXPORT_SYMBOL(qdisc_warn_nonwc); static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) { struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog, - timer); + timer.timer); wd->qdisc->flags &= ~TCQ_F_THROTTLED; __netif_schedule(qdisc_root(wd->qdisc)); @@ -468,8 +468,8 @@ static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer) void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc) { - hrtimer_init(&wd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - wd->timer.function = qdisc_watchdog; + tasklet_hrtimer_init(&wd->timer, qdisc_watchdog, + CLOCK_MONOTONIC, HRTIMER_MODE_ABS); wd->qdisc = qdisc; } EXPORT_SYMBOL(qdisc_watchdog_init); @@ -485,13 +485,13 @@ void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires) wd->qdisc->flags |= TCQ_F_THROTTLED; time = ktime_set(0, 0); time = ktime_add_ns(time, PSCHED_TICKS2NS(expires)); - hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); + tasklet_hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS); } EXPORT_SYMBOL(qdisc_watchdog_schedule); void qdisc_watchdog_cancel(struct qdisc_watchdog *wd) { - hrtimer_cancel(&wd->timer); + tasklet_hrtimer_cancel(&wd->timer); wd->qdisc->flags &= ~TCQ_F_THROTTLED; } EXPORT_SYMBOL(qdisc_watchdog_cancel); @@ -1456,8 +1456,6 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags); tcm = NLMSG_DATA(nlh); tcm->tcm_family = AF_UNSPEC; - tcm->tcm__pad1 = 0; - tcm->tcm__pad2 = 0; tcm->tcm_ifindex = qdisc_dev(q)->ifindex; tcm->tcm_parent = q->handle; tcm->tcm_handle = q->handle; diff --git a/trunk/net/sched/sch_cbq.c b/trunk/net/sched/sch_cbq.c index d5798e17a832..149b0405c5ec 100644 --- a/trunk/net/sched/sch_cbq.c +++ b/trunk/net/sched/sch_cbq.c @@ -163,7 +163,7 @@ struct cbq_sched_data psched_time_t now_rt; /* Cached real time */ unsigned pmask; - struct hrtimer delay_timer; + struct tasklet_hrtimer delay_timer; struct qdisc_watchdog watchdog; /* Watchdog timer, started when CBQ has backlog, but cannot @@ -503,6 +503,8 @@ static void cbq_ovl_delay(struct cbq_class *cl) cl->undertime = q->now + delay; if (delay > 0) { + struct hrtimer *ht; + sched += delay + cl->penalty; cl->penalized = sched; cl->cpriority = TC_CBQ_MAXPRIO; @@ -510,12 +512,12 @@ static void cbq_ovl_delay(struct cbq_class *cl) expires = ktime_set(0, 0); expires = ktime_add_ns(expires, PSCHED_TICKS2NS(sched)); - if (hrtimer_try_to_cancel(&q->delay_timer) && - ktime_to_ns(ktime_sub( - hrtimer_get_expires(&q->delay_timer), - expires)) > 0) - hrtimer_set_expires(&q->delay_timer, expires); - hrtimer_restart(&q->delay_timer); + ht = &q->delay_timer.timer; + if (hrtimer_try_to_cancel(ht) && + ktime_to_ns(ktime_sub(hrtimer_get_expires(ht), + expires)) > 0) + hrtimer_set_expires(ht, expires); + hrtimer_restart(ht); cl->delayed = 1; cl->xstats.overactions++; return; @@ -591,7 +593,7 @@ static psched_tdiff_t cbq_undelay_prio(struct cbq_sched_data *q, int prio, static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) { struct cbq_sched_data *q = container_of(timer, struct cbq_sched_data, - delay_timer); + delay_timer.timer); struct Qdisc *sch = q->watchdog.qdisc; psched_time_t now; psched_tdiff_t delay = 0; @@ -621,7 +623,7 @@ static enum hrtimer_restart cbq_undelay(struct hrtimer *timer) time = ktime_set(0, 0); time = ktime_add_ns(time, PSCHED_TICKS2NS(now + delay)); - hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); + tasklet_hrtimer_start(&q->delay_timer, time, HRTIMER_MODE_ABS); } sch->flags &= ~TCQ_F_THROTTLED; @@ -1214,7 +1216,7 @@ cbq_reset(struct Qdisc* sch) q->tx_class = NULL; q->tx_borrowed = NULL; qdisc_watchdog_cancel(&q->watchdog); - hrtimer_cancel(&q->delay_timer); + tasklet_hrtimer_cancel(&q->delay_timer); q->toplevel = TC_CBQ_MAXLEVEL; q->now = psched_get_time(); q->now_rt = q->now; @@ -1397,7 +1399,8 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt) q->link.minidle = -0x7FFFFFFF; qdisc_watchdog_init(&q->watchdog, sch); - hrtimer_init(&q->delay_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + tasklet_hrtimer_init(&q->delay_timer, cbq_undelay, + CLOCK_MONOTONIC, HRTIMER_MODE_ABS); q->delay_timer.function = cbq_undelay; q->toplevel = TC_CBQ_MAXLEVEL; q->now = psched_get_time(); diff --git a/trunk/net/sunrpc/clnt.c b/trunk/net/sunrpc/clnt.c index df1039f077c2..ebfcf9b89909 100644 --- a/trunk/net/sunrpc/clnt.c +++ b/trunk/net/sunrpc/clnt.c @@ -937,7 +937,6 @@ static inline void rpc_task_force_reencode(struct rpc_task *task) { task->tk_rqstp->rq_snd_buf.len = 0; - task->tk_rqstp->rq_bytes_sent = 0; } static inline void diff --git a/trunk/security/integrity/ima/ima_main.c b/trunk/security/integrity/ima/ima_main.c index b85e61bcf246..4732f5e5d127 100644 --- a/trunk/security/integrity/ima/ima_main.c +++ b/trunk/security/integrity/ima/ima_main.c @@ -249,11 +249,7 @@ void ima_counts_put(struct path *path, int mask) struct inode *inode = path->dentry->d_inode; struct ima_iint_cache *iint; - /* The inode may already have been freed, freeing the iint - * with it. Verify the inode is not NULL before dereferencing - * it. - */ - if (!ima_initialized || !inode || !S_ISREG(inode->i_mode)) + if (!ima_initialized || !S_ISREG(inode->i_mode)) return; iint = ima_iint_find_insert_get(inode); if (!iint) diff --git a/trunk/sound/arm/pxa2xx-ac97.c b/trunk/sound/arm/pxa2xx-ac97.c index 4e34d19ddbc0..c570ebd9d177 100644 --- a/trunk/sound/arm/pxa2xx-ac97.c +++ b/trunk/sound/arm/pxa2xx-ac97.c @@ -170,13 +170,6 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) struct snd_ac97_bus *ac97_bus; struct snd_ac97_template ac97_template; int ret; - pxa2xx_audio_ops_t *pdata = dev->dev.platform_data; - - if (dev->id >= 0) { - dev_err(&dev->dev, "PXA2xx has only one AC97 port.\n"); - ret = -ENXIO; - goto err_dev; - } ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, THIS_MODULE, 0, &card); @@ -207,8 +200,6 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) snprintf(card->longname, sizeof(card->longname), "%s (%s)", dev->dev.driver->name, card->mixername); - if (pdata && pdata->codec_pdata[0]) - snd_ac97_dev_add_pdata(ac97_bus->codec[0], pdata->codec_pdata[0]); snd_card_set_dev(card, &dev->dev); ret = snd_card_register(card); if (ret == 0) { @@ -221,7 +212,6 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev) err: if (card) snd_card_free(card); -err_dev: return ret; } diff --git a/trunk/sound/arm/pxa2xx-pcm-lib.c b/trunk/sound/arm/pxa2xx-pcm-lib.c index 743ac6a29065..6205f37d547c 100644 --- a/trunk/sound/arm/pxa2xx-pcm-lib.c +++ b/trunk/sound/arm/pxa2xx-pcm-lib.c @@ -136,9 +136,6 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) { struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; - if (!prtd || !prtd->params) - return 0; - DCSR(prtd->dma_ch) &= ~DCSR_RUN; DCSR(prtd->dma_ch) = 0; DCMD(prtd->dma_ch) = 0; diff --git a/trunk/sound/core/Kconfig b/trunk/sound/core/Kconfig index c15682a2f9db..6061fb5f4e1c 100644 --- a/trunk/sound/core/Kconfig +++ b/trunk/sound/core/Kconfig @@ -206,8 +206,4 @@ config SND_PCM_XRUN_DEBUG config SND_VMASTER bool -config SND_DMA_SGBUF - def_bool y - depends on X86 - source "sound/core/seq/Kconfig" diff --git a/trunk/sound/core/Makefile b/trunk/sound/core/Makefile index 350a08d277f4..4229052e7b91 100644 --- a/trunk/sound/core/Makefile +++ b/trunk/sound/core/Makefile @@ -13,7 +13,7 @@ snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \ pcm_memory.o snd-page-alloc-y := memalloc.o -snd-page-alloc-$(CONFIG_SND_DMA_SGBUF) += sgbuf.o +snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o snd-rawmidi-objs := rawmidi.o snd-timer-objs := timer.o diff --git a/trunk/sound/core/control.c b/trunk/sound/core/control.c index a8b7fabe645e..17b8d47a5cd0 100644 --- a/trunk/sound/core/control.c +++ b/trunk/sound/core/control.c @@ -414,7 +414,7 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) EXPORT_SYMBOL(snd_ctl_remove_id); /** - * snd_ctl_remove_user_ctl - remove and release the unlocked user control + * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it * @file: active control handle * @id: the control id to remove * @@ -423,8 +423,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id); * * Returns 0 if successful, or a negative error code on failure. */ -static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, - struct snd_ctl_elem_id *id) +static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, + struct snd_ctl_elem_id *id) { struct snd_card *card = file->card; struct snd_kcontrol *kctl; @@ -433,23 +433,15 @@ static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, down_write(&card->controls_rwsem); kctl = snd_ctl_find_id(card, id); if (kctl == NULL) { - ret = -ENOENT; - goto error; - } - if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) { - ret = -EINVAL; - goto error; + up_write(&card->controls_rwsem); + return -ENOENT; } for (idx = 0; idx < kctl->count; idx++) if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { - ret = -EBUSY; - goto error; + up_write(&card->controls_rwsem); + return -EBUSY; } ret = snd_ctl_remove(card, kctl); - if (ret < 0) - goto error; - card->user_ctl_count--; -error: up_write(&card->controls_rwsem); return ret; } @@ -959,7 +951,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, if (card->user_ctl_count >= MAX_USER_CONTROLS) return -ENOMEM; - if (info->count < 1) + if (info->count > 1024) return -EINVAL; access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| @@ -1060,10 +1052,18 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file, struct snd_ctl_elem_id __user *_id) { struct snd_ctl_elem_id id; + int err; if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; - return snd_ctl_remove_user_ctl(file, &id); + err = snd_ctl_remove_unlocked_id(file, &id); + if (! err) { + struct snd_card *card = file->card; + down_write(&card->controls_rwsem); + card->user_ctl_count--; + up_write(&card->controls_rwsem); + } + return err; } static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) diff --git a/trunk/sound/core/info.c b/trunk/sound/core/info.c index 3d1f5137420a..35df614f6c55 100644 --- a/trunk/sound/core/info.c +++ b/trunk/sound/core/info.c @@ -88,10 +88,12 @@ static int resize_info_buffer(struct snd_info_buffer *buffer, char *nbuf; nsize = PAGE_ALIGN(nsize); - nbuf = krealloc(buffer->buffer, nsize, GFP_KERNEL); + nbuf = kmalloc(nsize, GFP_KERNEL); if (! nbuf) return -ENOMEM; + memcpy(nbuf, buffer->buffer, buffer->len); + kfree(buffer->buffer); buffer->buffer = nbuf; buffer->len = nsize; return 0; diff --git a/trunk/sound/core/memalloc.c b/trunk/sound/core/memalloc.c index 9e92441f9b78..1b3534d67686 100644 --- a/trunk/sound/core/memalloc.c +++ b/trunk/sound/core/memalloc.c @@ -199,8 +199,6 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, case SNDRV_DMA_TYPE_DEV: dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); break; -#endif -#ifdef CONFIG_SND_DMA_SGBUF case SNDRV_DMA_TYPE_DEV_SG: snd_malloc_sgbuf_pages(device, size, dmab, NULL); break; @@ -271,8 +269,6 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) case SNDRV_DMA_TYPE_DEV: snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); break; -#endif -#ifdef CONFIG_SND_DMA_SGBUF case SNDRV_DMA_TYPE_DEV_SG: snd_free_sgbuf_pages(dmab); break; diff --git a/trunk/sound/core/pcm_memory.c b/trunk/sound/core/pcm_memory.c index caa7796bc2f5..a6d42808828c 100644 --- a/trunk/sound/core/pcm_memory.c +++ b/trunk/sound/core/pcm_memory.c @@ -304,7 +304,6 @@ int snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, EXPORT_SYMBOL(snd_pcm_lib_preallocate_pages_for_all); -#ifdef CONFIG_SND_DMA_SGBUF /** * snd_pcm_sgbuf_ops_page - get the page struct at the given offset * @substream: the pcm substream instance @@ -350,7 +349,6 @@ unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, return size; } EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size); -#endif /* CONFIG_SND_DMA_SGBUF */ /** * snd_pcm_lib_malloc_pages - allocate the DMA buffer diff --git a/trunk/sound/drivers/dummy.c b/trunk/sound/drivers/dummy.c index 54239d2e0997..f387d53e5039 100644 --- a/trunk/sound/drivers/dummy.c +++ b/trunk/sound/drivers/dummy.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include #include @@ -148,6 +150,9 @@ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0}; static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; +#ifdef CONFIG_HIGH_RES_TIMERS +static int hrtimer = 1; +#endif module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for dummy soundcard."); @@ -161,6 +166,10 @@ module_param_array(pcm_substreams, int, NULL, 0444); MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver."); //module_param_array(midi_devs, int, NULL, 0444); //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver."); +#ifdef CONFIG_HIGH_RES_TIMERS +module_param(hrtimer, bool, 0644); +MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source."); +#endif static struct platform_device *devices[SNDRV_CARDS]; @@ -171,16 +180,29 @@ static struct platform_device *devices[SNDRV_CARDS]; #define MIXER_ADDR_CD 4 #define MIXER_ADDR_LAST 4 +struct dummy_timer_ops { + int (*create)(struct snd_pcm_substream *); + void (*free)(struct snd_pcm_substream *); + int (*prepare)(struct snd_pcm_substream *); + int (*start)(struct snd_pcm_substream *); + int (*stop)(struct snd_pcm_substream *); + snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); +}; + struct snd_dummy { struct snd_card *card; struct snd_pcm *pcm; spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; + const struct dummy_timer_ops *timer_ops; }; -struct snd_dummy_pcm { - struct snd_dummy *dummy; +/* + * system timer interface + */ + +struct dummy_systimer_pcm { spinlock_t lock; struct timer_list timer; unsigned int pcm_buffer_size; @@ -192,46 +214,29 @@ struct snd_dummy_pcm { struct snd_pcm_substream *substream; }; - -static inline void snd_card_dummy_pcm_timer_start(struct snd_dummy_pcm *dpcm) +static int dummy_systimer_start(struct snd_pcm_substream *substream) { + struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; + spin_lock(&dpcm->lock); dpcm->timer.expires = 1 + jiffies; add_timer(&dpcm->timer); + spin_unlock(&dpcm->lock); + return 0; } -static inline void snd_card_dummy_pcm_timer_stop(struct snd_dummy_pcm *dpcm) -{ - del_timer(&dpcm->timer); -} - -static int snd_card_dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +static int dummy_systimer_stop(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dummy_pcm *dpcm = runtime->private_data; - int err = 0; - + struct dummy_systimer_pcm *dpcm = substream->runtime->private_data; spin_lock(&dpcm->lock); - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - snd_card_dummy_pcm_timer_start(dpcm); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - snd_card_dummy_pcm_timer_stop(dpcm); - break; - default: - err = -EINVAL; - break; - } + del_timer(&dpcm->timer); spin_unlock(&dpcm->lock); return 0; } -static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream) +static int dummy_systimer_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dummy_pcm *dpcm = runtime->private_data; + struct dummy_systimer_pcm *dpcm = runtime->private_data; int bps; bps = snd_pcm_format_width(runtime->format) * runtime->rate * @@ -247,15 +252,12 @@ static int snd_card_dummy_pcm_prepare(struct snd_pcm_substream *substream) dpcm->pcm_irq_pos = 0; dpcm->pcm_buf_pos = 0; - snd_pcm_format_set_silence(runtime->format, runtime->dma_area, - bytes_to_samples(runtime, runtime->dma_bytes)); - return 0; } -static void snd_card_dummy_pcm_timer_function(unsigned long data) +static void dummy_systimer_callback(unsigned long data) { - struct snd_dummy_pcm *dpcm = (struct snd_dummy_pcm *)data; + struct dummy_systimer_pcm *dpcm = (struct dummy_systimer_pcm *)data; unsigned long flags; spin_lock_irqsave(&dpcm->lock, flags); @@ -272,36 +274,212 @@ static void snd_card_dummy_pcm_timer_function(unsigned long data) spin_unlock_irqrestore(&dpcm->lock, flags); } -static snd_pcm_uframes_t snd_card_dummy_pcm_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t +dummy_systimer_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dummy_pcm *dpcm = runtime->private_data; + struct dummy_systimer_pcm *dpcm = runtime->private_data; return bytes_to_frames(runtime, dpcm->pcm_buf_pos / dpcm->pcm_hz); } -static struct snd_pcm_hardware snd_card_dummy_playback = +static int dummy_systimer_create(struct snd_pcm_substream *substream) { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), - .formats = USE_FORMATS, - .rates = USE_RATE, - .rate_min = USE_RATE_MIN, - .rate_max = USE_RATE_MAX, - .channels_min = USE_CHANNELS_MIN, - .channels_max = USE_CHANNELS_MAX, - .buffer_bytes_max = MAX_BUFFER_SIZE, - .period_bytes_min = 64, - .period_bytes_max = MAX_PERIOD_SIZE, - .periods_min = USE_PERIODS_MIN, - .periods_max = USE_PERIODS_MAX, - .fifo_size = 0, + struct dummy_systimer_pcm *dpcm; + + dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); + if (!dpcm) + return -ENOMEM; + substream->runtime->private_data = dpcm; + init_timer(&dpcm->timer); + dpcm->timer.data = (unsigned long) dpcm; + dpcm->timer.function = dummy_systimer_callback; + spin_lock_init(&dpcm->lock); + dpcm->substream = substream; + return 0; +} + +static void dummy_systimer_free(struct snd_pcm_substream *substream) +{ + kfree(substream->runtime->private_data); +} + +static struct dummy_timer_ops dummy_systimer_ops = { + .create = dummy_systimer_create, + .free = dummy_systimer_free, + .prepare = dummy_systimer_prepare, + .start = dummy_systimer_start, + .stop = dummy_systimer_stop, + .pointer = dummy_systimer_pointer, +}; + +#ifdef CONFIG_HIGH_RES_TIMERS +/* + * hrtimer interface + */ + +struct dummy_hrtimer_pcm { + ktime_t base_time; + ktime_t period_time; + atomic_t running; + struct hrtimer timer; + struct tasklet_struct tasklet; + struct snd_pcm_substream *substream; +}; + +static void dummy_hrtimer_pcm_elapsed(unsigned long priv) +{ + struct dummy_hrtimer_pcm *dpcm = (struct dummy_hrtimer_pcm *)priv; + if (atomic_read(&dpcm->running)) + snd_pcm_period_elapsed(dpcm->substream); +} + +static enum hrtimer_restart dummy_hrtimer_callback(struct hrtimer *timer) +{ + struct dummy_hrtimer_pcm *dpcm; + + dpcm = container_of(timer, struct dummy_hrtimer_pcm, timer); + if (!atomic_read(&dpcm->running)) + return HRTIMER_NORESTART; + tasklet_schedule(&dpcm->tasklet); + hrtimer_forward_now(timer, dpcm->period_time); + return HRTIMER_RESTART; +} + +static int dummy_hrtimer_start(struct snd_pcm_substream *substream) +{ + struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; + + dpcm->base_time = hrtimer_cb_get_time(&dpcm->timer); + hrtimer_start(&dpcm->timer, dpcm->period_time, HRTIMER_MODE_REL); + atomic_set(&dpcm->running, 1); + return 0; +} + +static int dummy_hrtimer_stop(struct snd_pcm_substream *substream) +{ + struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; + + atomic_set(&dpcm->running, 0); + hrtimer_cancel(&dpcm->timer); + return 0; +} + +static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm) +{ + tasklet_kill(&dpcm->tasklet); +} + +static snd_pcm_uframes_t +dummy_hrtimer_pointer(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct dummy_hrtimer_pcm *dpcm = runtime->private_data; + u64 delta; + u32 pos; + + delta = ktime_us_delta(hrtimer_cb_get_time(&dpcm->timer), + dpcm->base_time); + delta = div_u64(delta * runtime->rate + 999999, 1000000); + div_u64_rem(delta, runtime->buffer_size, &pos); + return pos; +} + +static int dummy_hrtimer_prepare(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct dummy_hrtimer_pcm *dpcm = runtime->private_data; + unsigned int period, rate; + long sec; + unsigned long nsecs; + + dummy_hrtimer_sync(dpcm); + period = runtime->period_size; + rate = runtime->rate; + sec = period / rate; + period %= rate; + nsecs = div_u64((u64)period * 1000000000UL + rate - 1, rate); + dpcm->period_time = ktime_set(sec, nsecs); + + return 0; +} + +static int dummy_hrtimer_create(struct snd_pcm_substream *substream) +{ + struct dummy_hrtimer_pcm *dpcm; + + dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); + if (!dpcm) + return -ENOMEM; + substream->runtime->private_data = dpcm; + hrtimer_init(&dpcm->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + dpcm->timer.function = dummy_hrtimer_callback; + dpcm->substream = substream; + atomic_set(&dpcm->running, 0); + tasklet_init(&dpcm->tasklet, dummy_hrtimer_pcm_elapsed, + (unsigned long)dpcm); + return 0; +} + +static void dummy_hrtimer_free(struct snd_pcm_substream *substream) +{ + struct dummy_hrtimer_pcm *dpcm = substream->runtime->private_data; + dummy_hrtimer_sync(dpcm); + kfree(dpcm); +} + +static struct dummy_timer_ops dummy_hrtimer_ops = { + .create = dummy_hrtimer_create, + .free = dummy_hrtimer_free, + .prepare = dummy_hrtimer_prepare, + .start = dummy_hrtimer_start, + .stop = dummy_hrtimer_stop, + .pointer = dummy_hrtimer_pointer, }; -static struct snd_pcm_hardware snd_card_dummy_capture = +#endif /* CONFIG_HIGH_RES_TIMERS */ + +/* + * PCM interface + */ + +static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +{ + struct snd_dummy *dummy = snd_pcm_substream_chip(substream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + return dummy->timer_ops->start(substream); + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + return dummy->timer_ops->stop(substream); + } + return -EINVAL; +} + +static int dummy_pcm_prepare(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_dummy *dummy = snd_pcm_substream_chip(substream); + + snd_pcm_format_set_silence(runtime->format, runtime->dma_area, + bytes_to_samples(runtime, runtime->dma_bytes)); + return dummy->timer_ops->prepare(substream); +} + +static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream) { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_RESUME | SNDRV_PCM_INFO_MMAP_VALID), + struct snd_dummy *dummy = snd_pcm_substream_chip(substream); + + return dummy->timer_ops->pointer(substream); +} + +static struct snd_pcm_hardware dummy_pcm_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_MMAP_VALID), .formats = USE_FORMATS, .rates = USE_RATE, .rate_min = USE_RATE_MIN, @@ -316,117 +494,70 @@ static struct snd_pcm_hardware snd_card_dummy_capture = .fifo_size = 0, }; -static void snd_card_dummy_runtime_free(struct snd_pcm_runtime *runtime) -{ - kfree(runtime->private_data); -} - -static int snd_card_dummy_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) +static int dummy_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *hw_params) { - return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params)); + return snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); } -static int snd_card_dummy_hw_free(struct snd_pcm_substream *substream) +static int dummy_pcm_hw_free(struct snd_pcm_substream *substream) { return snd_pcm_lib_free_pages(substream); } -static struct snd_dummy_pcm *new_pcm_stream(struct snd_pcm_substream *substream) -{ - struct snd_dummy_pcm *dpcm; - - dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL); - if (! dpcm) - return dpcm; - init_timer(&dpcm->timer); - dpcm->timer.data = (unsigned long) dpcm; - dpcm->timer.function = snd_card_dummy_pcm_timer_function; - spin_lock_init(&dpcm->lock); - dpcm->substream = substream; - return dpcm; -} - -static int snd_card_dummy_playback_open(struct snd_pcm_substream *substream) +static int dummy_pcm_open(struct snd_pcm_substream *substream) { + struct snd_dummy *dummy = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dummy_pcm *dpcm; int err; - if ((dpcm = new_pcm_stream(substream)) == NULL) - return -ENOMEM; - runtime->private_data = dpcm; - /* makes the infrastructure responsible for freeing dpcm */ - runtime->private_free = snd_card_dummy_runtime_free; - runtime->hw = snd_card_dummy_playback; - if (substream->pcm->device & 1) { - runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; - runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; - } - if (substream->pcm->device & 2) - runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID); - err = add_playback_constraints(runtime); + dummy->timer_ops = &dummy_systimer_ops; +#ifdef CONFIG_HIGH_RES_TIMERS + if (hrtimer) + dummy->timer_ops = &dummy_hrtimer_ops; +#endif + + err = dummy->timer_ops->create(substream); if (err < 0) return err; - return 0; -} - -static int snd_card_dummy_capture_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_dummy_pcm *dpcm; - int err; - - if ((dpcm = new_pcm_stream(substream)) == NULL) - return -ENOMEM; - runtime->private_data = dpcm; - /* makes the infrastructure responsible for freeing dpcm */ - runtime->private_free = snd_card_dummy_runtime_free; - runtime->hw = snd_card_dummy_capture; - if (substream->pcm->device == 1) { + runtime->hw = dummy_pcm_hardware; + if (substream->pcm->device & 1) { runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED; runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED; } if (substream->pcm->device & 2) - runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID); - err = add_capture_constraints(runtime); - if (err < 0) + runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + err = add_playback_constraints(substream->runtime); + else + err = add_capture_constraints(substream->runtime); + if (err < 0) { + dummy->timer_ops->free(substream); return err; - - return 0; -} - -static int snd_card_dummy_playback_close(struct snd_pcm_substream *substream) -{ + } return 0; } -static int snd_card_dummy_capture_close(struct snd_pcm_substream *substream) +static int dummy_pcm_close(struct snd_pcm_substream *substream) { + struct snd_dummy *dummy = snd_pcm_substream_chip(substream); + dummy->timer_ops->free(substream); return 0; } -static struct snd_pcm_ops snd_card_dummy_playback_ops = { - .open = snd_card_dummy_playback_open, - .close = snd_card_dummy_playback_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_card_dummy_hw_params, - .hw_free = snd_card_dummy_hw_free, - .prepare = snd_card_dummy_pcm_prepare, - .trigger = snd_card_dummy_pcm_trigger, - .pointer = snd_card_dummy_pcm_pointer, -}; - -static struct snd_pcm_ops snd_card_dummy_capture_ops = { - .open = snd_card_dummy_capture_open, - .close = snd_card_dummy_capture_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_card_dummy_hw_params, - .hw_free = snd_card_dummy_hw_free, - .prepare = snd_card_dummy_pcm_prepare, - .trigger = snd_card_dummy_pcm_trigger, - .pointer = snd_card_dummy_pcm_pointer, +static struct snd_pcm_ops dummy_pcm_ops = { + .open = dummy_pcm_open, + .close = dummy_pcm_close, + .ioctl = snd_pcm_lib_ioctl, + .hw_params = dummy_pcm_hw_params, + .hw_free = dummy_pcm_hw_free, + .prepare = dummy_pcm_prepare, + .trigger = dummy_pcm_trigger, + .pointer = dummy_pcm_pointer, }; static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, @@ -440,8 +571,8 @@ static int __devinit snd_card_dummy_pcm(struct snd_dummy *dummy, int device, if (err < 0) return err; dummy->pcm = pcm; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &dummy_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &dummy_pcm_ops); pcm->private_data = dummy; pcm->info_flags = 0; strcpy(pcm->name, "Dummy PCM"); diff --git a/trunk/sound/isa/cmi8330.c b/trunk/sound/isa/cmi8330.c index 02f79d252718..3ee0269e5bd0 100644 --- a/trunk/sound/isa/cmi8330.c +++ b/trunk/sound/isa/cmi8330.c @@ -1,5 +1,5 @@ /* - * Driver for C-Media's CMI8330 and CMI8329 soundcards. + * Driver for C-Media's CMI8330 soundcards. * Copyright (c) by George Talusan * http://www.undergrad.math.uwaterloo.ca/~gstalusa * @@ -35,7 +35,7 @@ * * This card has two mixers and two PCM devices. I've cheesed it such * that recording and playback can be done through the same device. - * The driver "magically" routes the capturing to the AD1848 codec, + * The driver "magically" routes the capturing to the CMI8330 codec, * and playback to the SB16 codec. This allows for full-duplex mode * to some extent. * The utilities in alsa-utils are aware of both devices, so passing @@ -64,7 +64,7 @@ /* */ MODULE_AUTHOR("George Talusan "); -MODULE_DESCRIPTION("C-Media CMI8330/CMI8329"); +MODULE_DESCRIPTION("C-Media CMI8330"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}"); @@ -86,38 +86,38 @@ static long mpuport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; static int mpuirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; module_param_array(index, int, NULL, 0444); -MODULE_PARM_DESC(index, "Index value for CMI8330/CMI8329 soundcard."); +MODULE_PARM_DESC(index, "Index value for CMI8330 soundcard."); module_param_array(id, charp, NULL, 0444); -MODULE_PARM_DESC(id, "ID string for CMI8330/CMI8329 soundcard."); +MODULE_PARM_DESC(id, "ID string for CMI8330 soundcard."); module_param_array(enable, bool, NULL, 0444); -MODULE_PARM_DESC(enable, "Enable CMI8330/CMI8329 soundcard."); +MODULE_PARM_DESC(enable, "Enable CMI8330 soundcard."); #ifdef CONFIG_PNP module_param_array(isapnp, bool, NULL, 0444); MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard."); #endif module_param_array(sbport, long, NULL, 0444); -MODULE_PARM_DESC(sbport, "Port # for CMI8330/CMI8329 SB driver."); +MODULE_PARM_DESC(sbport, "Port # for CMI8330 SB driver."); module_param_array(sbirq, int, NULL, 0444); -MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330/CMI8329 SB driver."); +MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330 SB driver."); module_param_array(sbdma8, int, NULL, 0444); -MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330/CMI8329 SB driver."); +MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330 SB driver."); module_param_array(sbdma16, int, NULL, 0444); -MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330/CMI8329 SB driver."); +MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330 SB driver."); module_param_array(wssport, long, NULL, 0444); -MODULE_PARM_DESC(wssport, "Port # for CMI8330/CMI8329 WSS driver."); +MODULE_PARM_DESC(wssport, "Port # for CMI8330 WSS driver."); module_param_array(wssirq, int, NULL, 0444); -MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330/CMI8329 WSS driver."); +MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330 WSS driver."); module_param_array(wssdma, int, NULL, 0444); -MODULE_PARM_DESC(wssdma, "DMA for CMI8330/CMI8329 WSS driver."); +MODULE_PARM_DESC(wssdma, "DMA for CMI8330 WSS driver."); module_param_array(fmport, long, NULL, 0444); -MODULE_PARM_DESC(fmport, "FM port # for CMI8330/CMI8329 driver."); +MODULE_PARM_DESC(fmport, "FM port # for CMI8330 driver."); module_param_array(mpuport, long, NULL, 0444); -MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330/CMI8329 driver."); +MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330 driver."); module_param_array(mpuirq, int, NULL, 0444); -MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330/CMI8329 MPU-401 port."); +MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330 MPU-401 port."); #ifdef CONFIG_PNP static int isa_registered; static int pnp_registered; @@ -156,11 +156,6 @@ static unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] = typedef int (*snd_pcm_open_callback_t)(struct snd_pcm_substream *); -enum card_type { - CMI8330, - CMI8329 -}; - struct snd_cmi8330 { #ifdef CONFIG_PNP struct pnp_dev *cap; @@ -177,14 +172,11 @@ struct snd_cmi8330 { snd_pcm_open_callback_t open; void *private_data; /* sb or wss */ } streams[2]; - - enum card_type type; }; #ifdef CONFIG_PNP static struct pnp_card_device_id snd_cmi8330_pnpids[] = { - { .id = "CMI0001", .devs = { { "@X@0001" }, { "@@@0001" }, { "@H@0001" }, { "A@@0001" } } }, { .id = "CMI0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } } }, { .id = "" } }; @@ -312,7 +304,7 @@ static int __devinit snd_cmi8330_mixer(struct snd_card *card, struct snd_cmi8330 unsigned int idx; int err; - strcpy(card->mixername, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D"); + strcpy(card->mixername, "CMI8330/C3D"); for (idx = 0; idx < ARRAY_SIZE(snd_cmi8330_controls); idx++) { err = snd_ctl_add(card, @@ -337,9 +329,6 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, struct pnp_dev *pdev; int err; - /* CMI8329 has a device with ID A@@0001, CMI8330 does not */ - acard->type = (id->devs[3].id[0]) ? CMI8329 : CMI8330; - acard->cap = pnp_request_card_device(card, id->devs[0].id, NULL); if (acard->cap == NULL) return -EBUSY; @@ -356,45 +345,38 @@ static int __devinit snd_cmi8330_pnp(int dev, struct snd_cmi8330 *acard, err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "AD1848 PnP configure failure\n"); + snd_printk(KERN_ERR "CMI8330/C3D PnP configure failure\n"); return -EBUSY; } wssport[dev] = pnp_port_start(pdev, 0); wssdma[dev] = pnp_dma(pdev, 0); wssirq[dev] = pnp_irq(pdev, 0); - if (pnp_port_start(pdev, 1)) - fmport[dev] = pnp_port_start(pdev, 1); + fmport[dev] = pnp_port_start(pdev, 1); /* allocate SB16 resources */ pdev = acard->play; err = pnp_activate_dev(pdev); if (err < 0) { - snd_printk(KERN_ERR "SB16 PnP configure failure\n"); + snd_printk(KERN_ERR "CMI8330/C3D (SB16) PnP configure failure\n"); return -EBUSY; } sbport[dev] = pnp_port_start(pdev, 0); sbdma8[dev] = pnp_dma(pdev, 0); sbdma16[dev] = pnp_dma(pdev, 1); sbirq[dev] = pnp_irq(pdev, 0); - /* On CMI8239, the OPL3 port might be present in SB16 PnP resources */ - if (fmport[dev] == SNDRV_AUTO_PORT) { - if (pnp_port_start(pdev, 1)) - fmport[dev] = pnp_port_start(pdev, 1); - else - fmport[dev] = 0x388; /* Or hardwired */ - } /* allocate MPU-401 resources */ pdev = acard->mpu; err = pnp_activate_dev(pdev); - if (err < 0) - snd_printk(KERN_ERR "MPU-401 PnP configure failure: will be disabled\n"); - else { - mpuport[dev] = pnp_port_start(pdev, 0); - mpuirq[dev] = pnp_irq(pdev, 0); + if (err < 0) { + snd_printk(KERN_ERR + "CMI8330/C3D (MPU-401) PnP configure failure\n"); + return -EBUSY; } + mpuport[dev] = pnp_port_start(pdev, 0); + mpuirq[dev] = pnp_irq(pdev, 0); return 0; } #endif @@ -448,9 +430,9 @@ static int __devinit snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 * snd_cmi8330_capture_open }; - if ((err = snd_pcm_new(card, (chip->type == CMI8329) ? "CMI8329" : "CMI8330", 0, 1, 1, &pcm)) < 0) + if ((err = snd_pcm_new(card, "CMI8330", 0, 1, 1, &pcm)) < 0) return err; - strcpy(pcm->name, (chip->type == CMI8329) ? "CMI8329" : "CMI8330"); + strcpy(pcm->name, "CMI8330"); pcm->private_data = chip; /* SB16 */ @@ -545,11 +527,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) wssdma[dev], -1, WSS_HW_DETECT, 0, &acard->wss); if (err < 0) { - snd_printk(KERN_ERR PFX "AD1848 device busy??\n"); + snd_printk(KERN_ERR PFX "(CMI8330) device busy??\n"); return err; } if (acard->wss->hardware != WSS_HW_CMI8330) { - snd_printk(KERN_ERR PFX "AD1848 not found during probe\n"); + snd_printk(KERN_ERR PFX "(CMI8330) not found during probe\n"); return -ENODEV; } @@ -559,11 +541,11 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) sbdma8[dev], sbdma16[dev], SB_HW_AUTO, &acard->sb)) < 0) { - snd_printk(KERN_ERR PFX "SB16 device busy??\n"); + snd_printk(KERN_ERR PFX "(SB16) device busy??\n"); return err; } if (acard->sb->hardware != SB_HW_16) { - snd_printk(KERN_ERR PFX "SB16 not found during probe\n"); + snd_printk(KERN_ERR PFX "(SB16) not found during probe\n"); return err; } @@ -603,8 +585,8 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev) mpuport[dev]); } - strcpy(card->driver, (acard->type == CMI8329) ? "CMI8329" : "CMI8330/C3D"); - strcpy(card->shortname, (acard->type == CMI8329) ? "C-Media CMI8329" : "C-Media CMI8330/C3D"); + strcpy(card->driver, "CMI8330/C3D"); + strcpy(card->shortname, "C-Media CMI8330/C3D"); sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d", card->shortname, acard->wss->port, diff --git a/trunk/sound/pci/Kconfig b/trunk/sound/pci/Kconfig index fb5ee3cc3968..748f6b7d90b7 100644 --- a/trunk/sound/pci/Kconfig +++ b/trunk/sound/pci/Kconfig @@ -135,11 +135,11 @@ config SND_AW2 config SND_AZT3328 - tristate "Aztech AZF3328 / PCI168" + tristate "Aztech AZF3328 / PCI168 (EXPERIMENTAL)" + depends on EXPERIMENTAL select SND_OPL3_LIB select SND_MPU401_UART select SND_PCM - select SND_RAWMIDI help Say Y here to include support for Aztech AZF3328 (PCI168) soundcards. diff --git a/trunk/sound/pci/ali5451/ali5451.c b/trunk/sound/pci/ali5451/ali5451.c index b458d208720b..76d76c08339b 100644 --- a/trunk/sound/pci/ali5451/ali5451.c +++ b/trunk/sound/pci/ali5451/ali5451.c @@ -478,6 +478,45 @@ static int snd_ali_reset_5451(struct snd_ali *codec) return 0; } +#ifdef CODEC_RESET + +static int snd_ali_reset_codec(struct snd_ali *codec) +{ + struct pci_dev *pci_dev; + unsigned char bVal; + unsigned int dwVal; + unsigned short wCount, wReg; + + pci_dev = codec->pci_m1533; + + pci_read_config_dword(pci_dev, 0x7c, &dwVal); + pci_write_config_dword(pci_dev, 0x7c, dwVal | 0x08000000); + udelay(5000); + pci_read_config_dword(pci_dev, 0x7c, &dwVal); + pci_write_config_dword(pci_dev, 0x7c, dwVal & 0xf7ffffff); + udelay(5000); + + bVal = inb(ALI_REG(codec,ALI_SCTRL)); + bVal |= 0x02; + outb(ALI_REG(codec,ALI_SCTRL),bVal); + udelay(5000); + bVal = inb(ALI_REG(codec,ALI_SCTRL)); + bVal &= 0xfd; + outb(ALI_REG(codec,ALI_SCTRL),bVal); + udelay(15000); + + wCount = 200; + while (wCount--) { + wReg = snd_ali_codec_read(codec->ac97, AC97_POWERDOWN); + if ((wReg & 0x000f) == 0x000f) + return 0; + udelay(5000); + } + return -1; +} + +#endif + /* * ALI 5451 Controller */ @@ -522,6 +561,22 @@ static void snd_ali_disable_address_interrupt(struct snd_ali *codec) outl(gc, ALI_REG(codec, ALI_GC_CIR)); } +#if 0 /* not used */ +static void snd_ali_enable_voice_irq(struct snd_ali *codec, + unsigned int channel) +{ + unsigned int mask; + struct snd_ali_channel_control *pchregs = &(codec->chregs); + + snd_ali_printk("enable_voice_irq channel=%d\n",channel); + + mask = 1 << (channel & 0x1f); + pchregs->data.ainten = inl(ALI_REG(codec, pchregs->regs.ainten)); + pchregs->data.ainten |= mask; + outl(pchregs->data.ainten, ALI_REG(codec, pchregs->regs.ainten)); +} +#endif + static void snd_ali_disable_voice_irq(struct snd_ali *codec, unsigned int channel) { @@ -622,6 +677,16 @@ static void snd_ali_free_channel_pcm(struct snd_ali *codec, int channel) } } +#if 0 /* not used */ +static void snd_ali_start_voice(struct snd_ali *codec, unsigned int channel) +{ + unsigned int mask = 1 << (channel & 0x1f); + + snd_ali_printk("start_voice: channel=%d\n",channel); + outl(mask, ALI_REG(codec,codec->chregs.regs.start)); +} +#endif + static void snd_ali_stop_voice(struct snd_ali *codec, unsigned int channel) { unsigned int mask = 1 << (channel & 0x1f); diff --git a/trunk/sound/pci/azt3328.c b/trunk/sound/pci/azt3328.c index 8451a0169f32..f290bc56178f 100644 --- a/trunk/sound/pci/azt3328.c +++ b/trunk/sound/pci/azt3328.c @@ -1,6 +1,6 @@ /* * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168). - * Copyright (C) 2002, 2005 - 2009 by Andreas Mohr + * Copyright (C) 2002, 2005 - 2008 by Andreas Mohr * * Framework borrowed from Bart Hartgers's als4000.c. * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801), @@ -10,13 +10,6 @@ * PCI168 A/AP, sub ID 8000 * Please give me feedback in case you try my driver with one of these!! * - * Keywords: Windows XP Vista 168nt4-125.zip 168win95-125.zip PCI 168 download - * (XP/Vista do not support this card at all but every Linux distribution - * has very good support out of the box; - * just to make sure that the right people hit this and get to know that, - * despite the high level of Internet ignorance - as usual :-P - - * about very good support for this card - on Linux!) - * * GPL LICENSE * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -78,11 +71,10 @@ * - built-in General DirectX timer having a 20 bits counter * with 1us resolution (see below!) * - I2S serial output port for external DAC - * [FIXME: 3.3V or 5V level? maximum rate is 66.2kHz right?] * - supports 33MHz PCI spec 2.1, PCI power management 1.0, compliant with ACPI * - supports hardware volume control * - single chip low cost solution (128 pin QFP) - * - supports programmable Sub-vendor and Sub-system ID [24C02 SEEPROM chip] + * - supports programmable Sub-vendor and Sub-system ID * required for Microsoft's logo compliance (FIXME: where?) * At least the Trident 4D Wave DX has one bit somewhere * to enable writes to PCI subsystem VID registers, that should be it. @@ -90,7 +82,6 @@ * some custom data starting at 0x80. What kind of config settings * are located in our extended PCI space anyway?? * - PCI168 AP(W) card: power amplifier with 4 Watts/channel at 4 Ohms - * [TDA1517P chip] * * Note that this driver now is actually *better* than the Windows driver, * since it additionally supports the card's 1MHz DirectX timer - just try @@ -155,15 +146,10 @@ * to read the Digital Enhanced Game Port. Not sure whether it is fixable. * * TODO - * - use PCI_VDEVICE - * - verify driver status on x86_64 - * - test multi-card driver operation - * - (ab)use 1MHz DirectX timer as kernel clocksource * - test MPU401 MIDI playback etc. * - add more power micro-management (disable various units of the card - * as long as they're unused, to improve audio quality and save power). - * However this requires more I/O ports which I haven't figured out yet - * and which thus might not even exist... + * as long as they're unused). However this requires more I/O ports which I + * haven't figured out yet and which thus might not even exist... * The standard suspend/resume functionality could probably make use of * some improvement, too... * - figure out what all unknown port bits are responsible for @@ -199,46 +185,25 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); #define SUPPORT_GAMEPORT 1 #endif -/* === Debug settings === - Further diagnostic functionality than the settings below - does not need to be provided, since one can easily write a bash script - to dump the card's I/O ports (those listed in lspci -v -v): - function dump() - { - local descr=$1; local addr=$2; local count=$3 - - echo "${descr}: ${count} @ ${addr}:" - dd if=/dev/port skip=$[${addr}] count=${count} bs=1 2>/dev/null| hexdump -C - } - and then use something like - "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8", - "dump codec00 0xa800 32", "dump mixer 0xb800 64", "dump synth 0xbc00 8", - possibly within a "while true; do ... sleep 1; done" loop. - Tweaking ports could be done using - VALSTRING="`printf "%02x" $value`" - printf "\x""$VALSTRING"|dd of=/dev/port seek=$[${addr}] bs=1 2>/dev/null -*/ - #define DEBUG_MISC 0 #define DEBUG_CALLS 0 #define DEBUG_MIXER 0 -#define DEBUG_CODEC 0 +#define DEBUG_PLAY_REC 0 #define DEBUG_IO 0 #define DEBUG_TIMER 0 #define DEBUG_GAME 0 -#define DEBUG_PM 0 #define MIXER_TESTING 0 #if DEBUG_MISC -#define snd_azf3328_dbgmisc(format, args...) printk(KERN_DEBUG format, ##args) +#define snd_azf3328_dbgmisc(format, args...) printk(KERN_ERR format, ##args) #else #define snd_azf3328_dbgmisc(format, args...) #endif #if DEBUG_CALLS #define snd_azf3328_dbgcalls(format, args...) printk(format, ##args) -#define snd_azf3328_dbgcallenter() printk(KERN_DEBUG "--> %s\n", __func__) -#define snd_azf3328_dbgcallleave() printk(KERN_DEBUG "<-- %s\n", __func__) +#define snd_azf3328_dbgcallenter() printk(KERN_ERR "--> %s\n", __func__) +#define snd_azf3328_dbgcallleave() printk(KERN_ERR "<-- %s\n", __func__) #else #define snd_azf3328_dbgcalls(format, args...) #define snd_azf3328_dbgcallenter() @@ -251,10 +216,10 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); #define snd_azf3328_dbgmixer(format, args...) #endif -#if DEBUG_CODEC -#define snd_azf3328_dbgcodec(format, args...) printk(KERN_DEBUG format, ##args) +#if DEBUG_PLAY_REC +#define snd_azf3328_dbgplay(format, args...) printk(KERN_DEBUG format, ##args) #else -#define snd_azf3328_dbgcodec(format, args...) +#define snd_azf3328_dbgplay(format, args...) #endif #if DEBUG_MISC @@ -269,12 +234,6 @@ MODULE_SUPPORTED_DEVICE("{{Aztech,AZF3328}}"); #define snd_azf3328_dbggame(format, args...) #endif -#if DEBUG_PM -#define snd_azf3328_dbgpm(format, args...) printk(KERN_DEBUG format, ##args) -#else -#define snd_azf3328_dbgpm(format, args...) -#endif - static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard."); @@ -291,23 +250,22 @@ static int seqtimer_scaling = 128; module_param(seqtimer_scaling, int, 0444); MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128."); -struct snd_azf3328_codec_data { - unsigned long io_base; +struct snd_azf3328_audio_stream { struct snd_pcm_substream *substream; - bool running; - const char *name; + int enabled; + int running; + unsigned long portbase; }; -enum snd_azf3328_codec_type { - AZF_CODEC_PLAYBACK = 0, - AZF_CODEC_CAPTURE = 1, - AZF_CODEC_I2S_OUT = 2, +enum snd_azf3328_stream_index { + AZF_PLAYBACK = 0, + AZF_CAPTURE = 1, }; struct snd_azf3328 { /* often-used fields towards beginning, then grouped */ - unsigned long ctrl_io; /* usually 0xb000, size 128 */ + unsigned long codec_io; /* usually 0xb000, size 128 */ unsigned long game_io; /* usually 0xb400, size 8 */ unsigned long mpu_io; /* usually 0xb800, size 4 */ unsigned long opl3_io; /* usually 0xbc00, size 8 */ @@ -317,17 +275,15 @@ struct snd_azf3328 { struct snd_timer *timer; - struct snd_pcm *pcm[3]; - - /* playback, recording and I2S out codecs */ - struct snd_azf3328_codec_data codecs[3]; + struct snd_pcm *pcm; + struct snd_azf3328_audio_stream audio_stream[2]; struct snd_card *card; struct snd_rawmidi *rmidi; #ifdef SUPPORT_GAMEPORT struct gameport *gameport; - u16 axes[4]; + int axes[4]; #endif struct pci_dev *pci; @@ -337,16 +293,16 @@ struct snd_azf3328 { * If we need to add more registers here, then we might try to fold this * into some transparent combined shadow register handling with * CONFIG_PM register storage below, but that's slightly difficult. */ - u16 shadow_reg_ctrl_6AH; + u16 shadow_reg_codec_6AH; #ifdef CONFIG_PM /* register value containers for power management - * Note: not always full I/O range preserved (similar to Win driver!) */ - u32 saved_regs_ctrl[AZF_ALIGN(AZF_IO_SIZE_CTRL_PM) / 4]; - u32 saved_regs_game[AZF_ALIGN(AZF_IO_SIZE_GAME_PM) / 4]; - u32 saved_regs_mpu[AZF_ALIGN(AZF_IO_SIZE_MPU_PM) / 4]; - u32 saved_regs_opl3[AZF_ALIGN(AZF_IO_SIZE_OPL3_PM) / 4]; - u32 saved_regs_mixer[AZF_ALIGN(AZF_IO_SIZE_MIXER_PM) / 4]; + * Note: not always full I/O range preserved (just like Win driver!) */ + u16 saved_regs_codec[AZF_IO_SIZE_CODEC_PM / 2]; + u16 saved_regs_game [AZF_IO_SIZE_GAME_PM / 2]; + u16 saved_regs_mpu [AZF_IO_SIZE_MPU_PM / 2]; + u16 saved_regs_opl3 [AZF_IO_SIZE_OPL3_PM / 2]; + u16 saved_regs_mixer[AZF_IO_SIZE_MIXER_PM / 2]; #endif }; @@ -360,7 +316,7 @@ MODULE_DEVICE_TABLE(pci, snd_azf3328_ids); static int -snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set) +snd_azf3328_io_reg_setb(unsigned reg, u8 mask, int do_set) { u8 prev = inb(reg), new; @@ -375,72 +331,39 @@ snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set) } static inline void -snd_azf3328_codec_outb(const struct snd_azf3328_codec_data *codec, - unsigned reg, - u8 value -) +snd_azf3328_codec_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value) { - outb(value, codec->io_base + reg); + outb(value, chip->codec_io + reg); } static inline u8 -snd_azf3328_codec_inb(const struct snd_azf3328_codec_data *codec, unsigned reg) +snd_azf3328_codec_inb(const struct snd_azf3328 *chip, unsigned reg) { - return inb(codec->io_base + reg); + return inb(chip->codec_io + reg); } static inline void -snd_azf3328_codec_outw(const struct snd_azf3328_codec_data *codec, - unsigned reg, - u16 value -) +snd_azf3328_codec_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) { - outw(value, codec->io_base + reg); + outw(value, chip->codec_io + reg); } static inline u16 -snd_azf3328_codec_inw(const struct snd_azf3328_codec_data *codec, unsigned reg) +snd_azf3328_codec_inw(const struct snd_azf3328 *chip, unsigned reg) { - return inw(codec->io_base + reg); + return inw(chip->codec_io + reg); } static inline void -snd_azf3328_codec_outl(const struct snd_azf3328_codec_data *codec, - unsigned reg, - u32 value -) +snd_azf3328_codec_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value) { - outl(value, codec->io_base + reg); + outl(value, chip->codec_io + reg); } static inline u32 -snd_azf3328_codec_inl(const struct snd_azf3328_codec_data *codec, unsigned reg) -{ - return inl(codec->io_base + reg); -} - -static inline void -snd_azf3328_ctrl_outb(const struct snd_azf3328 *chip, unsigned reg, u8 value) -{ - outb(value, chip->ctrl_io + reg); -} - -static inline u8 -snd_azf3328_ctrl_inb(const struct snd_azf3328 *chip, unsigned reg) -{ - return inb(chip->ctrl_io + reg); -} - -static inline void -snd_azf3328_ctrl_outw(const struct snd_azf3328 *chip, unsigned reg, u16 value) -{ - outw(value, chip->ctrl_io + reg); -} - -static inline void -snd_azf3328_ctrl_outl(const struct snd_azf3328 *chip, unsigned reg, u32 value) +snd_azf3328_codec_inl(const struct snd_azf3328 *chip, unsigned reg) { - outl(value, chip->ctrl_io + reg); + return inl(chip->codec_io + reg); } static inline void @@ -481,13 +404,13 @@ snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg) #define AZF_MUTE_BIT 0x80 -static bool +static int snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip, - unsigned reg, bool do_mute + unsigned reg, int do_mute ) { unsigned long portbase = chip->mixer_io + reg + 1; - bool updated; + int updated; /* the mute bit is on the *second* (i.e. right) register of a * left/right channel setting */ @@ -646,7 +569,7 @@ snd_azf3328_get_mixer(struct snd_kcontrol *kcontrol, { struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); struct azf3328_mixer_reg reg; - u16 oreg, val; + unsigned int oreg, val; snd_azf3328_dbgcallenter(); snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); @@ -677,7 +600,7 @@ snd_azf3328_put_mixer(struct snd_kcontrol *kcontrol, { struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); struct azf3328_mixer_reg reg; - u16 oreg, nreg, val; + unsigned int oreg, nreg, val; snd_azf3328_dbgcallenter(); snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); @@ -786,7 +709,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol, { struct snd_azf3328 *chip = snd_kcontrol_chip(kcontrol); struct azf3328_mixer_reg reg; - u16 oreg, nreg, val; + unsigned int oreg, nreg, val; snd_azf3328_mixer_reg_decode(®, kcontrol->private_value); oreg = snd_azf3328_mixer_inw(chip, reg.reg); @@ -944,15 +867,14 @@ snd_azf3328_hw_free(struct snd_pcm_substream *substream) static void snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, - enum snd_azf3328_codec_type codec_type, + unsigned reg, enum azf_freq_t bitrate, unsigned int format_width, unsigned int channels ) { - unsigned long flags; - const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; u16 val = 0xff00; + unsigned long flags; snd_azf3328_dbgcallenter(); switch (bitrate) { @@ -995,7 +917,7 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, spin_lock_irqsave(&chip->reg_lock, flags); /* set bitrate/format */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val); + snd_azf3328_codec_outw(chip, reg, val); /* changing the bitrate/format settings switches off the * audio output with an annoying click in case of 8/16bit format change @@ -1004,11 +926,11 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, * (FIXME: yes, it works, but what exactly am I doing here?? :) * FIXME: does this have some side effects for full-duplex * or other dramatic side effects? */ - if (codec_type == AZF_CODEC_PLAYBACK) /* only do it for playback */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) | - DMA_RUN_SOMETHING1 | - DMA_RUN_SOMETHING2 | + if (reg == IDX_IO_PLAY_SOUNDFORMAT) /* only do it for playback */ + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | + DMA_PLAY_SOMETHING1 | + DMA_PLAY_SOMETHING2 | SOMETHING_ALMOST_ALWAYS_SET | DMA_EPILOGUE_SOMETHING | DMA_SOMETHING_ELSE @@ -1020,134 +942,112 @@ snd_azf3328_codec_setfmt(struct snd_azf3328 *chip, static inline void snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip, - enum snd_azf3328_codec_type codec_type + unsigned reg ) { /* choose lowest frequency for low power consumption. * While this will cause louder noise due to rather coarse frequency, * it should never matter since output should always * get disabled properly when idle anyway. */ - snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1); + snd_azf3328_codec_setfmt(chip, reg, AZF_FREQ_4000, 8, 1); } static void -snd_azf3328_ctrl_reg_6AH_update(struct snd_azf3328 *chip, +snd_azf3328_codec_reg_6AH_update(struct snd_azf3328 *chip, unsigned bitmask, - bool enable + int enable ) { - bool do_mask = !enable; - if (do_mask) - chip->shadow_reg_ctrl_6AH |= bitmask; + if (enable) + chip->shadow_reg_codec_6AH &= ~bitmask; else - chip->shadow_reg_ctrl_6AH &= ~bitmask; - snd_azf3328_dbgcodec("6AH_update mask 0x%04x do_mask %d: val 0x%04x\n", - bitmask, do_mask, chip->shadow_reg_ctrl_6AH); - snd_azf3328_ctrl_outw(chip, IDX_IO_6AH, chip->shadow_reg_ctrl_6AH); + chip->shadow_reg_codec_6AH |= bitmask; + snd_azf3328_dbgplay("6AH_update mask 0x%04x enable %d: val 0x%04x\n", + bitmask, enable, chip->shadow_reg_codec_6AH); + snd_azf3328_codec_outw(chip, IDX_IO_6AH, chip->shadow_reg_codec_6AH); } static inline void -snd_azf3328_ctrl_enable_codecs(struct snd_azf3328 *chip, bool enable) +snd_azf3328_codec_enable(struct snd_azf3328 *chip, int enable) { - snd_azf3328_dbgcodec("codec_enable %d\n", enable); + snd_azf3328_dbgplay("codec_enable %d\n", enable); /* no idea what exactly is being done here, but I strongly assume it's * PM related */ - snd_azf3328_ctrl_reg_6AH_update( + snd_azf3328_codec_reg_6AH_update( chip, IO_6A_PAUSE_PLAYBACK_BIT8, enable ); } static void -snd_azf3328_ctrl_codec_activity(struct snd_azf3328 *chip, - enum snd_azf3328_codec_type codec_type, - bool enable +snd_azf3328_codec_activity(struct snd_azf3328 *chip, + enum snd_azf3328_stream_index stream_type, + int enable ) { - struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; - bool need_change = (codec->running != enable); + int need_change = (chip->audio_stream[stream_type].running != enable); - snd_azf3328_dbgcodec( - "codec_activity: %s codec, enable %d, need_change %d\n", - codec->name, enable, need_change + snd_azf3328_dbgplay( + "codec_activity: type %d, enable %d, need_change %d\n", + stream_type, enable, need_change ); if (need_change) { - static const struct { - enum snd_azf3328_codec_type other1; - enum snd_azf3328_codec_type other2; - } peer_codecs[3] = - { { AZF_CODEC_CAPTURE, AZF_CODEC_I2S_OUT }, - { AZF_CODEC_PLAYBACK, AZF_CODEC_I2S_OUT }, - { AZF_CODEC_PLAYBACK, AZF_CODEC_CAPTURE } }; - bool call_function; - - if (enable) - /* if enable codec, call enable_codecs func - to enable codec supply... */ - call_function = 1; - else { - /* ...otherwise call enable_codecs func - (which globally shuts down operation of codecs) - only in case the other codecs are currently - not active either! */ - call_function = - ((!chip->codecs[peer_codecs[codec_type].other1] - .running) - && (!chip->codecs[peer_codecs[codec_type].other2] - .running)); - } - if (call_function) - snd_azf3328_ctrl_enable_codecs(chip, enable); + enum snd_azf3328_stream_index other = + (stream_type == AZF_PLAYBACK) ? + AZF_CAPTURE : AZF_PLAYBACK; + /* small check to prevent shutting down the other party + * in case it's active */ + if ((enable) || !(chip->audio_stream[other].running)) + snd_azf3328_codec_enable(chip, enable); /* ...and adjust clock, too * (reduce noise and power consumption) */ if (!enable) snd_azf3328_codec_setfmt_lowpower( chip, - codec_type + chip->audio_stream[stream_type].portbase + + IDX_IO_PLAY_SOUNDFORMAT ); - codec->running = enable; } + chip->audio_stream[stream_type].running = enable; } static void -snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip, - enum snd_azf3328_codec_type codec_type, - unsigned long addr, - unsigned int count, - unsigned int size +snd_azf3328_setdmaa(struct snd_azf3328 *chip, + long unsigned int addr, + unsigned int count, + unsigned int size, + enum snd_azf3328_stream_index stream_type ) { - const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; snd_azf3328_dbgcallenter(); - if (!codec->running) { - /* AZF3328 uses a two buffer pointer DMA transfer approach */ + if (!chip->audio_stream[stream_type].running) { + /* AZF3328 uses a two buffer pointer DMA playback approach */ - unsigned long flags, addr_area2; + unsigned long flags, portbase, addr_area2; /* width 32bit (prevent overflow): */ - u32 count_areas, lengths; + unsigned long count_areas, count_tmp; + portbase = chip->audio_stream[stream_type].portbase; count_areas = size/2; addr_area2 = addr+count_areas; count_areas--; /* max. index */ - snd_azf3328_dbgcodec("setdma: buffers %08lx[%u] / %08lx[%u]\n", - addr, count_areas, addr_area2, count_areas); + snd_azf3328_dbgplay("set DMA: buf1 %08lx[%lu], buf2 %08lx[%lu]\n", addr, count_areas, addr_area2, count_areas); /* build combined I/O buffer length word */ - lengths = (count_areas << 16) | (count_areas); + count_tmp = count_areas; + count_areas |= (count_tmp << 16); spin_lock_irqsave(&chip->reg_lock, flags); - snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr); - snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2, - addr_area2); - snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS, - lengths); + outl(addr, portbase + IDX_IO_PLAY_DMA_START_1); + outl(addr_area2, portbase + IDX_IO_PLAY_DMA_START_2); + outl(count_areas, portbase + IDX_IO_PLAY_DMA_LEN_1); spin_unlock_irqrestore(&chip->reg_lock, flags); } snd_azf3328_dbgcallleave(); } static int -snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) +snd_azf3328_playback_prepare(struct snd_pcm_substream *substream) { #if 0 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); @@ -1158,161 +1058,157 @@ snd_azf3328_codec_prepare(struct snd_pcm_substream *substream) snd_azf3328_dbgcallenter(); #if 0 - snd_azf3328_codec_setfmt(chip, AZF_CODEC_..., + snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); - snd_azf3328_codec_setdmaa(chip, AZF_CODEC_..., - runtime->dma_addr, count, size); + snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_PLAYBACK); #endif snd_azf3328_dbgcallleave(); return 0; } static int -snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, - struct snd_pcm_substream *substream, int cmd) +snd_azf3328_capture_prepare(struct snd_pcm_substream *substream) +{ +#if 0 + struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + unsigned int size = snd_pcm_lib_buffer_bytes(substream); + unsigned int count = snd_pcm_lib_period_bytes(substream); +#endif + + snd_azf3328_dbgcallenter(); +#if 0 + snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, + runtime->rate, + snd_pcm_format_width(runtime->format), + runtime->channels); + snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, AZF_CAPTURE); +#endif + snd_azf3328_dbgcallleave(); + return 0; +} + +static int +snd_azf3328_playback_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); - const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; struct snd_pcm_runtime *runtime = substream->runtime; int result = 0; - u16 flags1; - bool previously_muted = 0; - bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type); + unsigned int status1; + int previously_muted; - snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd); + snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd); switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_azf3328_dbgcodec("START %s\n", codec->name); - - if (is_playback_codec) { - /* mute WaveOut (avoid clicking during setup) */ - previously_muted = - snd_azf3328_mixer_set_mute( - chip, IDX_MIXER_WAVEOUT, 1 - ); - } + snd_azf3328_dbgplay("START PLAYBACK\n"); + + /* mute WaveOut (avoid clicking during setup) */ + previously_muted = + snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); - snd_azf3328_codec_setfmt(chip, codec_type, + snd_azf3328_codec_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); spin_lock(&chip->reg_lock); /* first, remember current value: */ - flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); + status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); - /* stop transfer */ - flags1 &= ~DMA_RESUME; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + /* stop playback */ + status1 &= ~DMA_RESUME; + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); /* FIXME: clear interrupts or what??? */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_IRQTYPE, 0xffff); spin_unlock(&chip->reg_lock); - snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr, + snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), - snd_pcm_lib_buffer_bytes(substream) - ); + snd_pcm_lib_buffer_bytes(substream), + AZF_PLAYBACK); spin_lock(&chip->reg_lock); #ifdef WIN9X /* FIXME: enable playback/recording??? */ - flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); - /* start transfer again */ + /* start playback again */ /* FIXME: what is this value (0x0010)??? */ - flags1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); #else /* NT4 */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, 0x0000); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - DMA_RUN_SOMETHING1); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - DMA_RUN_SOMETHING1 | - DMA_RUN_SOMETHING2); - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + DMA_PLAY_SOMETHING1); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + DMA_PLAY_SOMETHING1 | + DMA_PLAY_SOMETHING2); + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, DMA_RESUME | SOMETHING_ALMOST_ALWAYS_SET | DMA_EPILOGUE_SOMETHING | DMA_SOMETHING_ELSE); #endif spin_unlock(&chip->reg_lock); - snd_azf3328_ctrl_codec_activity(chip, codec_type, 1); - - if (is_playback_codec) { - /* now unmute WaveOut */ - if (!previously_muted) - snd_azf3328_mixer_set_mute( - chip, IDX_MIXER_WAVEOUT, 0 - ); - } + snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 1); + + /* now unmute WaveOut */ + if (!previously_muted) + snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); - snd_azf3328_dbgcodec("STARTED %s\n", codec->name); + snd_azf3328_dbgplay("STARTED PLAYBACK\n"); break; case SNDRV_PCM_TRIGGER_RESUME: - snd_azf3328_dbgcodec("RESUME %s\n", codec->name); - /* resume codec if we were active */ + snd_azf3328_dbgplay("RESUME PLAYBACK\n"); + /* resume playback if we were active */ spin_lock(&chip->reg_lock); - if (codec->running) - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - snd_azf3328_codec_inw( - codec, IDX_IO_CODEC_DMA_FLAGS - ) | DMA_RESUME - ); + if (chip->audio_stream[AZF_PLAYBACK].running) + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) | DMA_RESUME); spin_unlock(&chip->reg_lock); break; case SNDRV_PCM_TRIGGER_STOP: - snd_azf3328_dbgcodec("STOP %s\n", codec->name); - - if (is_playback_codec) { - /* mute WaveOut (avoid clicking during setup) */ - previously_muted = - snd_azf3328_mixer_set_mute( - chip, IDX_MIXER_WAVEOUT, 1 - ); - } + snd_azf3328_dbgplay("STOP PLAYBACK\n"); + + /* mute WaveOut (avoid clicking during setup) */ + previously_muted = + snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); spin_lock(&chip->reg_lock); /* first, remember current value: */ - flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS); + status1 = snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS); - /* stop transfer */ - flags1 &= ~DMA_RESUME; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + /* stop playback */ + status1 &= ~DMA_RESUME; + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); /* hmm, is this really required? we're resetting the same bit * immediately thereafter... */ - flags1 |= DMA_RUN_SOMETHING1; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + status1 |= DMA_PLAY_SOMETHING1; + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); - flags1 &= ~DMA_RUN_SOMETHING1; - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1); + status1 &= ~DMA_PLAY_SOMETHING1; + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, status1); spin_unlock(&chip->reg_lock); - snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); - - if (is_playback_codec) { - /* now unmute WaveOut */ - if (!previously_muted) - snd_azf3328_mixer_set_mute( - chip, IDX_MIXER_WAVEOUT, 0 - ); - } + snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0); - snd_azf3328_dbgcodec("STOPPED %s\n", codec->name); + /* now unmute WaveOut */ + if (!previously_muted) + snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); + + snd_azf3328_dbgplay("STOPPED PLAYBACK\n"); break; case SNDRV_PCM_TRIGGER_SUSPEND: - snd_azf3328_dbgcodec("SUSPEND %s\n", codec->name); - /* make sure codec is stopped */ - snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, - snd_azf3328_codec_inw( - codec, IDX_IO_CODEC_DMA_FLAGS - ) & ~DMA_RESUME - ); + snd_azf3328_dbgplay("SUSPEND PLAYBACK\n"); + /* make sure playback is stopped */ + snd_azf3328_codec_outw(chip, IDX_IO_PLAY_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS) & ~DMA_RESUME); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); @@ -1321,7 +1217,7 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); break; default: - snd_printk(KERN_ERR "FIXME: unknown trigger mode!\n"); + printk(KERN_ERR "FIXME: unknown trigger mode!\n"); return -EINVAL; } @@ -1329,74 +1225,172 @@ snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type, return result; } +/* this is just analogous to playback; I'm not quite sure whether recording + * should actually be triggered like that */ static int -snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd) +snd_azf3328_capture_trigger(struct snd_pcm_substream *substream, int cmd) { - return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd); -} + struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int result = 0; + unsigned int status1; -static int -snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd) -{ - return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd); -} + snd_azf3328_dbgcalls("snd_azf3328_capture_trigger cmd %d\n", cmd); -static int -snd_azf3328_codec_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd) -{ - return snd_azf3328_codec_trigger(AZF_CODEC_I2S_OUT, substream, cmd); + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + + snd_azf3328_dbgplay("START CAPTURE\n"); + + snd_azf3328_codec_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, + runtime->rate, + snd_pcm_format_width(runtime->format), + runtime->channels); + + spin_lock(&chip->reg_lock); + /* first, remember current value: */ + status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS); + + /* stop recording */ + status1 &= ~DMA_RESUME; + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); + + /* FIXME: clear interrupts or what??? */ + snd_azf3328_codec_outw(chip, IDX_IO_REC_IRQTYPE, 0xffff); + spin_unlock(&chip->reg_lock); + + snd_azf3328_setdmaa(chip, runtime->dma_addr, + snd_pcm_lib_period_bytes(substream), + snd_pcm_lib_buffer_bytes(substream), + AZF_CAPTURE); + + spin_lock(&chip->reg_lock); +#ifdef WIN9X + /* FIXME: enable playback/recording??? */ + status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); + + /* start capture again */ + /* FIXME: what is this value (0x0010)??? */ + status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); +#else + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + 0x0000); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + DMA_PLAY_SOMETHING1); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + DMA_PLAY_SOMETHING1 | + DMA_PLAY_SOMETHING2); + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + DMA_RESUME | + SOMETHING_ALMOST_ALWAYS_SET | + DMA_EPILOGUE_SOMETHING | + DMA_SOMETHING_ELSE); +#endif + spin_unlock(&chip->reg_lock); + snd_azf3328_codec_activity(chip, AZF_CAPTURE, 1); + + snd_azf3328_dbgplay("STARTED CAPTURE\n"); + break; + case SNDRV_PCM_TRIGGER_RESUME: + snd_azf3328_dbgplay("RESUME CAPTURE\n"); + /* resume recording if we were active */ + spin_lock(&chip->reg_lock); + if (chip->audio_stream[AZF_CAPTURE].running) + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) | DMA_RESUME); + spin_unlock(&chip->reg_lock); + break; + case SNDRV_PCM_TRIGGER_STOP: + snd_azf3328_dbgplay("STOP CAPTURE\n"); + + spin_lock(&chip->reg_lock); + /* first, remember current value: */ + status1 = snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS); + + /* stop recording */ + status1 &= ~DMA_RESUME; + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); + + status1 |= DMA_PLAY_SOMETHING1; + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); + + status1 &= ~DMA_PLAY_SOMETHING1; + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, status1); + spin_unlock(&chip->reg_lock); + snd_azf3328_codec_activity(chip, AZF_CAPTURE, 0); + + snd_azf3328_dbgplay("STOPPED CAPTURE\n"); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + snd_azf3328_dbgplay("SUSPEND CAPTURE\n"); + /* make sure recording is stopped */ + snd_azf3328_codec_outw(chip, IDX_IO_REC_FLAGS, + snd_azf3328_codec_inw(chip, IDX_IO_REC_FLAGS) & ~DMA_RESUME); + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + snd_printk(KERN_ERR "FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); + break; + default: + printk(KERN_ERR "FIXME: unknown trigger mode!\n"); + return -EINVAL; + } + + snd_azf3328_dbgcallleave(); + return result; } static snd_pcm_uframes_t -snd_azf3328_codec_pointer(struct snd_pcm_substream *substream, - enum snd_azf3328_codec_type codec_type -) +snd_azf3328_playback_pointer(struct snd_pcm_substream *substream) { - const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); - const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type]; + struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); unsigned long bufptr, result; snd_pcm_uframes_t frmres; #ifdef QUERY_HARDWARE - bufptr = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1); + bufptr = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_START_1); #else bufptr = substream->runtime->dma_addr; #endif - result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS); + result = snd_azf3328_codec_inl(chip, IDX_IO_PLAY_DMA_CURRPOS); /* calculate offset */ result -= bufptr; frmres = bytes_to_frames( substream->runtime, result); - snd_azf3328_dbgcodec("%s @ 0x%8lx, frames %8ld\n", - codec->name, result, frmres); + snd_azf3328_dbgplay("PLAY @ 0x%8lx, frames %8ld\n", result, frmres); return frmres; } static snd_pcm_uframes_t -snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream) +snd_azf3328_capture_pointer(struct snd_pcm_substream *substream) { - return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK); -} + struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); + unsigned long bufptr, result; + snd_pcm_uframes_t frmres; -static snd_pcm_uframes_t -snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream) -{ - return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE); -} +#ifdef QUERY_HARDWARE + bufptr = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_START_1); +#else + bufptr = substream->runtime->dma_addr; +#endif + result = snd_azf3328_codec_inl(chip, IDX_IO_REC_DMA_CURRPOS); -static snd_pcm_uframes_t -snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream) -{ - return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT); + /* calculate offset */ + result -= bufptr; + frmres = bytes_to_frames( substream->runtime, result); + snd_azf3328_dbgplay("REC @ 0x%8lx, frames %8ld\n", result, frmres); + return frmres; } /******************************************************************/ #ifdef SUPPORT_GAMEPORT static inline void -snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, - bool enable -) +snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, int enable) { snd_azf3328_io_reg_setb( chip->game_io+IDX_GAME_HWCONFIG, @@ -1406,9 +1400,7 @@ snd_azf3328_gameport_irq_enable(struct snd_azf3328 *chip, } static inline void -snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, - bool enable -) +snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, int enable) { snd_azf3328_io_reg_setb( chip->game_io+IDX_GAME_HWCONFIG, @@ -1417,27 +1409,10 @@ snd_azf3328_gameport_legacy_address_enable(struct snd_azf3328 *chip, ); } -static void -snd_azf3328_gameport_set_counter_frequency(struct snd_azf3328 *chip, - unsigned int freq_cfg -) -{ - snd_azf3328_io_reg_setb( - chip->game_io+IDX_GAME_HWCONFIG, - 0x02, - (freq_cfg & 1) != 0 - ); - snd_azf3328_io_reg_setb( - chip->game_io+IDX_GAME_HWCONFIG, - 0x04, - (freq_cfg & 2) != 0 - ); -} - static inline void -snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, bool enable) +snd_azf3328_gameport_axis_circuit_enable(struct snd_azf3328 *chip, int enable) { - snd_azf3328_ctrl_reg_6AH_update( + snd_azf3328_codec_reg_6AH_update( chip, IO_6A_SOMETHING2_GAMEPORT, enable ); } @@ -1472,8 +1447,6 @@ snd_azf3328_gameport_open(struct gameport *gameport, int mode) break; } - snd_azf3328_gameport_set_counter_frequency(chip, - GAME_HWCFG_ADC_COUNTER_FREQ_STD); snd_azf3328_gameport_axis_circuit_enable(chip, (res == 0)); return res; @@ -1485,8 +1458,6 @@ snd_azf3328_gameport_close(struct gameport *gameport) struct snd_azf3328 *chip = gameport_get_port_data(gameport); snd_azf3328_dbggame("gameport_close\n"); - snd_azf3328_gameport_set_counter_frequency(chip, - GAME_HWCFG_ADC_COUNTER_FREQ_1_200); snd_azf3328_gameport_axis_circuit_enable(chip, 0); } @@ -1520,7 +1491,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport, val = snd_azf3328_game_inb(chip, IDX_GAME_AXES_CONFIG); if (val & GAME_AXES_SAMPLING_READY) { - for (i = 0; i < ARRAY_SIZE(chip->axes); ++i) { + for (i = 0; i < 4; ++i) { /* configure the axis to read */ val = (i << 4) | 0x0f; snd_azf3328_game_outb(chip, IDX_GAME_AXES_CONFIG, val); @@ -1543,7 +1514,7 @@ snd_azf3328_gameport_cooked_read(struct gameport *gameport, snd_azf3328_game_outw(chip, IDX_GAME_AXIS_VALUE, 0xffff); spin_unlock_irqrestore(&chip->reg_lock, flags); - for (i = 0; i < ARRAY_SIZE(chip->axes); i++) { + for (i = 0; i < 4; i++) { axes[i] = chip->axes[i]; if (axes[i] == 0xffff) axes[i] = -1; @@ -1581,8 +1552,6 @@ snd_azf3328_gameport(struct snd_azf3328 *chip, int dev) /* DISABLE legacy address: we don't need it! */ snd_azf3328_gameport_legacy_address_enable(chip, 0); - snd_azf3328_gameport_set_counter_frequency(chip, - GAME_HWCFG_ADC_COUNTER_FREQ_1_200); snd_azf3328_gameport_axis_circuit_enable(chip, 0); gameport_register_port(chip->gameport); @@ -1616,77 +1585,40 @@ snd_azf3328_gameport_interrupt(struct snd_azf3328 *chip) static inline void snd_azf3328_irq_log_unknown_type(u8 which) { - snd_azf3328_dbgcodec( + snd_azf3328_dbgplay( "azt3328: unknown IRQ type (%x) occurred, please report!\n", which ); } -static inline void -snd_azf3328_codec_interrupt(struct snd_azf3328 *chip, u8 status) -{ - u8 which; - enum snd_azf3328_codec_type codec_type; - const struct snd_azf3328_codec_data *codec; - - for (codec_type = AZF_CODEC_PLAYBACK; - codec_type <= AZF_CODEC_I2S_OUT; - ++codec_type) { - - /* skip codec if there's no interrupt for it */ - if (!(status & (1 << codec_type))) - continue; - - codec = &chip->codecs[codec_type]; - - spin_lock(&chip->reg_lock); - which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE); - /* ack all IRQ types immediately */ - snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which); - spin_unlock(&chip->reg_lock); - - if ((chip->pcm[codec_type]) && (codec->substream)) { - snd_pcm_period_elapsed(codec->substream); - snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n", - codec->name, - which, - snd_azf3328_codec_inl( - codec, IDX_IO_CODEC_DMA_CURRPOS - ) - ); - } else - printk(KERN_WARNING "azt3328: irq handler problem!\n"); - if (which & IRQ_SOMETHING) - snd_azf3328_irq_log_unknown_type(which); - } -} - static irqreturn_t snd_azf3328_interrupt(int irq, void *dev_id) { struct snd_azf3328 *chip = dev_id; - u8 status; -#if DEBUG_CODEC + u8 status, which; +#if DEBUG_PLAY_REC static unsigned long irq_count; #endif - status = snd_azf3328_ctrl_inb(chip, IDX_IO_IRQSTATUS); + status = snd_azf3328_codec_inb(chip, IDX_IO_IRQSTATUS); /* fast path out, to ease interrupt sharing */ if (!(status & - (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT - |IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER) + (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_GAMEPORT|IRQ_MPU401|IRQ_TIMER) )) return IRQ_NONE; /* must be interrupt for another device */ - snd_azf3328_dbgcodec( - "irq_count %ld! IDX_IO_IRQSTATUS %04x\n", + snd_azf3328_dbgplay( + "irq_count %ld! IDX_IO_PLAY_FLAGS %04x, " + "IDX_IO_PLAY_IRQTYPE %04x, IDX_IO_IRQSTATUS %04x\n", irq_count++ /* debug-only */, + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_FLAGS), + snd_azf3328_codec_inw(chip, IDX_IO_PLAY_IRQTYPE), status ); if (status & IRQ_TIMER) { - /* snd_azf3328_dbgcodec("timer %ld\n", + /* snd_azf3328_dbgplay("timer %ld\n", snd_azf3328_codec_inl(chip, IDX_IO_TIMER_VALUE) & TIMER_VALUE_MASK ); */ @@ -1694,36 +1626,71 @@ snd_azf3328_interrupt(int irq, void *dev_id) snd_timer_interrupt(chip->timer, chip->timer->sticks); /* ACK timer */ spin_lock(&chip->reg_lock); - snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0x07); spin_unlock(&chip->reg_lock); - snd_azf3328_dbgcodec("azt3328: timer IRQ\n"); + snd_azf3328_dbgplay("azt3328: timer IRQ\n"); } + if (status & IRQ_PLAYBACK) { + spin_lock(&chip->reg_lock); + which = snd_azf3328_codec_inb(chip, IDX_IO_PLAY_IRQTYPE); + /* ack all IRQ types immediately */ + snd_azf3328_codec_outb(chip, IDX_IO_PLAY_IRQTYPE, which); + spin_unlock(&chip->reg_lock); - if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT)) - snd_azf3328_codec_interrupt(chip, status); + if (chip->pcm && chip->audio_stream[AZF_PLAYBACK].substream) { + snd_pcm_period_elapsed( + chip->audio_stream[AZF_PLAYBACK].substream + ); + snd_azf3328_dbgplay("PLAY period done (#%x), @ %x\n", + which, + snd_azf3328_codec_inl( + chip, IDX_IO_PLAY_DMA_CURRPOS + ) + ); + } else + printk(KERN_WARNING "azt3328: irq handler problem!\n"); + if (which & IRQ_PLAY_SOMETHING) + snd_azf3328_irq_log_unknown_type(which); + } + if (status & IRQ_RECORDING) { + spin_lock(&chip->reg_lock); + which = snd_azf3328_codec_inb(chip, IDX_IO_REC_IRQTYPE); + /* ack all IRQ types immediately */ + snd_azf3328_codec_outb(chip, IDX_IO_REC_IRQTYPE, which); + spin_unlock(&chip->reg_lock); + if (chip->pcm && chip->audio_stream[AZF_CAPTURE].substream) { + snd_pcm_period_elapsed( + chip->audio_stream[AZF_CAPTURE].substream + ); + snd_azf3328_dbgplay("REC period done (#%x), @ %x\n", + which, + snd_azf3328_codec_inl( + chip, IDX_IO_REC_DMA_CURRPOS + ) + ); + } else + printk(KERN_WARNING "azt3328: irq handler problem!\n"); + if (which & IRQ_REC_SOMETHING) + snd_azf3328_irq_log_unknown_type(which); + } if (status & IRQ_GAMEPORT) snd_azf3328_gameport_interrupt(chip); - /* MPU401 has less critical IRQ requirements * than timer and playback/recording, right? */ if (status & IRQ_MPU401) { snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data); /* hmm, do we have to ack the IRQ here somehow? - * If so, then I don't know how yet... */ - snd_azf3328_dbgcodec("azt3328: MPU401 IRQ\n"); + * If so, then I don't know how... */ + snd_azf3328_dbgplay("azt3328: MPU401 IRQ\n"); } return IRQ_HANDLED; } /*****************************************************************/ -/* as long as we think we have identical snd_pcm_hardware parameters - for playback, capture and i2s out, we can use the same physical struct - since the struct is simply being copied into a member. -*/ -static const struct snd_pcm_hardware snd_azf3328_hardware = +static const struct snd_pcm_hardware snd_azf3328_playback = { /* FIXME!! Correct? */ .info = SNDRV_PCM_INFO_MMAP | @@ -1751,6 +1718,31 @@ static const struct snd_pcm_hardware snd_azf3328_hardware = .fifo_size = 0, }; +static const struct snd_pcm_hardware snd_azf3328_capture = +{ + /* FIXME */ + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_S8 | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_U16_LE, + .rates = SNDRV_PCM_RATE_5512 | + SNDRV_PCM_RATE_8000_48000 | + SNDRV_PCM_RATE_KNOT, + .rate_min = AZF_FREQ_4000, + .rate_max = AZF_FREQ_66200, + .channels_min = 1, + .channels_max = 2, + .buffer_bytes_max = 65536, + .period_bytes_min = 64, + .period_bytes_max = 65536, + .periods_min = 1, + .periods_max = 1024, + .fifo_size = 0, +}; + static unsigned int snd_azf3328_fixed_rates[] = { AZF_FREQ_4000, @@ -1778,52 +1770,31 @@ static struct snd_pcm_hw_constraint_list snd_azf3328_hw_constraints_rates = { /*****************************************************************/ static int -snd_azf3328_pcm_open(struct snd_pcm_substream *substream, - enum snd_azf3328_codec_type codec_type -) +snd_azf3328_playback_open(struct snd_pcm_substream *substream) { struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); struct snd_pcm_runtime *runtime = substream->runtime; snd_azf3328_dbgcallenter(); - chip->codecs[codec_type].substream = substream; - - /* same parameters for all our codecs - at least we think so... */ - runtime->hw = snd_azf3328_hardware; - + chip->audio_stream[AZF_PLAYBACK].substream = substream; + runtime->hw = snd_azf3328_playback; snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &snd_azf3328_hw_constraints_rates); snd_azf3328_dbgcallleave(); return 0; } -static int -snd_azf3328_playback_open(struct snd_pcm_substream *substream) -{ - return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK); -} - static int snd_azf3328_capture_open(struct snd_pcm_substream *substream) -{ - return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE); -} - -static int -snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream) -{ - return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT); -} - -static int -snd_azf3328_pcm_close(struct snd_pcm_substream *substream, - enum snd_azf3328_codec_type codec_type -) { struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); + struct snd_pcm_runtime *runtime = substream->runtime; snd_azf3328_dbgcallenter(); - chip->codecs[codec_type].substream = NULL; + chip->audio_stream[AZF_CAPTURE].substream = substream; + runtime->hw = snd_azf3328_capture; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &snd_azf3328_hw_constraints_rates); snd_azf3328_dbgcallleave(); return 0; } @@ -1831,19 +1802,23 @@ snd_azf3328_pcm_close(struct snd_pcm_substream *substream, static int snd_azf3328_playback_close(struct snd_pcm_substream *substream) { - return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK); + struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); + + snd_azf3328_dbgcallenter(); + chip->audio_stream[AZF_PLAYBACK].substream = NULL; + snd_azf3328_dbgcallleave(); + return 0; } static int snd_azf3328_capture_close(struct snd_pcm_substream *substream) { - return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE); -} + struct snd_azf3328 *chip = snd_pcm_substream_chip(substream); -static int -snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream) -{ - return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT); + snd_azf3328_dbgcallenter(); + chip->audio_stream[AZF_CAPTURE].substream = NULL; + snd_azf3328_dbgcallleave(); + return 0; } /******************************************************************/ @@ -1854,9 +1829,9 @@ static struct snd_pcm_ops snd_azf3328_playback_ops = { .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_azf3328_hw_params, .hw_free = snd_azf3328_hw_free, - .prepare = snd_azf3328_codec_prepare, - .trigger = snd_azf3328_codec_playback_trigger, - .pointer = snd_azf3328_codec_playback_pointer + .prepare = snd_azf3328_playback_prepare, + .trigger = snd_azf3328_playback_trigger, + .pointer = snd_azf3328_playback_pointer }; static struct snd_pcm_ops snd_azf3328_capture_ops = { @@ -1865,67 +1840,30 @@ static struct snd_pcm_ops snd_azf3328_capture_ops = { .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_azf3328_hw_params, .hw_free = snd_azf3328_hw_free, - .prepare = snd_azf3328_codec_prepare, - .trigger = snd_azf3328_codec_capture_trigger, - .pointer = snd_azf3328_codec_capture_pointer -}; - -static struct snd_pcm_ops snd_azf3328_i2s_out_ops = { - .open = snd_azf3328_i2s_out_open, - .close = snd_azf3328_i2s_out_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = snd_azf3328_hw_params, - .hw_free = snd_azf3328_hw_free, - .prepare = snd_azf3328_codec_prepare, - .trigger = snd_azf3328_codec_i2s_out_trigger, - .pointer = snd_azf3328_codec_i2s_out_pointer + .prepare = snd_azf3328_capture_prepare, + .trigger = snd_azf3328_capture_trigger, + .pointer = snd_azf3328_capture_pointer }; static int __devinit -snd_azf3328_pcm(struct snd_azf3328 *chip) +snd_azf3328_pcm(struct snd_azf3328 *chip, int device) { -enum { AZF_PCMDEV_STD, AZF_PCMDEV_I2S_OUT, NUM_AZF_PCMDEVS }; /* pcm devices */ - struct snd_pcm *pcm; int err; snd_azf3328_dbgcallenter(); - - err = snd_pcm_new(chip->card, "AZF3328 DSP", AZF_PCMDEV_STD, - 1, 1, &pcm); - if (err < 0) + if ((err = snd_pcm_new(chip->card, "AZF3328 DSP", device, 1, 1, &pcm)) < 0) return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_azf3328_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, - &snd_azf3328_capture_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_azf3328_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_azf3328_capture_ops); pcm->private_data = chip; pcm->info_flags = 0; strcpy(pcm->name, chip->card->shortname); - /* same pcm object for playback/capture (see snd_pcm_new() above) */ - chip->pcm[AZF_CODEC_PLAYBACK] = pcm; - chip->pcm[AZF_CODEC_CAPTURE] = pcm; + chip->pcm = pcm; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - 64*1024, 64*1024); - - err = snd_pcm_new(chip->card, "AZF3328 I2S OUT", AZF_PCMDEV_I2S_OUT, - 1, 0, &pcm); - if (err < 0) - return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, - &snd_azf3328_i2s_out_ops); - - pcm->private_data = chip; - pcm->info_flags = 0; - strcpy(pcm->name, chip->card->shortname); - chip->pcm[AZF_CODEC_I2S_OUT] = pcm; - - snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, - snd_dma_pci_data(chip->pci), - 64*1024, 64*1024); + snd_dma_pci_data(chip->pci), 64*1024, 64*1024); snd_azf3328_dbgcallleave(); return 0; @@ -1964,7 +1902,7 @@ snd_azf3328_timer_start(struct snd_timer *timer) snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay); delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE; spin_lock_irqsave(&chip->reg_lock, flags); - snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay); + snd_azf3328_codec_outl(chip, IDX_IO_TIMER_VALUE, delay); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_azf3328_dbgcallleave(); return 0; @@ -1981,7 +1919,7 @@ snd_azf3328_timer_stop(struct snd_timer *timer) spin_lock_irqsave(&chip->reg_lock, flags); /* disable timer countdown and interrupt */ /* FIXME: should we write TIMER_IRQ_ACK here? */ - snd_azf3328_ctrl_outb(chip, IDX_IO_TIMER_VALUE + 3, 0); + snd_azf3328_codec_outb(chip, IDX_IO_TIMER_VALUE + 3, 0); spin_unlock_irqrestore(&chip->reg_lock, flags); snd_azf3328_dbgcallleave(); return 0; @@ -2097,7 +2035,7 @@ snd_azf3328_test_bit(unsigned unsigned reg, int bit) outb(val, reg); - printk(KERN_DEBUG "reg %04x bit %d: %02x %02x %02x\n", + printk(KERN_ERR "reg %04x bit %d: %02x %02x %02x\n", reg, bit, val, valoff, valon ); } @@ -2110,9 +2048,9 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) u16 tmp; snd_azf3328_dbgmisc( - "ctrl_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, " + "codec_io 0x%lx, game_io 0x%lx, mpu_io 0x%lx, " "opl3_io 0x%lx, mixer_io 0x%lx, irq %d\n", - chip->ctrl_io, chip->game_io, chip->mpu_io, + chip->codec_io, chip->game_io, chip->mpu_io, chip->opl3_io, chip->mixer_io, chip->irq ); @@ -2145,9 +2083,9 @@ snd_azf3328_debug_show_ports(const struct snd_azf3328 *chip) inb(0x38c + tmp) ); - for (tmp = 0; tmp < AZF_IO_SIZE_CTRL; tmp += 2) - snd_azf3328_dbgmisc("ctrl 0x%02x: 0x%04x\n", - tmp, snd_azf3328_ctrl_inw(chip, tmp) + for (tmp = 0; tmp < AZF_IO_SIZE_CODEC; tmp += 2) + snd_azf3328_dbgmisc("codec 0x%02x: 0x%04x\n", + tmp, snd_azf3328_codec_inw(chip, tmp) ); for (tmp = 0; tmp < AZF_IO_SIZE_MIXER; tmp += 2) @@ -2168,8 +2106,7 @@ snd_azf3328_create(struct snd_card *card, static struct snd_device_ops ops = { .dev_free = snd_azf3328_dev_free, }; - u8 dma_init; - enum snd_azf3328_codec_type codec_type; + u16 tmp; *rchip = NULL; @@ -2201,21 +2138,14 @@ snd_azf3328_create(struct snd_card *card, if (err < 0) goto out_err; - chip->ctrl_io = pci_resource_start(pci, 0); + chip->codec_io = pci_resource_start(pci, 0); chip->game_io = pci_resource_start(pci, 1); chip->mpu_io = pci_resource_start(pci, 2); - chip->opl3_io = pci_resource_start(pci, 3); + chip->opl3_io = pci_resource_start(pci, 3); chip->mixer_io = pci_resource_start(pci, 4); - chip->codecs[AZF_CODEC_PLAYBACK].io_base = - chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK; - chip->codecs[AZF_CODEC_PLAYBACK].name = "PLAYBACK"; - chip->codecs[AZF_CODEC_CAPTURE].io_base = - chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE; - chip->codecs[AZF_CODEC_CAPTURE].name = "CAPTURE"; - chip->codecs[AZF_CODEC_I2S_OUT].io_base = - chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT; - chip->codecs[AZF_CODEC_I2S_OUT].name = "I2S_OUT"; + chip->audio_stream[AZF_PLAYBACK].portbase = chip->codec_io + 0x00; + chip->audio_stream[AZF_CAPTURE].portbase = chip->codec_io + 0x20; if (request_irq(pci->irq, snd_azf3328_interrupt, IRQF_SHARED, card->shortname, chip)) { @@ -2238,25 +2168,20 @@ snd_azf3328_create(struct snd_card *card, if (err < 0) goto out_err; - /* standard codec init stuff */ - /* default DMA init value */ - dma_init = DMA_RUN_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE; + /* shutdown codecs to save power */ + /* have snd_azf3328_codec_activity() act properly */ + chip->audio_stream[AZF_PLAYBACK].running = 1; + snd_azf3328_codec_activity(chip, AZF_PLAYBACK, 0); - for (codec_type = AZF_CODEC_PLAYBACK; - codec_type <= AZF_CODEC_I2S_OUT; ++codec_type) { - struct snd_azf3328_codec_data *codec = - &chip->codecs[codec_type]; + /* standard chip init stuff */ + /* default IRQ init value */ + tmp = DMA_PLAY_SOMETHING2|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE; - /* shutdown codecs to save power */ - /* have ...ctrl_codec_activity() act properly */ - codec->running = 1; - snd_azf3328_ctrl_codec_activity(chip, codec_type, 0); - - spin_lock_irq(&chip->reg_lock); - snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS, - dma_init); - spin_unlock_irq(&chip->reg_lock); - } + spin_lock_irq(&chip->reg_lock); + snd_azf3328_codec_outb(chip, IDX_IO_PLAY_FLAGS, tmp); + snd_azf3328_codec_outb(chip, IDX_IO_REC_FLAGS, tmp); + snd_azf3328_codec_outb(chip, IDX_IO_SOMETHING_FLAGS, tmp); + spin_unlock_irq(&chip->reg_lock); snd_card_set_dev(card, &pci->dev); @@ -2304,11 +2229,8 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) card->private_data = chip; - /* chose to use MPU401_HW_AZT2320 ID instead of MPU401_HW_MPU401, - since our hardware ought to be similar, thus use same ID. */ err = snd_mpu401_uart_new( - card, 0, - MPU401_HW_AZT2320, chip->mpu_io, MPU401_INFO_INTEGRATED, + card, 0, MPU401_HW_MPU401, chip->mpu_io, MPU401_INFO_INTEGRATED, pci->irq, 0, &chip->rmidi ); if (err < 0) { @@ -2322,7 +2244,7 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) if (err < 0) goto out_err; - err = snd_azf3328_pcm(chip); + err = snd_azf3328_pcm(chip, 0); if (err < 0) goto out_err; @@ -2344,14 +2266,14 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) opl3->private_data = chip; sprintf(card->longname, "%s at 0x%lx, irq %i", - card->shortname, chip->ctrl_io, chip->irq); + card->shortname, chip->codec_io, chip->irq); err = snd_card_register(card); if (err < 0) goto out_err; #ifdef MODULE - printk(KERN_INFO + printk( "azt3328: Sound driver for Aztech AZF3328-based soundcards such as PCI168.\n" "azt3328: Hardware was completely undocumented, unfortunately.\n" "azt3328: Feel free to contact andi AT lisas.de for bug reports etc.!\n" @@ -2386,52 +2308,36 @@ snd_azf3328_remove(struct pci_dev *pci) } #ifdef CONFIG_PM -static inline void -snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs) -{ - unsigned reg; - - for (reg = 0; reg < count; ++reg) { - *saved_regs = inl(io_addr); - snd_azf3328_dbgpm("suspend: io 0x%04lx: 0x%08x\n", - io_addr, *saved_regs); - ++saved_regs; - io_addr += sizeof(*saved_regs); - } -} - static int snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) { struct snd_card *card = pci_get_drvdata(pci); struct snd_azf3328 *chip = card->private_data; - u16 *saved_regs_ctrl_u16; + unsigned reg; snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]); - snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]); + snd_pcm_suspend_all(chip->pcm); - snd_azf3328_suspend_regs(chip->mixer_io, - ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer); + for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg) + chip->saved_regs_mixer[reg] = inw(chip->mixer_io + reg * 2); /* make sure to disable master volume etc. to prevent looping sound */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1); snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); - snd_azf3328_suspend_regs(chip->ctrl_io, - ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl); + for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg) + chip->saved_regs_codec[reg] = inw(chip->codec_io + reg * 2); /* manually store the one currently relevant write-only reg, too */ - saved_regs_ctrl_u16 = (u16 *)chip->saved_regs_ctrl; - saved_regs_ctrl_u16[IDX_IO_6AH / 2] = chip->shadow_reg_ctrl_6AH; + chip->saved_regs_codec[IDX_IO_6AH / 2] = chip->shadow_reg_codec_6AH; - snd_azf3328_suspend_regs(chip->game_io, - ARRAY_SIZE(chip->saved_regs_game), chip->saved_regs_game); - snd_azf3328_suspend_regs(chip->mpu_io, - ARRAY_SIZE(chip->saved_regs_mpu), chip->saved_regs_mpu); - snd_azf3328_suspend_regs(chip->opl3_io, - ARRAY_SIZE(chip->saved_regs_opl3), chip->saved_regs_opl3); + for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg) + chip->saved_regs_game[reg] = inw(chip->game_io + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg) + chip->saved_regs_mpu[reg] = inw(chip->mpu_io + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg) + chip->saved_regs_opl3[reg] = inw(chip->opl3_io + reg * 2); pci_disable_device(pci); pci_save_state(pci); @@ -2439,28 +2345,12 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state) return 0; } -static inline void -snd_azf3328_resume_regs(const u32 *saved_regs, - unsigned long io_addr, - unsigned count -) -{ - unsigned reg; - - for (reg = 0; reg < count; ++reg) { - outl(*saved_regs, io_addr); - snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n", - io_addr, *saved_regs, inl(io_addr)); - ++saved_regs; - io_addr += sizeof(*saved_regs); - } -} - static int snd_azf3328_resume(struct pci_dev *pci) { struct snd_card *card = pci_get_drvdata(pci); - const struct snd_azf3328 *chip = card->private_data; + struct snd_azf3328 *chip = card->private_data; + unsigned reg; pci_set_power_state(pci, PCI_D0); pci_restore_state(pci); @@ -2472,24 +2362,16 @@ snd_azf3328_resume(struct pci_dev *pci) } pci_set_master(pci); - snd_azf3328_resume_regs(chip->saved_regs_game, chip->game_io, - ARRAY_SIZE(chip->saved_regs_game)); - snd_azf3328_resume_regs(chip->saved_regs_mpu, chip->mpu_io, - ARRAY_SIZE(chip->saved_regs_mpu)); - snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io, - ARRAY_SIZE(chip->saved_regs_opl3)); - - snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io, - ARRAY_SIZE(chip->saved_regs_mixer)); - - /* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02) - and IDX_MIXER_RESET (offset 0x00) get touched at the same time, - resulting in a mixer reset condition persisting until _after_ - master vol was restored. Thus master vol needs an extra restore. */ - outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2); - - snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io, - ARRAY_SIZE(chip->saved_regs_ctrl)); + for (reg = 0; reg < AZF_IO_SIZE_GAME_PM / 2; ++reg) + outw(chip->saved_regs_game[reg], chip->game_io + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_MPU_PM / 2; ++reg) + outw(chip->saved_regs_mpu[reg], chip->mpu_io + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_OPL3_PM / 2; ++reg) + outw(chip->saved_regs_opl3[reg], chip->opl3_io + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_MIXER_PM / 2; ++reg) + outw(chip->saved_regs_mixer[reg], chip->mixer_io + reg * 2); + for (reg = 0; reg < AZF_IO_SIZE_CODEC_PM / 2; ++reg) + outw(chip->saved_regs_codec[reg], chip->codec_io + reg * 2); snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; diff --git a/trunk/sound/pci/azt3328.h b/trunk/sound/pci/azt3328.h index 6f46b97650cc..974e05122f00 100644 --- a/trunk/sound/pci/azt3328.h +++ b/trunk/sound/pci/azt3328.h @@ -6,59 +6,50 @@ /*** main I/O area port indices ***/ /* (only 0x70 of 0x80 bytes saved/restored by Windows driver) */ -#define AZF_IO_SIZE_CTRL 0x80 -#define AZF_IO_SIZE_CTRL_PM 0x70 +#define AZF_IO_SIZE_CODEC 0x80 +#define AZF_IO_SIZE_CODEC_PM 0x70 -/* the driver initialisation suggests a layout of 4 areas - * within the main card control I/O: - * from 0x00 (playback codec), from 0x20 (recording codec) - * and from 0x40 (most certainly I2S out codec). +/* the driver initialisation suggests a layout of 4 main areas: + * from 0x00 (playback), from 0x20 (recording) and from 0x40 (maybe MPU401??). * And another area from 0x60 to 0x6f (DirectX timer, IRQ management, * power management etc.???). */ -#define AZF_IO_OFFS_CODEC_PLAYBACK 0x00 -#define AZF_IO_OFFS_CODEC_CAPTURE 0x20 -#define AZF_IO_OFFS_CODEC_I2S_OUT 0x40 - -#define IDX_IO_CODEC_DMA_FLAGS 0x00 /* PU:0x0000 */ +/** playback area **/ +#define IDX_IO_PLAY_FLAGS 0x00 /* PU:0x0000 */ /* able to reactivate output after output muting due to 8/16bit * output change, just like 0x0002. * 0x0001 is the only bit that's able to start the DMA counter */ - #define DMA_RESUME 0x0001 /* paused if cleared? */ + #define DMA_RESUME 0x0001 /* paused if cleared ? */ /* 0x0002 *temporarily* set during DMA stopping. hmm * both 0x0002 and 0x0004 set in playback setup. */ /* able to reactivate output after output muting due to 8/16bit * output change, just like 0x0001. */ - #define DMA_RUN_SOMETHING1 0x0002 /* \ alternated (toggled) */ + #define DMA_PLAY_SOMETHING1 0x0002 /* \ alternated (toggled) */ /* 0x0004: NOT able to reactivate output */ - #define DMA_RUN_SOMETHING2 0x0004 /* / bits */ + #define DMA_PLAY_SOMETHING2 0x0004 /* / bits */ #define SOMETHING_ALMOST_ALWAYS_SET 0x0008 /* ???; can be modified */ #define DMA_EPILOGUE_SOMETHING 0x0010 #define DMA_SOMETHING_ELSE 0x0020 /* ??? */ - #define SOMETHING_UNMODIFIABLE 0xffc0 /* unused? not modifiable */ -#define IDX_IO_CODEC_IRQTYPE 0x02 /* PU:0x0001 */ + #define SOMETHING_UNMODIFIABLE 0xffc0 /* unused ? not modifiable */ +#define IDX_IO_PLAY_IRQTYPE 0x02 /* PU:0x0001 */ /* write back to flags in case flags are set, in order to ACK IRQ in handler * (bit 1 of port 0x64 indicates interrupt for one of these three types) * sometimes in this case it just writes 0xffff to globally ACK all IRQs * settings written are not reflected when reading back, though. - * seems to be IRQ, too (frequently used: port |= 0x07 !), but who knows? */ - #define IRQ_SOMETHING 0x0001 /* something & ACK */ - #define IRQ_FINISHED_DMABUF_1 0x0002 /* 1st dmabuf finished & ACK */ - #define IRQ_FINISHED_DMABUF_2 0x0004 /* 2nd dmabuf finished & ACK */ + * seems to be IRQ, too (frequently used: port |= 0x07 !), but who knows ? */ + #define IRQ_PLAY_SOMETHING 0x0001 /* something & ACK */ + #define IRQ_FINISHED_PLAYBUF_1 0x0002 /* 1st dmabuf finished & ACK */ + #define IRQ_FINISHED_PLAYBUF_2 0x0004 /* 2nd dmabuf finished & ACK */ #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ - #define IRQMASK_UNMODIFIABLE 0xffe0 /* unused? not modifiable */ - /* start address of 1st DMA transfer area, PU:0x00000000 */ -#define IDX_IO_CODEC_DMA_START_1 0x04 - /* start address of 2nd DMA transfer area, PU:0x00000000 */ -#define IDX_IO_CODEC_DMA_START_2 0x08 - /* both lengths of DMA transfer areas, PU:0x00000000 - length1: offset 0x0c, length2: offset 0x0e */ -#define IDX_IO_CODEC_DMA_LENGTHS 0x0c -#define IDX_IO_CODEC_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */ - /* offset within current DMA transfer area, PU:0x0000 */ -#define IDX_IO_CODEC_DMA_CURROFS 0x14 -#define IDX_IO_CODEC_SOUNDFORMAT 0x16 /* PU:0x0010 */ + #define IRQMASK_UNMODIFIABLE 0xffe0 /* unused ? not modifiable */ +#define IDX_IO_PLAY_DMA_START_1 0x04 /* start address of 1st DMA play area, PU:0x00000000 */ +#define IDX_IO_PLAY_DMA_START_2 0x08 /* start address of 2nd DMA play area, PU:0x00000000 */ +#define IDX_IO_PLAY_DMA_LEN_1 0x0c /* length of 1st DMA play area, PU:0x0000 */ +#define IDX_IO_PLAY_DMA_LEN_2 0x0e /* length of 2nd DMA play area, PU:0x0000 */ +#define IDX_IO_PLAY_DMA_CURRPOS 0x10 /* current DMA position, PU:0x00000000 */ +#define IDX_IO_PLAY_DMA_CURROFS 0x14 /* offset within current DMA play area, PU:0x0000 */ +#define IDX_IO_PLAY_SOUNDFORMAT 0x16 /* PU:0x0010 */ /* all unspecified bits can't be modified */ #define SOUNDFORMAT_FREQUENCY_MASK 0x000f #define SOUNDFORMAT_XTAL1 0x00 @@ -85,7 +76,6 @@ #define SOUNDFORMAT_FLAG_16BIT 0x0010 #define SOUNDFORMAT_FLAG_2CHANNELS 0x0020 - /* define frequency helpers, for maximum value safety */ enum azf_freq_t { #define AZF_FREQ(rate) AZF_FREQ_##rate = rate @@ -106,6 +96,29 @@ enum azf_freq_t { #undef AZF_FREQ }; +/** recording area (see also: playback bit flag definitions) **/ +#define IDX_IO_REC_FLAGS 0x20 /* ??, PU:0x0000 */ +#define IDX_IO_REC_IRQTYPE 0x22 /* ??, PU:0x0000 */ + #define IRQ_REC_SOMETHING 0x0001 /* something & ACK */ + #define IRQ_FINISHED_RECBUF_1 0x0002 /* 1st dmabuf finished & ACK */ + #define IRQ_FINISHED_RECBUF_2 0x0004 /* 2nd dmabuf finished & ACK */ + /* hmm, maybe these are just the corresponding *recording* flags ? + * but OTOH they are most likely at port 0x22 instead */ + #define IRQMASK_SOME_STATUS_1 0x0008 /* \ related bits */ + #define IRQMASK_SOME_STATUS_2 0x0010 /* / (checked together in loop) */ +#define IDX_IO_REC_DMA_START_1 0x24 /* PU:0x00000000 */ +#define IDX_IO_REC_DMA_START_2 0x28 /* PU:0x00000000 */ +#define IDX_IO_REC_DMA_LEN_1 0x2c /* PU:0x0000 */ +#define IDX_IO_REC_DMA_LEN_2 0x2e /* PU:0x0000 */ +#define IDX_IO_REC_DMA_CURRPOS 0x30 /* PU:0x00000000 */ +#define IDX_IO_REC_DMA_CURROFS 0x34 /* PU:0x00000000 */ +#define IDX_IO_REC_SOUNDFORMAT 0x36 /* PU:0x0000 */ + +/** hmm, what is this I/O area for? MPU401?? or external DAC via I2S?? (after playback, recording, ???, timer) **/ +#define IDX_IO_SOMETHING_FLAGS 0x40 /* gets set to 0x34 just like port 0x0 and 0x20 on card init, PU:0x0000 */ +/* general */ +#define IDX_IO_42H 0x42 /* PU:0x0001 */ + /** DirectX timer, main interrupt area (FIXME: and something else?) **/ #define IDX_IO_TIMER_VALUE 0x60 /* found this timer area by pure luck :-) */ /* timer countdown value; triggers IRQ when timer is finished */ @@ -120,19 +133,17 @@ enum azf_freq_t { #define IDX_IO_IRQSTATUS 0x64 /* some IRQ bit in here might also be used to signal a power-management timer * timeout, to request shutdown of the chip (e.g. AD1815JS has such a thing). - * OPL3 hardware contains several timers which confusingly in most cases - * are NOT routed to an IRQ, but some designs (e.g. LM4560) DO support that, - * so I wouldn't be surprised at all to discover that AZF3328 - * supports that thing as well... */ + * Some OPL3 hardware (e.g. in LM4560) has some special timer hardware which + * can trigger an OPL3 timer IRQ, so maybe there's such a thing as well... */ #define IRQ_PLAYBACK 0x0001 #define IRQ_RECORDING 0x0002 - #define IRQ_I2S_OUT 0x0004 /* this IS I2S, right!? (untested) */ + #define IRQ_UNKNOWN1 0x0004 /* most probably I2S port */ #define IRQ_GAMEPORT 0x0008 /* Interrupt of Digital(ly) Enhanced Game Port */ #define IRQ_MPU401 0x0010 #define IRQ_TIMER 0x0020 /* DirectX timer */ - #define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly OPL3 timer? */ - #define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly OPL3 timer? */ + #define IRQ_UNKNOWN2 0x0040 /* probably unused, or possibly I2S port? */ + #define IRQ_UNKNOWN3 0x0080 /* probably unused, or possibly I2S port? */ #define IDX_IO_66H 0x66 /* writing 0xffff returns 0x0000 */ /* this is set to e.g. 0x3ff or 0x300, and writable; * maybe some buffer limit, but I couldn't find out more, PU:0x00ff: */ @@ -195,7 +206,7 @@ enum azf_freq_t { /*** Gameport area port indices ***/ /* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ #define AZF_IO_SIZE_GAME 0x08 -#define AZF_IO_SIZE_GAME_PM 0x06 +#define AZF_IO_SIZE_GAME_PM 0x06 enum { AZF_GAME_LEGACY_IO_PORT = 0x200 @@ -261,12 +272,6 @@ enum { * 11 --> 1/200: */ #define GAME_HWCFG_ADC_COUNTER_FREQ_MASK 0x06 - /* FIXME: these values might be reversed... */ - #define GAME_HWCFG_ADC_COUNTER_FREQ_STD 0 - #define GAME_HWCFG_ADC_COUNTER_FREQ_1_2 1 - #define GAME_HWCFG_ADC_COUNTER_FREQ_1_20 2 - #define GAME_HWCFG_ADC_COUNTER_FREQ_1_200 3 - /* enable gameport legacy I/O address (0x200) * I was unable to locate any configurability for a different address: */ #define GAME_HWCFG_LEGACY_ADDRESS_ENABLE 0x08 @@ -276,7 +281,6 @@ enum { #define AZF_IO_SIZE_MPU_PM 0x04 /*** OPL3 synth ***/ -/* (only 0x06 of 0x08 bytes saved/restored by Windows driver) */ #define AZF_IO_SIZE_OPL3 0x08 #define AZF_IO_SIZE_OPL3_PM 0x06 /* hmm, given that a standard OPL3 has 4 registers only, @@ -336,7 +340,4 @@ enum { #define SET_CHAN_LEFT 1 #define SET_CHAN_RIGHT 2 -/* helper macro to align I/O port ranges to 32bit I/O width */ -#define AZF_ALIGN(x) (((x) + 3) & (~3)) - #endif /* __SOUND_AZT3328_H */ diff --git a/trunk/sound/pci/cs46xx/cs46xx_lib.h b/trunk/sound/pci/cs46xx/cs46xx_lib.h index b5189495d58a..4eb55aa33612 100644 --- a/trunk/sound/pci/cs46xx/cs46xx_lib.h +++ b/trunk/sound/pci/cs46xx/cs46xx_lib.h @@ -35,7 +35,7 @@ #ifdef CONFIG_SND_CS46XX_NEW_DSP -#define CS46XX_MIN_PERIOD_SIZE 64 +#define CS46XX_MIN_PERIOD_SIZE 1 #define CS46XX_MAX_PERIOD_SIZE 1024*1024 #else #define CS46XX_MIN_PERIOD_SIZE 2048 diff --git a/trunk/sound/pci/ctxfi/ct20k2reg.h b/trunk/sound/pci/ctxfi/ct20k2reg.h index e0394e3996e8..2d07986f57cc 100644 --- a/trunk/sound/pci/ctxfi/ct20k2reg.h +++ b/trunk/sound/pci/ctxfi/ct20k2reg.h @@ -11,12 +11,9 @@ /* Timer Registers */ -#define WC 0x1b7000 -#define TIMR 0x1b7004 -# define TIMR_IE (1<<15) -# define TIMR_IP (1<<14) -#define GIP 0x1b7010 -#define GIE 0x1b7014 +#define TIMER_TIMR 0x1B7004 +#define INTERRUPT_GIP 0x1B7010 +#define INTERRUPT_GIE 0x1B7014 /* I2C Registers */ #define I2C_IF_ADDRESS 0x1B9000 diff --git a/trunk/sound/pci/ctxfi/ctamixer.c b/trunk/sound/pci/ctxfi/ctamixer.c index fee35cfc0c7f..a7f4a671f7b7 100644 --- a/trunk/sound/pci/ctxfi/ctamixer.c +++ b/trunk/sound/pci/ctxfi/ctamixer.c @@ -63,7 +63,7 @@ static int amixer_set_input(struct amixer *amixer, struct rsc *rsc) hw = amixer->rsc.hw; hw->amixer_set_mode(amixer->rsc.ctrl_blk, AMIXER_Y_IMMEDIATE); amixer->input = rsc; - if (!rsc) + if (NULL == rsc) hw->amixer_set_x(amixer->rsc.ctrl_blk, BLANK_SLOT); else hw->amixer_set_x(amixer->rsc.ctrl_blk, @@ -99,7 +99,7 @@ static int amixer_set_sum(struct amixer *amixer, struct sum *sum) hw = amixer->rsc.hw; amixer->sum = sum; - if (!sum) { + if (NULL == sum) { hw->amixer_set_se(amixer->rsc.ctrl_blk, 0); } else { hw->amixer_set_se(amixer->rsc.ctrl_blk, 1); @@ -124,20 +124,20 @@ static int amixer_commit_write(struct amixer *amixer) /* Program master and conjugate resources */ amixer->rsc.ops->master(&amixer->rsc); - if (input) + if (NULL != input) input->ops->master(input); - if (sum) + if (NULL != sum) sum->rsc.ops->master(&sum->rsc); for (i = 0; i < amixer->rsc.msr; i++) { hw->amixer_set_dirty_all(amixer->rsc.ctrl_blk); - if (input) { + if (NULL != input) { hw->amixer_set_x(amixer->rsc.ctrl_blk, input->ops->output_slot(input)); input->ops->next_conj(input); } - if (sum) { + if (NULL != sum) { hw->amixer_set_sadr(amixer->rsc.ctrl_blk, sum->rsc.ops->index(&sum->rsc)); sum->rsc.ops->next_conj(&sum->rsc); @@ -147,10 +147,10 @@ static int amixer_commit_write(struct amixer *amixer) amixer->rsc.ops->next_conj(&amixer->rsc); } amixer->rsc.ops->master(&amixer->rsc); - if (input) + if (NULL != input) input->ops->master(input); - if (sum) + if (NULL != sum) sum->rsc.ops->master(&sum->rsc); return 0; @@ -303,7 +303,7 @@ int amixer_mgr_create(void *hw, struct amixer_mgr **ramixer_mgr) *ramixer_mgr = NULL; amixer_mgr = kzalloc(sizeof(*amixer_mgr), GFP_KERNEL); - if (!amixer_mgr) + if (NULL == amixer_mgr) return -ENOMEM; err = rsc_mgr_init(&amixer_mgr->mgr, AMIXER, AMIXER_RESOURCE_NUM, hw); @@ -456,7 +456,7 @@ int sum_mgr_create(void *hw, struct sum_mgr **rsum_mgr) *rsum_mgr = NULL; sum_mgr = kzalloc(sizeof(*sum_mgr), GFP_KERNEL); - if (!sum_mgr) + if (NULL == sum_mgr) return -ENOMEM; err = rsc_mgr_init(&sum_mgr->mgr, SUM, SUM_RESOURCE_NUM, hw); diff --git a/trunk/sound/pci/ctxfi/ctatc.c b/trunk/sound/pci/ctxfi/ctatc.c index b1b3a644f738..a49c76647307 100644 --- a/trunk/sound/pci/ctxfi/ctatc.c +++ b/trunk/sound/pci/ctxfi/ctatc.c @@ -136,7 +136,7 @@ static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm) struct snd_pcm_runtime *runtime; struct ct_vm *vm; - if (!apcm->substream) + if (NULL == apcm->substream) return 0; runtime = apcm->substream->runtime; @@ -144,7 +144,7 @@ static int ct_map_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm) apcm->vm_block = vm->map(vm, apcm->substream, runtime->dma_bytes); - if (!apcm->vm_block) + if (NULL == apcm->vm_block) return -ENOENT; return 0; @@ -154,7 +154,7 @@ static void ct_unmap_audio_buffer(struct ct_atc *atc, struct ct_atc_pcm *apcm) { struct ct_vm *vm; - if (!apcm->vm_block) + if (NULL == apcm->vm_block) return; vm = atc->vm; @@ -231,16 +231,16 @@ atc_get_pitch(unsigned int input_rate, unsigned int output_rate) static int select_rom(unsigned int pitch) { - if (pitch > 0x00428f5c && pitch < 0x01b851ec) { + if ((pitch > 0x00428f5c) && (pitch < 0x01b851ec)) { /* 0.26 <= pitch <= 1.72 */ return 1; - } else if (pitch == 0x01d66666 || pitch == 0x01d66667) { + } else if ((0x01d66666 == pitch) || (0x01d66667 == pitch)) { /* pitch == 1.8375 */ return 2; - } else if (pitch == 0x02000000) { + } else if (0x02000000 == pitch) { /* pitch == 2 */ return 3; - } else if (pitch >= 0x0 && pitch <= 0x08000000) { + } else if ((pitch >= 0x0) && (pitch <= 0x08000000)) { /* 0 <= pitch <= 8 */ return 0; } else { @@ -283,7 +283,7 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) /* Get AMIXER resource */ n_amixer = (n_amixer < 2) ? 2 : n_amixer; apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); - if (!apcm->amixers) { + if (NULL == apcm->amixers) { err = -ENOMEM; goto error1; } @@ -311,7 +311,7 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) INIT_VOL, atc->pcm[i+device*2]); mutex_unlock(&atc->atc_mutex); src = src->ops->next_interleave(src); - if (!src) + if (NULL == src) src = apcm->src; } @@ -334,7 +334,7 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm) struct srcimp *srcimp; int i; - if (apcm->srcimps) { + if (NULL != apcm->srcimps) { for (i = 0; i < apcm->n_srcimp; i++) { srcimp = apcm->srcimps[i]; srcimp->ops->unmap(srcimp); @@ -345,7 +345,7 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm) apcm->srcimps = NULL; } - if (apcm->srccs) { + if (NULL != apcm->srccs) { for (i = 0; i < apcm->n_srcc; i++) { src_mgr->put_src(src_mgr, apcm->srccs[i]); apcm->srccs[i] = NULL; @@ -354,7 +354,7 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm) apcm->srccs = NULL; } - if (apcm->amixers) { + if (NULL != apcm->amixers) { for (i = 0; i < apcm->n_amixer; i++) { amixer_mgr->put_amixer(amixer_mgr, apcm->amixers[i]); apcm->amixers[i] = NULL; @@ -363,17 +363,17 @@ atc_pcm_release_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm) apcm->amixers = NULL; } - if (apcm->mono) { + if (NULL != apcm->mono) { sum_mgr->put_sum(sum_mgr, apcm->mono); apcm->mono = NULL; } - if (apcm->src) { + if (NULL != apcm->src) { src_mgr->put_src(src_mgr, apcm->src); apcm->src = NULL; } - if (apcm->vm_block) { + if (NULL != apcm->vm_block) { /* Undo device virtual mem map */ ct_unmap_audio_buffer(atc, apcm); apcm->vm_block = NULL; @@ -419,7 +419,7 @@ static int atc_pcm_stop(struct ct_atc *atc, struct ct_atc_pcm *apcm) src->ops->set_state(src, SRC_STATE_OFF); src->ops->commit_write(src); - if (apcm->srccs) { + if (NULL != apcm->srccs) { for (i = 0; i < apcm->n_srcc; i++) { src = apcm->srccs[i]; src->ops->set_bm(src, 0); @@ -544,18 +544,18 @@ atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm) if (n_srcc) { apcm->srccs = kzalloc(sizeof(void *)*n_srcc, GFP_KERNEL); - if (!apcm->srccs) + if (NULL == apcm->srccs) return -ENOMEM; } if (n_amixer) { apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); - if (!apcm->amixers) { + if (NULL == apcm->amixers) { err = -ENOMEM; goto error1; } } apcm->srcimps = kzalloc(sizeof(void *)*n_srcimp, GFP_KERNEL); - if (!apcm->srcimps) { + if (NULL == apcm->srcimps) { err = -ENOMEM; goto error1; } @@ -818,7 +818,7 @@ static int spdif_passthru_playback_get_resources(struct ct_atc *atc, /* Get AMIXER resource */ n_amixer = (n_amixer < 2) ? 2 : n_amixer; apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL); - if (!apcm->amixers) { + if (NULL == apcm->amixers) { err = -ENOMEM; goto error1; } @@ -919,7 +919,7 @@ spdif_passthru_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm) amixer = apcm->amixers[i]; amixer->ops->setup(amixer, &src->rsc, INIT_VOL, NULL); src = src->ops->next_interleave(src); - if (!src) + if (NULL == src) src = apcm->src; } /* Connect to SPDIFOO */ @@ -1121,7 +1121,7 @@ static int atc_release_resources(struct ct_atc *atc) struct ct_mixer *mixer = NULL; /* disconnect internal mixer objects */ - if (atc->mixer) { + if (NULL != atc->mixer) { mixer = atc->mixer; mixer->set_input_left(mixer, MIX_LINE_IN, NULL); mixer->set_input_right(mixer, MIX_LINE_IN, NULL); @@ -1131,7 +1131,7 @@ static int atc_release_resources(struct ct_atc *atc) mixer->set_input_right(mixer, MIX_SPDIF_IN, NULL); } - if (atc->daios) { + if (NULL != atc->daios) { daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; for (i = 0; i < atc->n_daio; i++) { daio = atc->daios[i]; @@ -1149,7 +1149,7 @@ static int atc_release_resources(struct ct_atc *atc) atc->daios = NULL; } - if (atc->pcm) { + if (NULL != atc->pcm) { sum_mgr = atc->rsc_mgrs[SUM]; for (i = 0; i < atc->n_pcm; i++) sum_mgr->put_sum(sum_mgr, atc->pcm[i]); @@ -1158,7 +1158,7 @@ static int atc_release_resources(struct ct_atc *atc) atc->pcm = NULL; } - if (atc->srcs) { + if (NULL != atc->srcs) { src_mgr = atc->rsc_mgrs[SRC]; for (i = 0; i < atc->n_src; i++) src_mgr->put_src(src_mgr, atc->srcs[i]); @@ -1167,7 +1167,7 @@ static int atc_release_resources(struct ct_atc *atc) atc->srcs = NULL; } - if (atc->srcimps) { + if (NULL != atc->srcimps) { srcimp_mgr = atc->rsc_mgrs[SRCIMP]; for (i = 0; i < atc->n_srcimp; i++) { srcimp = atc->srcimps[i]; @@ -1185,7 +1185,7 @@ static int ct_atc_destroy(struct ct_atc *atc) { int i = 0; - if (!atc) + if (NULL == atc) return 0; if (atc->timer) { @@ -1196,20 +1196,21 @@ static int ct_atc_destroy(struct ct_atc *atc) atc_release_resources(atc); /* Destroy internal mixer objects */ - if (atc->mixer) + if (NULL != atc->mixer) ct_mixer_destroy(atc->mixer); for (i = 0; i < NUM_RSCTYP; i++) { - if (rsc_mgr_funcs[i].destroy && atc->rsc_mgrs[i]) + if ((NULL != rsc_mgr_funcs[i].destroy) && + (NULL != atc->rsc_mgrs[i])) rsc_mgr_funcs[i].destroy(atc->rsc_mgrs[i]); } - if (atc->hw) + if (NULL != atc->hw) destroy_hw_obj((struct hw *)atc->hw); /* Destroy device virtual memory manager object */ - if (atc->vm) { + if (NULL != atc->vm) { ct_vm_destroy(atc->vm); atc->vm = NULL; } @@ -1274,7 +1275,7 @@ int __devinit ct_atc_create_alsa_devs(struct ct_atc *atc) alsa_dev_funcs[MIXER].public_name = atc->chip_name; for (i = 0; i < NUM_CTALSADEVS; i++) { - if (!alsa_dev_funcs[i].create) + if (NULL == alsa_dev_funcs[i].create) continue; err = alsa_dev_funcs[i].create(atc, i, @@ -1311,7 +1312,7 @@ static int __devinit atc_create_hw_devs(struct ct_atc *atc) return err; for (i = 0; i < NUM_RSCTYP; i++) { - if (!rsc_mgr_funcs[i].create) + if (NULL == rsc_mgr_funcs[i].create) continue; err = rsc_mgr_funcs[i].create(atc->hw, &atc->rsc_mgrs[i]); @@ -1338,19 +1339,19 @@ static int atc_get_resources(struct ct_atc *atc) int err, i; atc->daios = kzalloc(sizeof(void *)*(DAIONUM), GFP_KERNEL); - if (!atc->daios) + if (NULL == atc->daios) return -ENOMEM; atc->srcs = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); - if (!atc->srcs) + if (NULL == atc->srcs) return -ENOMEM; atc->srcimps = kzalloc(sizeof(void *)*(2*2), GFP_KERNEL); - if (!atc->srcimps) + if (NULL == atc->srcimps) return -ENOMEM; atc->pcm = kzalloc(sizeof(void *)*(2*4), GFP_KERNEL); - if (!atc->pcm) + if (NULL == atc->pcm) return -ENOMEM; daio_mgr = (struct daio_mgr *)atc->rsc_mgrs[DAIO]; @@ -1647,7 +1648,7 @@ int __devinit ct_atc_create(struct snd_card *card, struct pci_dev *pci, *ratc = NULL; atc = kzalloc(sizeof(*atc), GFP_KERNEL); - if (!atc) + if (NULL == atc) return -ENOMEM; /* Set operations */ diff --git a/trunk/sound/pci/ctxfi/ctdaio.c b/trunk/sound/pci/ctxfi/ctdaio.c index af56eb949bde..deb6cfa73600 100644 --- a/trunk/sound/pci/ctxfi/ctdaio.c +++ b/trunk/sound/pci/ctxfi/ctdaio.c @@ -173,7 +173,7 @@ static int dao_set_left_input(struct dao *dao, struct rsc *input) int i; entry = kzalloc((sizeof(*entry) * daio->rscl.msr), GFP_KERNEL); - if (!entry) + if (NULL == entry) return -ENOMEM; /* Program master and conjugate resources */ @@ -201,7 +201,7 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input) int i; entry = kzalloc((sizeof(*entry) * daio->rscr.msr), GFP_KERNEL); - if (!entry) + if (NULL == entry) return -ENOMEM; /* Program master and conjugate resources */ @@ -228,7 +228,7 @@ static int dao_clear_left_input(struct dao *dao) struct daio *daio = &dao->daio; int i; - if (!dao->imappers[0]) + if (NULL == dao->imappers[0]) return 0; entry = dao->imappers[0]; @@ -252,7 +252,7 @@ static int dao_clear_right_input(struct dao *dao) struct daio *daio = &dao->daio; int i; - if (!dao->imappers[daio->rscl.msr]) + if (NULL == dao->imappers[daio->rscl.msr]) return 0; entry = dao->imappers[daio->rscl.msr]; @@ -408,7 +408,7 @@ static int dao_rsc_init(struct dao *dao, return err; dao->imappers = kzalloc(sizeof(void *)*desc->msr*2, GFP_KERNEL); - if (!dao->imappers) { + if (NULL == dao->imappers) { err = -ENOMEM; goto error1; } @@ -442,11 +442,11 @@ static int dao_rsc_init(struct dao *dao, static int dao_rsc_uninit(struct dao *dao) { - if (dao->imappers) { - if (dao->imappers[0]) + if (NULL != dao->imappers) { + if (NULL != dao->imappers[0]) dao_clear_left_input(dao); - if (dao->imappers[dao->daio.rscl.msr]) + if (NULL != dao->imappers[dao->daio.rscl.msr]) dao_clear_right_input(dao); kfree(dao->imappers); @@ -555,7 +555,7 @@ static int get_daio_rsc(struct daio_mgr *mgr, /* Allocate mem for daio resource */ if (desc->type <= DAIO_OUT_MAX) { dao = kzalloc(sizeof(*dao), GFP_KERNEL); - if (!dao) { + if (NULL == dao) { err = -ENOMEM; goto error; } @@ -566,7 +566,7 @@ static int get_daio_rsc(struct daio_mgr *mgr, *rdaio = &dao->daio; } else { dai = kzalloc(sizeof(*dai), GFP_KERNEL); - if (!dai) { + if (NULL == dai) { err = -ENOMEM; goto error; } @@ -583,9 +583,9 @@ static int get_daio_rsc(struct daio_mgr *mgr, return 0; error: - if (dao) + if (NULL != dao) kfree(dao); - else if (dai) + else if (NULL != dai) kfree(dai); spin_lock_irqsave(&mgr->mgr_lock, flags); @@ -663,7 +663,7 @@ static int daio_imap_add(struct daio_mgr *mgr, struct imapper *entry) int err; spin_lock_irqsave(&mgr->imap_lock, flags); - if (!entry->addr && mgr->init_imap_added) { + if ((0 == entry->addr) && (mgr->init_imap_added)) { input_mapper_delete(&mgr->imappers, mgr->init_imap, daio_map_op, mgr); mgr->init_imap_added = 0; @@ -707,7 +707,7 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) *rdaio_mgr = NULL; daio_mgr = kzalloc(sizeof(*daio_mgr), GFP_KERNEL); - if (!daio_mgr) + if (NULL == daio_mgr) return -ENOMEM; err = rsc_mgr_init(&daio_mgr->mgr, DAIO, DAIO_RESOURCE_NUM, hw); @@ -718,7 +718,7 @@ int daio_mgr_create(void *hw, struct daio_mgr **rdaio_mgr) spin_lock_init(&daio_mgr->imap_lock); INIT_LIST_HEAD(&daio_mgr->imappers); entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { + if (NULL == entry) { err = -ENOMEM; goto error2; } diff --git a/trunk/sound/pci/ctxfi/cthw20k1.c b/trunk/sound/pci/ctxfi/cthw20k1.c index 0cf400f879f9..ad3e1d144464 100644 --- a/trunk/sound/pci/ctxfi/cthw20k1.c +++ b/trunk/sound/pci/ctxfi/cthw20k1.c @@ -168,7 +168,7 @@ static int src_get_rsc_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -494,7 +494,7 @@ static int src_mgr_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -515,7 +515,7 @@ static int srcimp_mgr_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -702,7 +702,7 @@ static int amixer_rsc_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -723,7 +723,7 @@ static int amixer_mgr_get_ctrl_blk(void **rblk) *rblk = NULL; /*blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk;*/ @@ -909,7 +909,7 @@ static int dai_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -958,7 +958,7 @@ static int dao_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -1152,7 +1152,7 @@ static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; blk->i2sctl = hw_read_20kx(hw, I2SCTL); @@ -1808,7 +1808,7 @@ static int uaa_to_xfi(struct pci_dev *pci) /* By default, Hendrix card UAA Bar0 should be using memory... */ io_base = pci_resource_start(pci, 0); mem_base = ioremap(io_base, pci_resource_len(pci, 0)); - if (!mem_base) + if (NULL == mem_base) return -ENOENT; /* Read current mode from Mode Change Register */ @@ -1977,7 +1977,7 @@ static int hw_card_shutdown(struct hw *hw) hw->irq = -1; - if (hw->mem_base) + if (NULL != ((void *)hw->mem_base)) iounmap((void *)hw->mem_base); hw->mem_base = (unsigned long)NULL; @@ -2274,7 +2274,7 @@ int __devinit create_20k1_hw_obj(struct hw **rhw) *rhw = NULL; hw20k1 = kzalloc(sizeof(*hw20k1), GFP_KERNEL); - if (!hw20k1) + if (NULL == hw20k1) return -ENOMEM; spin_lock_init(&hw20k1->reg_20k1_lock); diff --git a/trunk/sound/pci/ctxfi/cthw20k2.c b/trunk/sound/pci/ctxfi/cthw20k2.c index b6b11bfe7574..dec46d04b041 100644 --- a/trunk/sound/pci/ctxfi/cthw20k2.c +++ b/trunk/sound/pci/ctxfi/cthw20k2.c @@ -166,7 +166,7 @@ static int src_get_rsc_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -492,7 +492,7 @@ static int src_mgr_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -513,7 +513,7 @@ static int srcimp_mgr_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -702,7 +702,7 @@ static int amixer_rsc_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -891,7 +891,7 @@ static int dai_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -941,7 +941,7 @@ static int dao_get_ctrl_blk(void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; *rblk = blk; @@ -1092,7 +1092,7 @@ static int daio_mgr_get_ctrl_blk(struct hw *hw, void **rblk) *rblk = NULL; blk = kzalloc(sizeof(*blk), GFP_KERNEL); - if (!blk) + if (NULL == blk) return -ENOMEM; for (i = 0; i < 8; i++) { @@ -1112,26 +1112,6 @@ static int daio_mgr_put_ctrl_blk(void *blk) return 0; } -/* Timer interrupt */ -static int set_timer_irq(struct hw *hw, int enable) -{ - hw_write_20kx(hw, GIE, enable ? IT_INT : 0); - return 0; -} - -static int set_timer_tick(struct hw *hw, unsigned int ticks) -{ - if (ticks) - ticks |= TIMR_IE | TIMR_IP; - hw_write_20kx(hw, TIMR, ticks); - return 0; -} - -static unsigned int get_wc(struct hw *hw) -{ - return hw_read_20kx(hw, WC); -} - /* Card hardware initialization block */ struct dac_conf { unsigned int msr; /* master sample rate in rsrs */ @@ -1861,22 +1841,6 @@ static int hw_have_digit_io_switch(struct hw *hw) return 0; } -static irqreturn_t ct_20k2_interrupt(int irq, void *dev_id) -{ - struct hw *hw = dev_id; - unsigned int status; - - status = hw_read_20kx(hw, GIP); - if (!status) - return IRQ_NONE; - - if (hw->irq_callback) - hw->irq_callback(hw->irq_callback_data, status); - - hw_write_20kx(hw, GIP, status); - return IRQ_HANDLED; -} - static int hw_card_start(struct hw *hw) { int err = 0; @@ -1904,7 +1868,7 @@ static int hw_card_start(struct hw *hw) hw->io_base = pci_resource_start(hw->pci, 2); hw->mem_base = (unsigned long)ioremap(hw->io_base, pci_resource_len(hw->pci, 2)); - if (!hw->mem_base) { + if (NULL == (void *)hw->mem_base) { err = -ENOENT; goto error2; } @@ -1915,15 +1879,12 @@ static int hw_card_start(struct hw *hw) set_field(&gctl, GCTL_UAA, 0); hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); - if (hw->irq < 0) { - err = request_irq(pci->irq, ct_20k2_interrupt, IRQF_SHARED, - "ctxfi", hw); - if (err < 0) { - printk(KERN_ERR "XFi: Cannot get irq %d\n", pci->irq); - goto error2; - } - hw->irq = pci->irq; + /*if ((err = request_irq(pci->irq, ct_atc_interrupt, IRQF_SHARED, + atc->chip_details->nm_card, hw))) { + goto error3; } + hw->irq = pci->irq; + */ pci_set_master(pci); @@ -1962,7 +1923,7 @@ static int hw_card_shutdown(struct hw *hw) hw->irq = -1; - if (hw->mem_base) + if (NULL != ((void *)hw->mem_base)) iounmap((void *)hw->mem_base); hw->mem_base = (unsigned long)NULL; @@ -2011,7 +1972,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) hw_write_20kx(hw, GLOBAL_CNTL_GCTL, gctl); /* Reset all global pending interrupts */ - hw_write_20kx(hw, GIE, 0); + hw_write_20kx(hw, INTERRUPT_GIE, 0); /* Reset all SRC pending interrupts */ hw_write_20kx(hw, SRC_IP, 0); @@ -2188,10 +2149,6 @@ static struct hw ct20k2_preset __devinitdata = { .daio_mgr_set_imapnxt = daio_mgr_set_imapnxt, .daio_mgr_set_imapaddr = daio_mgr_set_imapaddr, .daio_mgr_commit_write = daio_mgr_commit_write, - - .set_timer_irq = set_timer_irq, - .set_timer_tick = set_timer_tick, - .get_wc = get_wc, }; int __devinit create_20k2_hw_obj(struct hw **rhw) diff --git a/trunk/sound/pci/ctxfi/ctmixer.c b/trunk/sound/pci/ctxfi/ctmixer.c index 15c1e7271ea8..f26d7cd9db9f 100644 --- a/trunk/sound/pci/ctxfi/ctmixer.c +++ b/trunk/sound/pci/ctxfi/ctmixer.c @@ -654,7 +654,7 @@ ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new) int err; kctl = snd_ctl_new1(new, mixer->atc); - if (!kctl) + if (NULL == kctl) return -ENOMEM; if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface) @@ -837,17 +837,17 @@ static int ct_mixer_get_mem(struct ct_mixer **rmixer) *rmixer = NULL; /* Allocate mem for mixer obj */ mixer = kzalloc(sizeof(*mixer), GFP_KERNEL); - if (!mixer) + if (NULL == mixer) return -ENOMEM; mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM), GFP_KERNEL); - if (!mixer->amixers) { + if (NULL == mixer->amixers) { err = -ENOMEM; goto error1; } mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL); - if (!mixer->sums) { + if (NULL == mixer->sums) { err = -ENOMEM; goto error2; } diff --git a/trunk/sound/pci/ctxfi/ctpcm.c b/trunk/sound/pci/ctxfi/ctpcm.c index d0dc227fbdd3..60ea23180acb 100644 --- a/trunk/sound/pci/ctxfi/ctpcm.c +++ b/trunk/sound/pci/ctxfi/ctpcm.c @@ -97,7 +97,7 @@ static void ct_atc_pcm_interrupt(struct ct_atc_pcm *atc_pcm) { struct ct_atc_pcm *apcm = atc_pcm; - if (!apcm->substream) + if (NULL == apcm->substream) return; snd_pcm_period_elapsed(apcm->substream); @@ -123,7 +123,7 @@ static int ct_pcm_playback_open(struct snd_pcm_substream *substream) int err; apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); - if (!apcm) + if (NULL == apcm) return -ENOMEM; apcm->substream = substream; @@ -271,7 +271,7 @@ static int ct_pcm_capture_open(struct snd_pcm_substream *substream) int err; apcm = kzalloc(sizeof(*apcm), GFP_KERNEL); - if (!apcm) + if (NULL == apcm) return -ENOMEM; apcm->started = 0; diff --git a/trunk/sound/pci/ctxfi/ctresource.c b/trunk/sound/pci/ctxfi/ctresource.c index 7dfaf67344d4..889c495bb7d1 100644 --- a/trunk/sound/pci/ctxfi/ctresource.c +++ b/trunk/sound/pci/ctxfi/ctresource.c @@ -144,7 +144,7 @@ int rsc_init(struct rsc *rsc, u32 idx, enum RSCTYP type, u32 msr, void *hw) rsc->msr = msr; rsc->hw = hw; rsc->ops = &rsc_generic_ops; - if (!hw) { + if (NULL == hw) { rsc->ctrl_blk = NULL; return 0; } @@ -216,7 +216,7 @@ int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type, mgr->type = NUM_RSCTYP; mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL); - if (!mgr->rscs) + if (NULL == mgr->rscs) return -ENOMEM; switch (type) { diff --git a/trunk/sound/pci/ctxfi/ctsrc.c b/trunk/sound/pci/ctxfi/ctsrc.c index c749fa720889..df43a5cd3938 100644 --- a/trunk/sound/pci/ctxfi/ctsrc.c +++ b/trunk/sound/pci/ctxfi/ctsrc.c @@ -441,7 +441,7 @@ get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc) else src = kzalloc(sizeof(*src), GFP_KERNEL); - if (!src) { + if (NULL == src) { err = -ENOMEM; goto error1; } @@ -550,7 +550,7 @@ int src_mgr_create(void *hw, struct src_mgr **rsrc_mgr) *rsrc_mgr = NULL; src_mgr = kzalloc(sizeof(*src_mgr), GFP_KERNEL); - if (!src_mgr) + if (NULL == src_mgr) return -ENOMEM; err = rsc_mgr_init(&src_mgr->mgr, SRC, SRC_RESOURCE_NUM, hw); @@ -679,7 +679,7 @@ static int srcimp_rsc_init(struct srcimp *srcimp, /* Reserve memory for imapper nodes */ srcimp->imappers = kzalloc(sizeof(struct imapper)*desc->msr, GFP_KERNEL); - if (!srcimp->imappers) { + if (NULL == srcimp->imappers) { err = -ENOMEM; goto error1; } @@ -833,7 +833,7 @@ int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr) *rsrcimp_mgr = NULL; srcimp_mgr = kzalloc(sizeof(*srcimp_mgr), GFP_KERNEL); - if (!srcimp_mgr) + if (NULL == srcimp_mgr) return -ENOMEM; err = rsc_mgr_init(&srcimp_mgr->mgr, SRCIMP, SRCIMP_RESOURCE_NUM, hw); @@ -844,7 +844,7 @@ int srcimp_mgr_create(void *hw, struct srcimp_mgr **rsrcimp_mgr) spin_lock_init(&srcimp_mgr->imap_lock); INIT_LIST_HEAD(&srcimp_mgr->imappers); entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { + if (NULL == entry) { err = -ENOMEM; goto error2; } diff --git a/trunk/sound/pci/ctxfi/ctvmem.c b/trunk/sound/pci/ctxfi/ctvmem.c index 6b78752e9503..67665a7e43c6 100644 --- a/trunk/sound/pci/ctxfi/ctvmem.c +++ b/trunk/sound/pci/ctxfi/ctvmem.c @@ -60,7 +60,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size) } block = kzalloc(sizeof(*block), GFP_KERNEL); - if (!block) + if (NULL == block) goto out; block->addr = entry->addr; @@ -181,7 +181,7 @@ int ct_vm_create(struct ct_vm **rvm) *rvm = NULL; vm = kzalloc(sizeof(*vm), GFP_KERNEL); - if (!vm) + if (NULL == vm) return -ENOMEM; mutex_init(&vm->lock); @@ -189,7 +189,7 @@ int ct_vm_create(struct ct_vm **rvm) /* Allocate page table pages */ for (i = 0; i < CT_PTP_NUM; i++) { vm->ptp[i] = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!vm->ptp[i]) + if (NULL == vm->ptp[i]) break; } if (!i) { diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 30eeb304351c..6f683e451f2b 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -6423,9 +6423,9 @@ static struct hda_verb alc885_mbp_ch2_init[] = { }; /* - * 4ch mode + * 6ch mode */ -static struct hda_verb alc885_mbp_ch4_init[] = { +static struct hda_verb alc885_mbp_ch6_init[] = { { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 }, @@ -6434,9 +6434,9 @@ static struct hda_verb alc885_mbp_ch4_init[] = { { } /* end */ }; -static struct hda_channel_mode alc885_mbp_4ch_modes[2] = { +static struct hda_channel_mode alc885_mbp_6ch_modes[2] = { { 2, alc885_mbp_ch2_init }, - { 4, alc885_mbp_ch4_init }, + { 6, alc885_mbp_ch6_init }, }; /* @@ -6497,11 +6497,10 @@ static struct snd_kcontrol_new alc882_base_mixer[] = { }; static struct snd_kcontrol_new alc885_mbp3_mixer[] = { - HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT), - HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT), + HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT), + HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT), + HDA_CODEC_MUTE ("Speaker Playback Switch", 0x14, 0x00, HDA_OUTPUT), + HDA_CODEC_VOLUME("Line-Out Playback Volume", 0x0d, 0x00, HDA_OUTPUT), HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT), @@ -6815,18 +6814,14 @@ static struct hda_verb alc885_mbp3_init_verbs[] = { {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, - /* HP mixer */ - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, - {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Front Pin: output 0 (0x0c) */ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, - /* HP Pin: output 0 (0x0e) */ + /* HP Pin: output 0 (0x0d) */ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, - {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, - {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, /* Mic (rear) pin: input vref at 80% */ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, @@ -7200,11 +7195,10 @@ static struct alc_config_preset alc882_presets[] = { .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer }, .init_verbs = { alc885_mbp3_init_verbs, alc880_gpio1_init_verbs }, - .num_dacs = 2, + .num_dacs = ARRAY_SIZE(alc882_dac_nids), .dac_nids = alc882_dac_nids, - .hp_nid = 0x04, - .channel_mode = alc885_mbp_4ch_modes, - .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes), + .channel_mode = alc885_mbp_6ch_modes, + .num_channel_mode = ARRAY_SIZE(alc885_mbp_6ch_modes), .input_mux = &alc882_capture_source, .dig_out_nid = ALC882_DIGOUT_NID, .dig_in_nid = ALC882_DIGIN_NID, diff --git a/trunk/sound/pci/hda/patch_via.c b/trunk/sound/pci/hda/patch_via.c index e8f10b10cceb..9008b4b013aa 100644 --- a/trunk/sound/pci/hda/patch_via.c +++ b/trunk/sound/pci/hda/patch_via.c @@ -1395,7 +1395,6 @@ static int patch_vt1708(struct hda_codec *codec) if (!spec->adc_nids && spec->input_mux) { spec->adc_nids = vt1708_adc_nids; spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids); - get_mux_nids(codec); spec->mixers[spec->num_mixers] = vt1708_capture_mixer; spec->num_mixers++; } diff --git a/trunk/sound/pci/oxygen/oxygen_lib.c b/trunk/sound/pci/oxygen/oxygen_lib.c index 9a8936e20744..312251d39696 100644 --- a/trunk/sound/pci/oxygen/oxygen_lib.c +++ b/trunk/sound/pci/oxygen/oxygen_lib.c @@ -260,9 +260,6 @@ oxygen_search_pci_id(struct oxygen *chip, const struct pci_device_id ids[]) * chip didn't if the first EEPROM word was overwritten. */ subdevice = oxygen_read_eeprom(chip, 2); - /* use default ID if EEPROM is missing */ - if (subdevice == 0xffff) - subdevice = 0x8788; /* * We use only the subsystem device ID for searching because it is * unique even without the subsystem vendor ID, which may have been diff --git a/trunk/sound/pci/oxygen/oxygen_pcm.c b/trunk/sound/pci/oxygen/oxygen_pcm.c index ef2345d82b86..3b5ca70c9d4d 100644 --- a/trunk/sound/pci/oxygen/oxygen_pcm.c +++ b/trunk/sound/pci/oxygen/oxygen_pcm.c @@ -469,11 +469,9 @@ static int oxygen_multich_hw_params(struct snd_pcm_substream *substream, oxygen_write16_masked(chip, OXYGEN_I2S_MULTICH_FORMAT, oxygen_rate(hw_params) | chip->model.dac_i2s_format | - oxygen_i2s_mclk(hw_params) | oxygen_i2s_bits(hw_params), OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_FORMAT_MASK | - OXYGEN_I2S_MCLK_MASK | OXYGEN_I2S_BITS_MASK); oxygen_update_dac_routing(chip); oxygen_update_spdif_source(chip); diff --git a/trunk/sound/soc/Kconfig b/trunk/sound/soc/Kconfig index b1749bc67979..d3e786a9a0a7 100644 --- a/trunk/sound/soc/Kconfig +++ b/trunk/sound/soc/Kconfig @@ -29,7 +29,6 @@ source "sound/soc/au1x/Kconfig" source "sound/soc/blackfin/Kconfig" source "sound/soc/davinci/Kconfig" source "sound/soc/fsl/Kconfig" -source "sound/soc/imx/Kconfig" source "sound/soc/omap/Kconfig" source "sound/soc/pxa/Kconfig" source "sound/soc/s3c24xx/Kconfig" diff --git a/trunk/sound/soc/Makefile b/trunk/sound/soc/Makefile index 0c5eac01bf2e..6f1e28de23cf 100644 --- a/trunk/sound/soc/Makefile +++ b/trunk/sound/soc/Makefile @@ -1,4 +1,4 @@ -snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o +snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ @@ -7,7 +7,6 @@ obj-$(CONFIG_SND_SOC) += au1x/ obj-$(CONFIG_SND_SOC) += blackfin/ obj-$(CONFIG_SND_SOC) += davinci/ obj-$(CONFIG_SND_SOC) += fsl/ -obj-$(CONFIG_SND_SOC) += imx/ obj-$(CONFIG_SND_SOC) += omap/ obj-$(CONFIG_SND_SOC) += pxa/ obj-$(CONFIG_SND_SOC) += s3c24xx/ diff --git a/trunk/sound/soc/atmel/sam9g20_wm8731.c b/trunk/sound/soc/atmel/sam9g20_wm8731.c index 130b12118d4f..173a239a541c 100644 --- a/trunk/sound/soc/atmel/sam9g20_wm8731.c +++ b/trunk/sound/soc/atmel/sam9g20_wm8731.c @@ -56,32 +56,133 @@ #define MCLK_RATE 12000000 -/* - * As shipped the board does not have inputs. However, it is relatively - * straightforward to modify the board to hook them up so support is left - * in the driver. - */ -#undef ENABLE_MIC_INPUT - static struct clk *mclk; +static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; + int ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, + MCLK_RATE, SND_SOC_CLOCK_IN); + if (ret < 0) { + clk_disable(mclk); + return ret; + } + + return 0; +} + +static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); + + dev_dbg(rtd->socdev->dev, "shutdown"); +} + static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct atmel_ssc_info *ssc_p = cpu_dai->private_data; + struct ssc_device *ssc = ssc_p->ssc; int ret; + unsigned int rate; + int cmr_div, period; + + if (ssc == NULL) { + printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n"); + return -EINVAL; + } + /* set codec DAI configuration */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) return ret; /* set cpu DAI configuration */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); + if (ret < 0) + return ret; + + /* + * The SSC clock dividers depend on the sample rate. The CMR.DIV + * field divides the system master clock MCK to drive the SSC TK + * signal which provides the codec BCLK. The TCMR.PERIOD and + * RCMR.PERIOD fields further divide the BCLK signal to drive + * the SSC TF and RF signals which provide the codec DACLRC and + * ADCLRC clocks. + * + * The dividers were determined through trial and error, where a + * CMR.DIV value is chosen such that the resulting BCLK value is + * divisible, or almost divisible, by (2 * sample rate), and then + * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1. + */ + rate = params_rate(params); + + switch (rate) { + case 8000: + cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */ + period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */ + break; + case 11025: + cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */ + period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */ + break; + case 16000: + cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */ + period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */ + break; + case 22050: + cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */ + period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */ + break; + case 32000: + cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */ + period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */ + break; + case 44100: + cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */ + period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */ + break; + case 48000: + cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */ + period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */ + break; + case 88200: + cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */ + period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */ + break; + case 96000: + cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */ + period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */ + break; + default: + printk(KERN_WARNING "unsupported rate %d" + " on at91sam9g20ek board\n", rate); + return -EINVAL; + } + + /* set the MCK divider for BCLK */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div); + if (ret < 0) + return ret; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* set the BCLK divider for DACLRC */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, + ATMEL_SSC_TCMR_PERIOD, period); + } else { + /* set the BCLK divider for ADCLRC */ + ret = snd_soc_dai_set_clkdiv(cpu_dai, + ATMEL_SSC_RCMR_PERIOD, period); + } if (ret < 0) return ret; @@ -89,7 +190,9 @@ static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, } static struct snd_soc_ops at91sam9g20ek_ops = { + .startup = at91sam9g20ek_startup, .hw_params = at91sam9g20ek_hw_params, + .shutdown = at91sam9g20ek_shutdown, }; static int at91sam9g20ek_set_bias_level(struct snd_soc_card *card, @@ -138,20 +241,10 @@ static const struct snd_soc_dapm_route intercon[] = { */ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) { - struct snd_soc_dai *codec_dai = &codec->dai[0]; - int ret; - printk(KERN_DEBUG "at91sam9g20ek_wm8731 " ": at91sam9g20ek_wm8731_init() called\n"); - ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, - MCLK_RATE, SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Failed to set WM8731 SYSCLK: %d\n", ret); - return ret; - } - /* Add specific widgets */ snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets, ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); @@ -162,13 +255,8 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) snd_soc_dapm_nc_pin(codec, "RLINEIN"); snd_soc_dapm_nc_pin(codec, "LLINEIN"); -#ifdef ENABLE_MIC_INPUT - snd_soc_dapm_enable_pin(codec, "Int Mic"); -#else - snd_soc_dapm_nc_pin(codec, "Int Mic"); -#endif - /* always connected */ + snd_soc_dapm_enable_pin(codec, "Int Mic"); snd_soc_dapm_enable_pin(codec, "Ext Spk"); snd_soc_dapm_sync(codec); diff --git a/trunk/sound/soc/au1x/psc-ac97.c b/trunk/sound/soc/au1x/psc-ac97.c index a521aa90ddee..479d7bdf1865 100644 --- a/trunk/sound/soc/au1x/psc-ac97.c +++ b/trunk/sound/soc/au1x/psc-ac97.c @@ -1,8 +1,8 @@ /* * Au12x0/Au1550 PSC ALSA ASoC audio support. * - * (c) 2007-2009 MSC Vertriebsges.m.b.H., - * Manuel Lauss + * (c) 2007-2008 MSC Vertriebsges.m.b.H., + * Manuel Lauss * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -30,9 +29,6 @@ #include "psc.h" -/* how often to retry failed codec register reads/writes */ -#define AC97_RW_RETRIES 5 - #define AC97_DIR \ (SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE) @@ -49,9 +45,6 @@ #define AC97PCR_CLRFIFO(stype) \ ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC) -#define AC97STAT_BUSY(stype) \ - ((stype) == PCM_TX ? PSC_AC97STAT_TB : PSC_AC97STAT_RB) - /* instance data. There can be only one, MacLeod!!!! */ static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; @@ -61,33 +54,24 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, { /* FIXME */ struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; - unsigned short data, retry, tmo; + unsigned short data, tmo; - au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); + au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg), AC97_CDC(pscdata)); au_sync(); - retry = AC97_RW_RETRIES; - do { - mutex_lock(&pscdata->lock); - - au_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg), - AC97_CDC(pscdata)); - au_sync(); - - tmo = 2000; - while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) - && --tmo) - udelay(2); + tmo = 1000; + while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo) + udelay(2); + if (!tmo) + data = 0xffff; + else data = au_readl(AC97_CDC(pscdata)) & 0xffff; - au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); - au_sync(); - - mutex_unlock(&pscdata->lock); - } while (--retry && !tmo); + au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); + au_sync(); - return retry ? data : 0xffff; + return data; } /* AC97 controller writes to codec register */ @@ -96,29 +80,16 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, { /* FIXME */ struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; - unsigned int tmo, retry; + unsigned int tmo; - au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); + au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff), AC97_CDC(pscdata)); au_sync(); - - retry = AC97_RW_RETRIES; - do { - mutex_lock(&pscdata->lock); - - au_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff), - AC97_CDC(pscdata)); + tmo = 1000; + while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) && --tmo) au_sync(); - tmo = 2000; - while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) - && --tmo) - udelay(2); - - au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); - au_sync(); - - mutex_unlock(&pscdata->lock); - } while (--retry && !tmo); + au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); + au_sync(); } /* AC97 controller asserts a warm reset */ @@ -158,9 +129,9 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) au_sync(); /* wait for PSC to indicate it's ready */ - i = 1000; + i = 100000; while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i)) - msleep(1); + au_sync(); if (i == 0) { printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n"); @@ -172,9 +143,9 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) au_sync(); /* wait for AC97 core to become ready */ - i = 1000; + i = 100000; while (!((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i)) - msleep(1); + au_sync(); if (i == 0) printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n"); } @@ -194,12 +165,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, { /* FIXME */ struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; - unsigned long r, ro, stat; + unsigned long r, stat; int chans, stype = SUBSTREAM_TYPE(substream); chans = params_channels(params); - r = ro = au_readl(AC97_CFG(pscdata)); + r = au_readl(AC97_CFG(pscdata)); stat = au_readl(AC97_STAT(pscdata)); /* already active? */ @@ -209,6 +180,9 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, (pscdata->rate != params_rate(params))) return -EINVAL; } else { + /* disable AC97 device controller first */ + au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata)); + au_sync(); /* set sample bitdepth: REG[24:21]=(BITS-2)/2 */ r &= ~PSC_AC97CFG_LEN_MASK; @@ -225,40 +199,14 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, r |= PSC_AC97CFG_RXSLOT_ENA(4); } - /* do we need to poke the hardware? */ - if (!(r ^ ro)) - goto out; - - /* ac97 engine is about to be disabled */ - mutex_lock(&pscdata->lock); - - /* disable AC97 device controller first... */ - au_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata)); - au_sync(); - - /* ...wait for it... */ - while (au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) - asm volatile ("nop"); - - /* ...write config... */ - au_writel(r, AC97_CFG(pscdata)); - au_sync(); - - /* ...enable the AC97 controller again... */ + /* finally enable the AC97 controller again */ au_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata)); au_sync(); - /* ...and wait for ready bit */ - while (!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) - asm volatile ("nop"); - - mutex_unlock(&pscdata->lock); - pscdata->cfg = r; pscdata->rate = params_rate(params); } -out: return 0; } @@ -274,8 +222,6 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: - au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata)); - au_sync(); au_writel(AC97PCR_START(stype), AC97_PCR(pscdata)); au_sync(); break; @@ -283,13 +229,6 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, case SNDRV_PCM_TRIGGER_SUSPEND: au_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata)); au_sync(); - - while (au_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype)) - asm volatile ("nop"); - - au_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata)); - au_sync(); - break; default: ret = -EINVAL; @@ -312,8 +251,6 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev, if (!au1xpsc_ac97_workdata) return -ENOMEM; - mutex_init(&au1xpsc_ac97_workdata->lock); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { ret = -ENODEV; @@ -332,9 +269,9 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev, goto out1; /* configuration: max dma trigger threshold, enable ac97 */ - au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 | - PSC_AC97CFG_TT_FIFO8 | - PSC_AC97CFG_DE_ENABLE; + au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 | + PSC_AC97CFG_TT_FIFO8 | + PSC_AC97CFG_DE_ENABLE; /* preserve PSC clock source set up by platform (dev.platform_data * is already occupied by soc layer) @@ -449,4 +386,4 @@ module_exit(au1xpsc_ac97_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); -MODULE_AUTHOR("Manuel Lauss "); +MODULE_AUTHOR("Manuel Lauss "); diff --git a/trunk/sound/soc/au1x/psc.h b/trunk/sound/soc/au1x/psc.h index 3f474e8ed4f6..8fdb1a04a07b 100644 --- a/trunk/sound/soc/au1x/psc.h +++ b/trunk/sound/soc/au1x/psc.h @@ -29,7 +29,6 @@ struct au1xpsc_audio_data { unsigned long pm[2]; struct resource *ioarea; - struct mutex lock; }; #define PCM_TX 0 diff --git a/trunk/sound/soc/blackfin/Kconfig b/trunk/sound/soc/blackfin/Kconfig index ac927ffdc961..811596f4c092 100644 --- a/trunk/sound/soc/blackfin/Kconfig +++ b/trunk/sound/soc/blackfin/Kconfig @@ -7,15 +7,6 @@ config SND_BF5XX_I2S mode (supports single stereo In/Out). You will also need to select the audio interfaces to support below. -config SND_BF5XX_TDM - tristate "SoC I2S(TDM mode) Audio for the ADI BF5xx chip" - depends on (BLACKFIN && SND_SOC) - help - Say Y or M if you want to add support for codecs attached to - the Blackfin SPORT (synchronous serial ports) interface in TDM - mode. - You will also need to select the audio interfaces to support below. - config SND_BF5XX_SOC_SSM2602 tristate "SoC SSM2602 Audio support for BF52x ezkit" depends on SND_BF5XX_I2S @@ -78,24 +69,12 @@ config SND_BF5XX_SOC_I2S tristate select SND_BF5XX_SOC_SPORT -config SND_BF5XX_SOC_TDM - tristate - select SND_BF5XX_SOC_SPORT - config SND_BF5XX_SOC_AC97 tristate select AC97_BUS select SND_SOC_AC97_BUS select SND_BF5XX_SOC_SPORT -config SND_BF5XX_SOC_AD1836 - tristate "SoC AD1836 Audio support for BF5xx" - depends on SND_BF5XX_TDM - select SND_BF5XX_SOC_TDM - select SND_SOC_AD1836 - help - Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. - config SND_BF5XX_SOC_AD1980 tristate "SoC AD1980/1 Audio support for BF5xx" depends on SND_BF5XX_AC97 @@ -104,17 +83,9 @@ config SND_BF5XX_SOC_AD1980 help Say Y if you want to add support for SoC audio on BF5xx STAMP/EZKIT. -config SND_BF5XX_SOC_AD1938 - tristate "SoC AD1938 Audio support for Blackfin" - depends on SND_BF5XX_TDM - select SND_BF5XX_SOC_TDM - select SND_SOC_AD1938 - help - Say Y if you want to add support for AD1938 codec on Blackfin. - config SND_BF5XX_SPORT_NUM int "Set a SPORT for Sound chip" - depends on (SND_BF5XX_I2S || SND_BF5XX_AC97 || SND_BF5XX_TDM) + depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) range 0 3 if BF54x range 0 1 if !BF54x default 0 diff --git a/trunk/sound/soc/blackfin/Makefile b/trunk/sound/soc/blackfin/Makefile index 87e30423912f..97bb37a6359c 100644 --- a/trunk/sound/soc/blackfin/Makefile +++ b/trunk/sound/soc/blackfin/Makefile @@ -1,29 +1,21 @@ # Blackfin Platform Support snd-bf5xx-ac97-objs := bf5xx-ac97-pcm.o snd-bf5xx-i2s-objs := bf5xx-i2s-pcm.o -snd-bf5xx-tdm-objs := bf5xx-tdm-pcm.o snd-soc-bf5xx-sport-objs := bf5xx-sport.o snd-soc-bf5xx-ac97-objs := bf5xx-ac97.o snd-soc-bf5xx-i2s-objs := bf5xx-i2s.o -snd-soc-bf5xx-tdm-objs := bf5xx-tdm.o obj-$(CONFIG_SND_BF5XX_AC97) += snd-bf5xx-ac97.o obj-$(CONFIG_SND_BF5XX_I2S) += snd-bf5xx-i2s.o -obj-$(CONFIG_SND_BF5XX_TDM) += snd-bf5xx-tdm.o obj-$(CONFIG_SND_BF5XX_SOC_SPORT) += snd-soc-bf5xx-sport.o obj-$(CONFIG_SND_BF5XX_SOC_AC97) += snd-soc-bf5xx-ac97.o obj-$(CONFIG_SND_BF5XX_SOC_I2S) += snd-soc-bf5xx-i2s.o -obj-$(CONFIG_SND_BF5XX_SOC_TDM) += snd-soc-bf5xx-tdm.o # Blackfin Machine Support -snd-ad1836-objs := bf5xx-ad1836.o snd-ad1980-objs := bf5xx-ad1980.o snd-ssm2602-objs := bf5xx-ssm2602.o snd-ad73311-objs := bf5xx-ad73311.o -snd-ad1938-objs := bf5xx-ad1938.o -obj-$(CONFIG_SND_BF5XX_SOC_AD1836) += snd-ad1836.o obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o -obj-$(CONFIG_SND_BF5XX_SOC_AD1938) += snd-ad1938.o diff --git a/trunk/sound/soc/blackfin/bf5xx-ac97.c b/trunk/sound/soc/blackfin/bf5xx-ac97.c index 2758b9017a7f..b1ed423fabd5 100644 --- a/trunk/sound/soc/blackfin/bf5xx-ac97.c +++ b/trunk/sound/soc/blackfin/bf5xx-ac97.c @@ -277,24 +277,28 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) if (!dai->active) return 0; - ret = sport_set_multichannel(sport, 16, 0x1F, 1); + ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } - ret = sport_config_rx(sport, IRFS, 0xF, 0, (16*16-1)); + ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } - ret = sport_config_tx(sport, ITFS, 0xF, 0, (16*16-1)); + ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } + if (dai->capture.active) + sport_rx_start(sport); + if (dai->playback.active) + sport_tx_start(sport); return 0; } diff --git a/trunk/sound/soc/blackfin/bf5xx-ad1836.c b/trunk/sound/soc/blackfin/bf5xx-ad1836.c deleted file mode 100644 index cd361e304b0f..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-ad1836.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ad1836.c - * Author: Barry Song - * - * Created: Aug 4 2009 - * Description: Board driver for ad1836 sound chip - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../codecs/ad1836.h" -#include "bf5xx-sport.h" - -#include "bf5xx-tdm-pcm.h" -#include "bf5xx-tdm.h" - -static struct snd_soc_card bf5xx_ad1836; - -static int bf5xx_ad1836_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - - cpu_dai->private_data = sport_handle; - return 0; -} - -static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - int ret = 0; - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops bf5xx_ad1836_ops = { - .startup = bf5xx_ad1836_startup, - .hw_params = bf5xx_ad1836_hw_params, -}; - -static struct snd_soc_dai_link bf5xx_ad1836_dai = { - .name = "ad1836", - .stream_name = "AD1836", - .cpu_dai = &bf5xx_tdm_dai, - .codec_dai = &ad1836_dai, - .ops = &bf5xx_ad1836_ops, -}; - -static struct snd_soc_card bf5xx_ad1836 = { - .name = "bf5xx_ad1836", - .platform = &bf5xx_tdm_soc_platform, - .dai_link = &bf5xx_ad1836_dai, - .num_links = 1, -}; - -static struct snd_soc_device bf5xx_ad1836_snd_devdata = { - .card = &bf5xx_ad1836, - .codec_dev = &soc_codec_dev_ad1836, -}; - -static struct platform_device *bfxx_ad1836_snd_device; - -static int __init bf5xx_ad1836_init(void) -{ - int ret; - - bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1); - if (!bfxx_ad1836_snd_device) - return -ENOMEM; - - platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836_snd_devdata); - bf5xx_ad1836_snd_devdata.dev = &bfxx_ad1836_snd_device->dev; - ret = platform_device_add(bfxx_ad1836_snd_device); - - if (ret) - platform_device_put(bfxx_ad1836_snd_device); - - return ret; -} - -static void __exit bf5xx_ad1836_exit(void) -{ - platform_device_unregister(bfxx_ad1836_snd_device); -} - -module_init(bf5xx_ad1836_init); -module_exit(bf5xx_ad1836_exit); - -/* Module information */ -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("ALSA SoC AD1836 board driver"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/blackfin/bf5xx-ad1938.c b/trunk/sound/soc/blackfin/bf5xx-ad1938.c deleted file mode 100644 index 08269e91810c..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-ad1938.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-ad1938.c - * Author: Barry Song - * - * Created: Thur June 4 2009 - * Description: Board driver for ad1938 sound chip - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../codecs/ad1938.h" -#include "bf5xx-sport.h" - -#include "bf5xx-tdm-pcm.h" -#include "bf5xx-tdm.h" - -static struct snd_soc_card bf5xx_ad1938; - -static int bf5xx_ad1938_startup(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - - cpu_dai->private_data = sport_handle; - return 0; -} - -static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - int ret = 0; - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set codec DAI slots, 8 channels, all channels are enabled */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8); - if (ret < 0) - return ret; - - return 0; -} - -static struct snd_soc_ops bf5xx_ad1938_ops = { - .startup = bf5xx_ad1938_startup, - .hw_params = bf5xx_ad1938_hw_params, -}; - -static struct snd_soc_dai_link bf5xx_ad1938_dai = { - .name = "ad1938", - .stream_name = "AD1938", - .cpu_dai = &bf5xx_tdm_dai, - .codec_dai = &ad1938_dai, - .ops = &bf5xx_ad1938_ops, -}; - -static struct snd_soc_card bf5xx_ad1938 = { - .name = "bf5xx_ad1938", - .platform = &bf5xx_tdm_soc_platform, - .dai_link = &bf5xx_ad1938_dai, - .num_links = 1, -}; - -static struct snd_soc_device bf5xx_ad1938_snd_devdata = { - .card = &bf5xx_ad1938, - .codec_dev = &soc_codec_dev_ad1938, -}; - -static struct platform_device *bfxx_ad1938_snd_device; - -static int __init bf5xx_ad1938_init(void) -{ - int ret; - - bfxx_ad1938_snd_device = platform_device_alloc("soc-audio", -1); - if (!bfxx_ad1938_snd_device) - return -ENOMEM; - - platform_set_drvdata(bfxx_ad1938_snd_device, &bf5xx_ad1938_snd_devdata); - bf5xx_ad1938_snd_devdata.dev = &bfxx_ad1938_snd_device->dev; - ret = platform_device_add(bfxx_ad1938_snd_device); - - if (ret) - platform_device_put(bfxx_ad1938_snd_device); - - return ret; -} - -static void __exit bf5xx_ad1938_exit(void) -{ - platform_device_unregister(bfxx_ad1938_snd_device); -} - -module_init(bf5xx_ad1938_init); -module_exit(bf5xx_ad1938_exit); - -/* Module information */ -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("ALSA SoC AD1938 board driver"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/blackfin/bf5xx-ad73311.c b/trunk/sound/soc/blackfin/bf5xx-ad73311.c index 9825b71d0e28..edfbdc024e66 100644 --- a/trunk/sound/soc/blackfin/bf5xx-ad73311.c +++ b/trunk/sound/soc/blackfin/bf5xx-ad73311.c @@ -203,23 +203,23 @@ static struct snd_soc_device bf5xx_ad73311_snd_devdata = { .codec_dev = &soc_codec_dev_ad73311, }; -static struct platform_device *bf5xx_ad73311_snd_device; +static struct platform_device *bf52x_ad73311_snd_device; static int __init bf5xx_ad73311_init(void) { int ret; pr_debug("%s enter\n", __func__); - bf5xx_ad73311_snd_device = platform_device_alloc("soc-audio", -1); - if (!bf5xx_ad73311_snd_device) + bf52x_ad73311_snd_device = platform_device_alloc("soc-audio", -1); + if (!bf52x_ad73311_snd_device) return -ENOMEM; - platform_set_drvdata(bf5xx_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); - bf5xx_ad73311_snd_devdata.dev = &bf5xx_ad73311_snd_device->dev; - ret = platform_device_add(bf5xx_ad73311_snd_device); + platform_set_drvdata(bf52x_ad73311_snd_device, &bf5xx_ad73311_snd_devdata); + bf5xx_ad73311_snd_devdata.dev = &bf52x_ad73311_snd_device->dev; + ret = platform_device_add(bf52x_ad73311_snd_device); if (ret) - platform_device_put(bf5xx_ad73311_snd_device); + platform_device_put(bf52x_ad73311_snd_device); return ret; } @@ -227,7 +227,7 @@ static int __init bf5xx_ad73311_init(void) static void __exit bf5xx_ad73311_exit(void) { pr_debug("%s enter\n", __func__); - platform_device_unregister(bf5xx_ad73311_snd_device); + platform_device_unregister(bf52x_ad73311_snd_device); } module_init(bf5xx_ad73311_init); diff --git a/trunk/sound/soc/blackfin/bf5xx-i2s.c b/trunk/sound/soc/blackfin/bf5xx-i2s.c index 876abade27e1..af06904bab0f 100644 --- a/trunk/sound/soc/blackfin/bf5xx-i2s.c +++ b/trunk/sound/soc/blackfin/bf5xx-i2s.c @@ -259,18 +259,22 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai) if (!dai->active) return 0; - ret = sport_config_rx(sport, RFSR | RCKFE, RSFSE|0x1f, 0, 0); + ret = sport_config_rx(sport_handle, RFSR | RCKFE, RSFSE|0x1f, 0, 0); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } - ret = sport_config_tx(sport, TFSR | TCKFE, TSFSE|0x1f, 0, 0); + ret = sport_config_tx(sport_handle, TFSR | TCKFE, TSFSE|0x1f, 0, 0); if (ret) { pr_err("SPORT is busy!\n"); return -EBUSY; } + if (dai->capture.active) + sport_rx_start(sport); + if (dai->playback.active) + sport_tx_start(sport); return 0; } diff --git a/trunk/sound/soc/blackfin/bf5xx-ssm2602.c b/trunk/sound/soc/blackfin/bf5xx-ssm2602.c index 3a00fa4dbe6d..bc0cdded7116 100644 --- a/trunk/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/trunk/sound/soc/blackfin/bf5xx-ssm2602.c @@ -148,24 +148,24 @@ static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { .codec_data = &bf5xx_ssm2602_setup, }; -static struct platform_device *bf5xx_ssm2602_snd_device; +static struct platform_device *bf52x_ssm2602_snd_device; static int __init bf5xx_ssm2602_init(void) { int ret; pr_debug("%s enter\n", __func__); - bf5xx_ssm2602_snd_device = platform_device_alloc("soc-audio", -1); - if (!bf5xx_ssm2602_snd_device) + bf52x_ssm2602_snd_device = platform_device_alloc("soc-audio", -1); + if (!bf52x_ssm2602_snd_device) return -ENOMEM; - platform_set_drvdata(bf5xx_ssm2602_snd_device, + platform_set_drvdata(bf52x_ssm2602_snd_device, &bf5xx_ssm2602_snd_devdata); - bf5xx_ssm2602_snd_devdata.dev = &bf5xx_ssm2602_snd_device->dev; - ret = platform_device_add(bf5xx_ssm2602_snd_device); + bf5xx_ssm2602_snd_devdata.dev = &bf52x_ssm2602_snd_device->dev; + ret = platform_device_add(bf52x_ssm2602_snd_device); if (ret) - platform_device_put(bf5xx_ssm2602_snd_device); + platform_device_put(bf52x_ssm2602_snd_device); return ret; } @@ -173,7 +173,7 @@ static int __init bf5xx_ssm2602_init(void) static void __exit bf5xx_ssm2602_exit(void) { pr_debug("%s enter\n", __func__); - platform_device_unregister(bf5xx_ssm2602_snd_device); + platform_device_unregister(bf52x_ssm2602_snd_device); } module_init(bf5xx_ssm2602_init); diff --git a/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c b/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c deleted file mode 100644 index ccb5e823bd18..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-tdm-pcm.c - * Author: Barry Song - * - * Created: Tue June 06 2009 - * Description: DMA driver for tdm codec - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "bf5xx-tdm-pcm.h" -#include "bf5xx-tdm.h" -#include "bf5xx-sport.h" - -#define PCM_BUFFER_MAX 0x10000 -#define FRAGMENT_SIZE_MIN (4*1024) -#define FRAGMENTS_MIN 2 -#define FRAGMENTS_MAX 32 - -static void bf5xx_dma_irq(void *data) -{ - struct snd_pcm_substream *pcm = data; - snd_pcm_period_elapsed(pcm); -} - -static const struct snd_pcm_hardware bf5xx_pcm_hardware = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_RESUME), - .formats = SNDRV_PCM_FMTBIT_S32_LE, - .rates = SNDRV_PCM_RATE_48000, - .channels_min = 2, - .channels_max = 8, - .buffer_bytes_max = PCM_BUFFER_MAX, - .period_bytes_min = FRAGMENT_SIZE_MIN, - .period_bytes_max = PCM_BUFFER_MAX/2, - .periods_min = FRAGMENTS_MIN, - .periods_max = FRAGMENTS_MAX, -}; - -static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - size_t size = bf5xx_pcm_hardware.buffer_bytes_max; - snd_pcm_lib_malloc_pages(substream, size * 4); - - return 0; -} - -static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) -{ - snd_pcm_lib_free_pages(substream); - - return 0; -} - -static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int fragsize_bytes = frames_to_bytes(runtime, runtime->period_size); - - fragsize_bytes /= runtime->channels; - /* inflate the fragsize to match the dma width of SPORT */ - fragsize_bytes *= 8; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - sport_set_tx_callback(sport, bf5xx_dma_irq, substream); - sport_config_tx_dma(sport, runtime->dma_area, - runtime->periods, fragsize_bytes); - } else { - sport_set_rx_callback(sport, bf5xx_dma_irq, substream); - sport_config_rx_dma(sport, runtime->dma_area, - runtime->periods, fragsize_bytes); - } - - return 0; -} - -static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_tx_start(sport); - else - sport_rx_start(sport); - break; - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_tx_stop(sport); - else - sport_rx_stop(sport); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct sport_device *sport = runtime->private_data; - unsigned int diff; - snd_pcm_uframes_t frames; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - diff = sport_curr_offset_tx(sport); - frames = diff / (8*4); /* 32 bytes per frame */ - } else { - diff = sport_curr_offset_rx(sport); - frames = diff / (8*4); - } - return frames; -} - -static int bf5xx_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret = 0; - - snd_soc_set_runtime_hwparams(substream, &bf5xx_pcm_hardware); - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - goto out; - - if (sport_handle != NULL) - runtime->private_data = sport_handle; - else { - pr_err("sport_handle is NULL\n"); - ret = -ENODEV; - } -out: - return ret; -} - -static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, - snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) -{ - unsigned int *src; - unsigned int *dst; - int i; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - src = buf; - dst = (unsigned int *)substream->runtime->dma_area; - - dst += pos * 8; - while (count--) { - for (i = 0; i < substream->runtime->channels; i++) - *(dst + i) = *src++; - dst += 8; - } - } else { - src = (unsigned int *)substream->runtime->dma_area; - dst = buf; - - src += pos * 8; - while (count--) { - for (i = 0; i < substream->runtime->channels; i++) - *dst++ = *(src+i); - src += 8; - } - } - - return 0; -} - -static int bf5xx_pcm_silence(struct snd_pcm_substream *substream, - int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count) -{ - unsigned char *buf = substream->runtime->dma_area; - buf += pos * 8 * 4; - memset(buf, '\0', count * 8 * 4); - - return 0; -} - - -struct snd_pcm_ops bf5xx_pcm_tdm_ops = { - .open = bf5xx_pcm_open, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = bf5xx_pcm_hw_params, - .hw_free = bf5xx_pcm_hw_free, - .prepare = bf5xx_pcm_prepare, - .trigger = bf5xx_pcm_trigger, - .pointer = bf5xx_pcm_pointer, - .copy = bf5xx_pcm_copy, - .silence = bf5xx_pcm_silence, -}; - -static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = bf5xx_pcm_hardware.buffer_bytes_max; - - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - buf->area = dma_alloc_coherent(pcm->card->dev, size * 4, - &buf->addr, GFP_KERNEL); - if (!buf->area) { - pr_err("Failed to allocate dma memory \ - Please increase uncached DMA memory region\n"); - return -ENOMEM; - } - buf->bytes = size; - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - sport_handle->tx_buf = buf->area; - else - sport_handle->rx_buf = buf->area; - - return 0; -} - -static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - dma_free_coherent(NULL, buf->bytes, buf->area, 0); - buf->area = NULL; - } - if (sport_handle) - sport_done(sport_handle); -} - -static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32); - -static int bf5xx_pcm_tdm_new(struct snd_card *card, struct snd_soc_dai *dai, - struct snd_pcm *pcm) -{ - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &bf5xx_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(32); - - if (dai->playback.channels_min) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret) - goto out; - } - - if (dai->capture.channels_min) { - ret = bf5xx_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - if (ret) - goto out; - } -out: - return ret; -} - -struct snd_soc_platform bf5xx_tdm_soc_platform = { - .name = "bf5xx-audio", - .pcm_ops = &bf5xx_pcm_tdm_ops, - .pcm_new = bf5xx_pcm_tdm_new, - .pcm_free = bf5xx_pcm_free_dma_buffers, -}; -EXPORT_SYMBOL_GPL(bf5xx_tdm_soc_platform); - -static int __init bfin_pcm_tdm_init(void) -{ - return snd_soc_register_platform(&bf5xx_tdm_soc_platform); -} -module_init(bfin_pcm_tdm_init); - -static void __exit bfin_pcm_tdm_exit(void) -{ - snd_soc_unregister_platform(&bf5xx_tdm_soc_platform); -} -module_exit(bfin_pcm_tdm_exit); - -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.h b/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.h deleted file mode 100644 index ddc5047df88c..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-tdm-pcm.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-tdm-pcm.h -- ALSA PCM interface for the Blackfin - * - * Copyright 2009 Analog Device Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_TDM_PCM_H -#define _BF5XX_TDM_PCM_H - -struct bf5xx_pcm_dma_params { - char *name; /* stream identifier */ -}; - -/* platform data */ -extern struct snd_soc_platform bf5xx_tdm_soc_platform; - -#endif diff --git a/trunk/sound/soc/blackfin/bf5xx-tdm.c b/trunk/sound/soc/blackfin/bf5xx-tdm.c deleted file mode 100644 index 3096badf09a5..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-tdm.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - * File: sound/soc/blackfin/bf5xx-tdm.c - * Author: Barry Song - * - * Created: Thurs June 04 2009 - * Description: Blackfin I2S(TDM) CPU DAI driver - * Even though TDM mode can be as part of I2S DAI, but there - * are so much difference in configuration and data flow, - * it's very ugly to integrate I2S and TDM into a module - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "bf5xx-sport.h" -#include "bf5xx-tdm.h" - -struct bf5xx_tdm_port { - u16 tcr1; - u16 rcr1; - u16 tcr2; - u16 rcr2; - int configured; -}; - -static struct bf5xx_tdm_port bf5xx_tdm; -static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; - -static struct sport_param sport_params[2] = { - { - .dma_rx_chan = CH_SPORT0_RX, - .dma_tx_chan = CH_SPORT0_TX, - .err_irq = IRQ_SPORT0_ERROR, - .regs = (struct sport_register *)SPORT0_TCR1, - }, - { - .dma_rx_chan = CH_SPORT1_RX, - .dma_tx_chan = CH_SPORT1_TX, - .err_irq = IRQ_SPORT1_ERROR, - .regs = (struct sport_register *)SPORT1_TCR1, - } -}; - -/* - * Setting the TFS pin selector for SPORT 0 based on whether the selected - * port id F or G. If the port is F then no conflict should exist for the - * TFS. When Port G is selected and EMAC then there is a conflict between - * the PHY interrupt line and TFS. Current settings prevent the conflict - * by ignoring the TFS pin when Port G is selected. This allows both - * ssm2602 using Port G and EMAC concurrently. - */ -#ifdef CONFIG_BF527_SPORT0_PORTF -#define LOCAL_SPORT0_TFS (P_SPORT0_TFS) -#else -#define LOCAL_SPORT0_TFS (0) -#endif - -static u16 sport_req[][7] = { {P_SPORT0_DTPRI, P_SPORT0_TSCLK, P_SPORT0_RFS, - P_SPORT0_DRPRI, P_SPORT0_RSCLK, LOCAL_SPORT0_TFS, 0}, - {P_SPORT1_DTPRI, P_SPORT1_TSCLK, P_SPORT1_RFS, P_SPORT1_DRPRI, - P_SPORT1_RSCLK, P_SPORT1_TFS, 0} }; - -static int bf5xx_tdm_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - int ret = 0; - - /* interface format:support TDM,slave mode */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - break; - default: - printk(KERN_ERR "%s: Unknown DAI format type\n", __func__); - ret = -EINVAL; - break; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - case SND_SOC_DAIFMT_CBS_CFS: - case SND_SOC_DAIFMT_CBM_CFS: - case SND_SOC_DAIFMT_CBS_CFM: - ret = -EINVAL; - break; - default: - printk(KERN_ERR "%s: Unknown DAI master type\n", __func__); - ret = -EINVAL; - break; - } - - return ret; -} - -static int bf5xx_tdm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int ret = 0; - - bf5xx_tdm.tcr2 &= ~0x1f; - bf5xx_tdm.rcr2 &= ~0x1f; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S32_LE: - bf5xx_tdm.tcr2 |= 31; - bf5xx_tdm.rcr2 |= 31; - sport_handle->wdsize = 4; - break; - /* at present, we only support 32bit transfer */ - default: - pr_err("not supported PCM format yet\n"); - return -EINVAL; - break; - } - - if (!bf5xx_tdm.configured) { - /* - * TX and RX are not independent,they are enabled at the - * same time, even if only one side is running. So, we - * need to configure both of them at the time when the first - * stream is opened. - * - * CPU DAI:slave mode. - */ - ret = sport_config_rx(sport_handle, bf5xx_tdm.rcr1, - bf5xx_tdm.rcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - ret = sport_config_tx(sport_handle, bf5xx_tdm.tcr1, - bf5xx_tdm.tcr2, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - return -EBUSY; - } - - bf5xx_tdm.configured = 1; - } - - return 0; -} - -static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - /* No active stream, SPORT is allowed to be configured again. */ - if (!dai->active) - bf5xx_tdm.configured = 0; -} - -#ifdef CONFIG_PM -static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) -{ - struct sport_device *sport = - (struct sport_device *)dai->private_data; - - if (!dai->active) - return 0; - if (dai->capture.active) - sport_rx_stop(sport); - if (dai->playback.active) - sport_tx_stop(sport); - return 0; -} - -static int bf5xx_tdm_resume(struct snd_soc_dai *dai) -{ - int ret; - struct sport_device *sport = - (struct sport_device *)dai->private_data; - - if (!dai->active) - return 0; - - ret = sport_set_multichannel(sport, 8, 0xFF, 1); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - ret = sport_config_rx(sport, IRFS, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - ret = sport_config_tx(sport, ITFS, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - } - - return 0; -} - -#else -#define bf5xx_tdm_suspend NULL -#define bf5xx_tdm_resume NULL -#endif - -static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = { - .hw_params = bf5xx_tdm_hw_params, - .set_fmt = bf5xx_tdm_set_dai_fmt, - .shutdown = bf5xx_tdm_shutdown, -}; - -struct snd_soc_dai bf5xx_tdm_dai = { - .name = "bf5xx-tdm", - .id = 0, - .suspend = bf5xx_tdm_suspend, - .resume = bf5xx_tdm_resume, - .playback = { - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE,}, - .capture = { - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE,}, - .ops = &bf5xx_tdm_dai_ops, -}; -EXPORT_SYMBOL_GPL(bf5xx_tdm_dai); - -static int __devinit bfin_tdm_probe(struct platform_device *pdev) -{ - int ret = 0; - - if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { - pr_err("Requesting Peripherals failed\n"); - return -EFAULT; - } - - /* request DMA for SPORT */ - sport_handle = sport_init(&sport_params[sport_num], 4, \ - 8 * sizeof(u32), NULL); - if (!sport_handle) { - peripheral_free_list(&sport_req[sport_num][0]); - return -ENODEV; - } - - /* SPORT works in TDM mode */ - ret = sport_set_multichannel(sport_handle, 8, 0xFF, 1); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = sport_config_rx(sport_handle, IRFS, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = sport_config_tx(sport_handle, ITFS, 0x1F, 0, 0); - if (ret) { - pr_err("SPORT is busy!\n"); - ret = -EBUSY; - goto sport_config_err; - } - - ret = snd_soc_register_dai(&bf5xx_tdm_dai); - if (ret) { - pr_err("Failed to register DAI: %d\n", ret); - goto sport_config_err; - } - return 0; - -sport_config_err: - peripheral_free_list(&sport_req[sport_num][0]); - return ret; -} - -static int __devexit bfin_tdm_remove(struct platform_device *pdev) -{ - peripheral_free_list(&sport_req[sport_num][0]); - snd_soc_unregister_dai(&bf5xx_tdm_dai); - - return 0; -} - -static struct platform_driver bfin_tdm_driver = { - .probe = bfin_tdm_probe, - .remove = __devexit_p(bfin_tdm_remove), - .driver = { - .name = "bfin-tdm", - .owner = THIS_MODULE, - }, -}; - -static int __init bfin_tdm_init(void) -{ - return platform_driver_register(&bfin_tdm_driver); -} -module_init(bfin_tdm_init); - -static void __exit bfin_tdm_exit(void) -{ - platform_driver_unregister(&bfin_tdm_driver); -} -module_exit(bfin_tdm_exit); - -/* Module information */ -MODULE_AUTHOR("Barry Song"); -MODULE_DESCRIPTION("TDM driver for ADI Blackfin"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/blackfin/bf5xx-tdm.h b/trunk/sound/soc/blackfin/bf5xx-tdm.h deleted file mode 100644 index 618ec3d90cd4..000000000000 --- a/trunk/sound/soc/blackfin/bf5xx-tdm.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * sound/soc/blackfin/bf5xx-tdm.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _BF5XX_TDM_H -#define _BF5XX_TDM_H - -extern struct snd_soc_dai bf5xx_tdm_dai; - -#endif diff --git a/trunk/sound/soc/codecs/Kconfig b/trunk/sound/soc/codecs/Kconfig index 0edca93af3b0..bbc97fd76648 100644 --- a/trunk/sound/soc/codecs/Kconfig +++ b/trunk/sound/soc/codecs/Kconfig @@ -12,15 +12,11 @@ config SND_SOC_ALL_CODECS tristate "Build all ASoC CODEC drivers" select SND_SOC_L3 select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS - select SND_SOC_AD1836 if SPI_MASTER - select SND_SOC_AD1938 if SPI_MASTER select SND_SOC_AD1980 if SND_SOC_AC97_BUS select SND_SOC_AD73311 if I2C select SND_SOC_AK4104 if SPI_MASTER select SND_SOC_AK4535 if I2C - select SND_SOC_AK4642 if I2C select SND_SOC_CS4270 if I2C - select SND_SOC_MAX9877 if I2C select SND_SOC_PCM3008 select SND_SOC_SPDIF select SND_SOC_SSM2602 if I2C @@ -34,23 +30,18 @@ config SND_SOC_ALL_CODECS select SND_SOC_WM8350 if MFD_WM8350 select SND_SOC_WM8400 if MFD_WM8400 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8523 if I2C select SND_SOC_WM8580 if I2C select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8753 if SND_SOC_I2C_AND_SPI - select SND_SOC_WM8776 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8900 if I2C select SND_SOC_WM8903 if I2C select SND_SOC_WM8940 if I2C select SND_SOC_WM8960 if I2C - select SND_SOC_WM8961 if I2C select SND_SOC_WM8971 if I2C - select SND_SOC_WM8974 if I2C select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI select SND_SOC_WM8990 if I2C - select SND_SOC_WM8993 if I2C select SND_SOC_WM9081 if I2C select SND_SOC_WM9705 if SND_SOC_AC97_BUS select SND_SOC_WM9712 if SND_SOC_AC97_BUS @@ -66,21 +57,11 @@ config SND_SOC_ALL_CODECS If unsure select "N". -config SND_SOC_WM_HUBS - tristate - default y if SND_SOC_WM8993=y - default m if SND_SOC_WM8993=m config SND_SOC_AC97_CODEC tristate select SND_AC97_CODEC -config SND_SOC_AD1836 - tristate - -config SND_SOC_AD1938 - tristate - config SND_SOC_AD1980 tristate @@ -93,9 +74,6 @@ config SND_SOC_AK4104 config SND_SOC_AK4535 tristate -config SND_SOC_AK4642 - tristate - # Cirrus Logic CS4270 Codec config SND_SOC_CS4270 tristate @@ -108,9 +86,6 @@ config SND_SOC_CS4270_VD33_ERRATA bool depends on SND_SOC_CS4270 -config SND_SOC_CX20442 - tristate - config SND_SOC_L3 tristate @@ -154,9 +129,6 @@ config SND_SOC_WM8400 config SND_SOC_WM8510 tristate -config SND_SOC_WM8523 - tristate - config SND_SOC_WM8580 tristate @@ -172,9 +144,6 @@ config SND_SOC_WM8750 config SND_SOC_WM8753 tristate -config SND_SOC_WM8776 - tristate - config SND_SOC_WM8900 tristate @@ -187,24 +156,15 @@ config SND_SOC_WM8940 config SND_SOC_WM8960 tristate -config SND_SOC_WM8961 - tristate - config SND_SOC_WM8971 tristate -config SND_SOC_WM8974 - tristate - config SND_SOC_WM8988 tristate config SND_SOC_WM8990 tristate -config SND_SOC_WM8993 - tristate - config SND_SOC_WM9081 tristate @@ -216,7 +176,3 @@ config SND_SOC_WM9712 config SND_SOC_WM9713 tristate - -# Amp -config SND_SOC_MAX9877 - tristate diff --git a/trunk/sound/soc/codecs/Makefile b/trunk/sound/soc/codecs/Makefile index fb4af28486ba..8b7530546f4d 100644 --- a/trunk/sound/soc/codecs/Makefile +++ b/trunk/sound/soc/codecs/Makefile @@ -1,13 +1,9 @@ snd-soc-ac97-objs := ac97.o -snd-soc-ad1836-objs := ad1836.o -snd-soc-ad1938-objs := ad1938.o snd-soc-ad1980-objs := ad1980.o snd-soc-ad73311-objs := ad73311.o snd-soc-ak4104-objs := ak4104.o snd-soc-ak4535-objs := ak4535.o -snd-soc-ak4642-objs := ak4642.o snd-soc-cs4270-objs := cs4270.o -snd-soc-cx20442-objs := cx20442.o snd-soc-l3-objs := l3.o snd-soc-pcm3008-objs := pcm3008.o snd-soc-spdif-objs := spdif_transciever.o @@ -22,42 +18,29 @@ snd-soc-uda1380-objs := uda1380.o snd-soc-wm8350-objs := wm8350.o snd-soc-wm8400-objs := wm8400.o snd-soc-wm8510-objs := wm8510.o -snd-soc-wm8523-objs := wm8523.o snd-soc-wm8580-objs := wm8580.o snd-soc-wm8728-objs := wm8728.o snd-soc-wm8731-objs := wm8731.o snd-soc-wm8750-objs := wm8750.o snd-soc-wm8753-objs := wm8753.o -snd-soc-wm8776-objs := wm8776.o snd-soc-wm8900-objs := wm8900.o snd-soc-wm8903-objs := wm8903.o snd-soc-wm8940-objs := wm8940.o snd-soc-wm8960-objs := wm8960.o -snd-soc-wm8961-objs := wm8961.o snd-soc-wm8971-objs := wm8971.o -snd-soc-wm8974-objs := wm8974.o snd-soc-wm8988-objs := wm8988.o snd-soc-wm8990-objs := wm8990.o -snd-soc-wm8993-objs := wm8993.o snd-soc-wm9081-objs := wm9081.o snd-soc-wm9705-objs := wm9705.o snd-soc-wm9712-objs := wm9712.o snd-soc-wm9713-objs := wm9713.o -snd-soc-wm-hubs-objs := wm_hubs.o - -# Amp -snd-soc-max9877-objs := max9877.o obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o -obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o -obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o -obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o -obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o @@ -72,28 +55,19 @@ obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o -obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o -obj-$(CONFIG_SND_SOC_WM8776) += snd-soc-wm8776.o obj-$(CONFIG_SND_SOC_WM8900) += snd-soc-wm8900.o obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o obj-$(CONFIG_SND_SOC_WM8971) += snd-soc-wm8971.o -obj-$(CONFIG_SND_SOC_WM8974) += snd-soc-wm8974.o obj-$(CONFIG_SND_SOC_WM8940) += snd-soc-wm8940.o obj-$(CONFIG_SND_SOC_WM8960) += snd-soc-wm8960.o -obj-$(CONFIG_SND_SOC_WM8961) += snd-soc-wm8961.o obj-$(CONFIG_SND_SOC_WM8988) += snd-soc-wm8988.o obj-$(CONFIG_SND_SOC_WM8990) += snd-soc-wm8990.o -obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o -obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o - -# Amp -obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o diff --git a/trunk/sound/soc/codecs/ad1836.c b/trunk/sound/soc/codecs/ad1836.c deleted file mode 100644 index 3612bb92df90..000000000000 --- a/trunk/sound/soc/codecs/ad1836.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * File: sound/soc/codecs/ad1836.c - * Author: Barry Song - * - * Created: Aug 04 2009 - * Description: Driver for AD1836 sound chip - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ad1836.h" - -/* codec private data */ -struct ad1836_priv { - struct snd_soc_codec codec; - u16 reg_cache[AD1836_NUM_REGS]; -}; - -static struct snd_soc_codec *ad1836_codec; -struct snd_soc_codec_device soc_codec_dev_ad1836; -static int ad1836_register(struct ad1836_priv *ad1836); -static void ad1836_unregister(struct ad1836_priv *ad1836); - -/* - * AD1836 volume/mute/de-emphasis etc. controls - */ -static const char *ad1836_deemp[] = {"None", "44.1kHz", "32kHz", "48kHz"}; - -static const struct soc_enum ad1836_deemp_enum = - SOC_ENUM_SINGLE(AD1836_DAC_CTRL1, 8, 4, ad1836_deemp); - -static const struct snd_kcontrol_new ad1836_snd_controls[] = { - /* DAC volume control */ - SOC_DOUBLE_R("DAC1 Volume", AD1836_DAC_L1_VOL, - AD1836_DAC_R1_VOL, 0, 0x3FF, 0), - SOC_DOUBLE_R("DAC2 Volume", AD1836_DAC_L2_VOL, - AD1836_DAC_R2_VOL, 0, 0x3FF, 0), - SOC_DOUBLE_R("DAC3 Volume", AD1836_DAC_L3_VOL, - AD1836_DAC_R3_VOL, 0, 0x3FF, 0), - - /* ADC switch control */ - SOC_DOUBLE("ADC1 Switch", AD1836_ADC_CTRL2, AD1836_ADCL1_MUTE, - AD1836_ADCR1_MUTE, 1, 1), - SOC_DOUBLE("ADC2 Switch", AD1836_ADC_CTRL2, AD1836_ADCL2_MUTE, - AD1836_ADCR2_MUTE, 1, 1), - - /* DAC switch control */ - SOC_DOUBLE("DAC1 Switch", AD1836_DAC_CTRL2, AD1836_DACL1_MUTE, - AD1836_DACR1_MUTE, 1, 1), - SOC_DOUBLE("DAC2 Switch", AD1836_DAC_CTRL2, AD1836_DACL2_MUTE, - AD1836_DACR2_MUTE, 1, 1), - SOC_DOUBLE("DAC3 Switch", AD1836_DAC_CTRL2, AD1836_DACL3_MUTE, - AD1836_DACR3_MUTE, 1, 1), - - /* ADC high-pass filter */ - SOC_SINGLE("ADC High Pass Filter Switch", AD1836_ADC_CTRL1, - AD1836_ADC_HIGHPASS_FILTER, 1, 0), - - /* DAC de-emphasis */ - SOC_ENUM("Playback Deemphasis", ad1836_deemp_enum), -}; - -static const struct snd_soc_dapm_widget ad1836_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", "Playback", AD1836_DAC_CTRL1, - AD1836_DAC_POWERDOWN, 1), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1836_ADC_CTRL1, - AD1836_ADC_POWERDOWN, 1, NULL, 0), - SND_SOC_DAPM_OUTPUT("DAC1OUT"), - SND_SOC_DAPM_OUTPUT("DAC2OUT"), - SND_SOC_DAPM_OUTPUT("DAC3OUT"), - SND_SOC_DAPM_INPUT("ADC1IN"), - SND_SOC_DAPM_INPUT("ADC2IN"), -}; - -static const struct snd_soc_dapm_route audio_paths[] = { - { "DAC", NULL, "ADC_PWR" }, - { "ADC", NULL, "ADC_PWR" }, - { "DAC1OUT", "DAC1 Switch", "DAC" }, - { "DAC2OUT", "DAC2 Switch", "DAC" }, - { "DAC3OUT", "DAC3 Switch", "DAC" }, - { "ADC", "ADC1 Switch", "ADC1IN" }, - { "ADC", "ADC2 Switch", "ADC2IN" }, -}; - -/* - * DAI ops entries - */ - -static int ad1836_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - /* at present, we support adc aux mode to interface with - * blackfin sport tdm mode - */ - case SND_SOC_DAIFMT_DSP_A: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - /* ALCLK,ABCLK are both output, AD1836 can only be master */ - case SND_SOC_DAIFMT_CBM_CFM: - break; - default: - return -EINVAL; - } - - return 0; -} - -static int ad1836_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int word_len = 0; - - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - word_len = 3; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - word_len = 1; - break; - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S32_LE: - word_len = 0; - break; - } - - snd_soc_update_bits(codec, AD1836_DAC_CTRL1, - AD1836_DAC_WORD_LEN_MASK, word_len); - - snd_soc_update_bits(codec, AD1836_ADC_CTRL2, - AD1836_ADC_WORD_LEN_MASK, word_len); - - return 0; -} - - -/* - * interface to read/write ad1836 register - */ -#define AD1836_SPI_REG_SHFT 12 -#define AD1836_SPI_READ (1 << 11) -#define AD1836_SPI_VAL_MSK 0x3FF - -/* - * write to the ad1836 register space - */ - -static int ad1836_write_reg(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u16 *reg_cache = codec->reg_cache; - int ret = 0; - - if (value != reg_cache[reg]) { - unsigned short buf; - struct spi_transfer t = { - .tx_buf = &buf, - .len = 2, - }; - struct spi_message m; - - buf = (reg << AD1836_SPI_REG_SHFT) | - (value & AD1836_SPI_VAL_MSK); - spi_message_init(&m); - spi_message_add_tail(&t, &m); - ret = spi_sync(codec->control_data, &m); - if (ret == 0) - reg_cache[reg] = value; - } - - return ret; -} - -/* - * read from the ad1836 register space cache - */ -static unsigned int ad1836_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *reg_cache = codec->reg_cache; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - return reg_cache[reg]; -} - -static int __devinit ad1836_spi_probe(struct spi_device *spi) -{ - struct snd_soc_codec *codec; - struct ad1836_priv *ad1836; - - ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL); - if (ad1836 == NULL) - return -ENOMEM; - - codec = &ad1836->codec; - codec->control_data = spi; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, ad1836); - - return ad1836_register(ad1836); -} - -static int __devexit ad1836_spi_remove(struct spi_device *spi) -{ - struct ad1836_priv *ad1836 = dev_get_drvdata(&spi->dev); - - ad1836_unregister(ad1836); - return 0; -} - -static struct spi_driver ad1836_spi_driver = { - .driver = { - .name = "ad1836-spi", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = ad1836_spi_probe, - .remove = __devexit_p(ad1836_spi_remove), -}; - -static struct snd_soc_dai_ops ad1836_dai_ops = { - .hw_params = ad1836_hw_params, - .set_fmt = ad1836_set_dai_fmt, -}; - -/* codec DAI instance */ -struct snd_soc_dai ad1836_dai = { - .name = "AD1836", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 6, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 4, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .ops = &ad1836_dai_ops, -}; -EXPORT_SYMBOL_GPL(ad1836_dai); - -static int ad1836_register(struct ad1836_priv *ad1836) -{ - int ret; - struct snd_soc_codec *codec = &ad1836->codec; - - if (ad1836_codec) { - dev_err(codec->dev, "Another ad1836 is registered\n"); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - codec->private_data = ad1836; - codec->reg_cache = ad1836->reg_cache; - codec->reg_cache_size = AD1836_NUM_REGS; - codec->name = "AD1836"; - codec->owner = THIS_MODULE; - codec->dai = &ad1836_dai; - codec->num_dai = 1; - codec->write = ad1836_write_reg; - codec->read = ad1836_read_reg_cache; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - ad1836_dai.dev = codec->dev; - ad1836_codec = codec; - - /* default setting for ad1836 */ - /* de-emphasis: 48kHz, power-on dac */ - codec->write(codec, AD1836_DAC_CTRL1, 0x300); - /* unmute dac channels */ - codec->write(codec, AD1836_DAC_CTRL2, 0x0); - /* high-pass filter enable, power-on adc */ - codec->write(codec, AD1836_ADC_CTRL1, 0x100); - /* unmute adc channles, adc aux mode */ - codec->write(codec, AD1836_ADC_CTRL2, 0x180); - /* left/right diff:PGA/MUX */ - codec->write(codec, AD1836_ADC_CTRL3, 0x3A); - /* volume */ - codec->write(codec, AD1836_DAC_L1_VOL, 0x3FF); - codec->write(codec, AD1836_DAC_R1_VOL, 0x3FF); - codec->write(codec, AD1836_DAC_L2_VOL, 0x3FF); - codec->write(codec, AD1836_DAC_R2_VOL, 0x3FF); - codec->write(codec, AD1836_DAC_L3_VOL, 0x3FF); - codec->write(codec, AD1836_DAC_R3_VOL, 0x3FF); - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - kfree(ad1836); - return ret; - } - - ret = snd_soc_register_dai(&ad1836_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - kfree(ad1836); - return ret; - } - - return 0; -} - -static void ad1836_unregister(struct ad1836_priv *ad1836) -{ - snd_soc_unregister_dai(&ad1836_dai); - snd_soc_unregister_codec(&ad1836->codec); - kfree(ad1836); - ad1836_codec = NULL; -} - -static int ad1836_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (ad1836_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = ad1836_codec; - codec = ad1836_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, ad1836_snd_controls, - ARRAY_SIZE(ad1836_snd_controls)); - snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, - ARRAY_SIZE(ad1836_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); - snd_soc_dapm_new_widgets(codec); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int ad1836_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ad1836 = { - .probe = ad1836_probe, - .remove = ad1836_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad1836); - -static int __init ad1836_init(void) -{ - int ret; - - ret = spi_register_driver(&ad1836_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register ad1836 SPI driver: %d\n", - ret); - } - - return ret; -} -module_init(ad1836_init); - -static void __exit ad1836_exit(void) -{ - spi_unregister_driver(&ad1836_spi_driver); -} -module_exit(ad1836_exit); - -MODULE_DESCRIPTION("ASoC ad1836 driver"); -MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/ad1836.h b/trunk/sound/soc/codecs/ad1836.h deleted file mode 100644 index 7660ee6973c0..000000000000 --- a/trunk/sound/soc/codecs/ad1836.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * File: sound/soc/codecs/ad1836.h - * Based on: - * Author: Barry Song - * - * Created: Aug 04, 2009 - * Description: definitions for AD1836 registers - * - * Modified: - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ - -#ifndef __AD1836_H__ -#define __AD1836_H__ - -#define AD1836_DAC_CTRL1 0 -#define AD1836_DAC_POWERDOWN 2 -#define AD1836_DAC_SERFMT_MASK 0xE0 -#define AD1836_DAC_SERFMT_PCK256 (0x4 << 5) -#define AD1836_DAC_SERFMT_PCK128 (0x5 << 5) -#define AD1836_DAC_WORD_LEN_MASK 0x18 - -#define AD1836_DAC_CTRL2 1 -#define AD1836_DACL1_MUTE 0 -#define AD1836_DACR1_MUTE 1 -#define AD1836_DACL2_MUTE 2 -#define AD1836_DACR2_MUTE 3 -#define AD1836_DACL3_MUTE 4 -#define AD1836_DACR3_MUTE 5 - -#define AD1836_DAC_L1_VOL 2 -#define AD1836_DAC_R1_VOL 3 -#define AD1836_DAC_L2_VOL 4 -#define AD1836_DAC_R2_VOL 5 -#define AD1836_DAC_L3_VOL 6 -#define AD1836_DAC_R3_VOL 7 - -#define AD1836_ADC_CTRL1 12 -#define AD1836_ADC_POWERDOWN 7 -#define AD1836_ADC_HIGHPASS_FILTER 8 - -#define AD1836_ADC_CTRL2 13 -#define AD1836_ADCL1_MUTE 0 -#define AD1836_ADCR1_MUTE 1 -#define AD1836_ADCL2_MUTE 2 -#define AD1836_ADCR2_MUTE 3 -#define AD1836_ADC_WORD_LEN_MASK 0x30 -#define AD1836_ADC_SERFMT_MASK (7 << 6) -#define AD1836_ADC_SERFMT_PCK256 (0x4 << 6) -#define AD1836_ADC_SERFMT_PCK128 (0x5 << 6) - -#define AD1836_ADC_CTRL3 14 - -#define AD1836_NUM_REGS 16 - -extern struct snd_soc_dai ad1836_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad1836; -#endif diff --git a/trunk/sound/soc/codecs/ad1938.c b/trunk/sound/soc/codecs/ad1938.c deleted file mode 100644 index e62b27701a49..000000000000 --- a/trunk/sound/soc/codecs/ad1938.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * File: sound/soc/codecs/ad1938.c - * Author: Barry Song - * - * Created: June 04 2009 - * Description: Driver for AD1938 sound chip - * - * Modified: - * Copyright 2009 Analog Devices Inc. - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ad1938.h" - -/* codec private data */ -struct ad1938_priv { - struct snd_soc_codec codec; - u8 reg_cache[AD1938_NUM_REGS]; -}; - -static struct snd_soc_codec *ad1938_codec; -struct snd_soc_codec_device soc_codec_dev_ad1938; -static int ad1938_register(struct ad1938_priv *ad1938); -static void ad1938_unregister(struct ad1938_priv *ad1938); - -/* - * AD1938 volume/mute/de-emphasis etc. controls - */ -static const char *ad1938_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"}; - -static const struct soc_enum ad1938_deemp_enum = - SOC_ENUM_SINGLE(AD1938_DAC_CTRL2, 1, 4, ad1938_deemp); - -static const struct snd_kcontrol_new ad1938_snd_controls[] = { - /* DAC volume control */ - SOC_DOUBLE_R("DAC1 Volume", AD1938_DAC_L1_VOL, - AD1938_DAC_R1_VOL, 0, 0xFF, 1), - SOC_DOUBLE_R("DAC2 Volume", AD1938_DAC_L2_VOL, - AD1938_DAC_R2_VOL, 0, 0xFF, 1), - SOC_DOUBLE_R("DAC3 Volume", AD1938_DAC_L3_VOL, - AD1938_DAC_R3_VOL, 0, 0xFF, 1), - SOC_DOUBLE_R("DAC4 Volume", AD1938_DAC_L4_VOL, - AD1938_DAC_R4_VOL, 0, 0xFF, 1), - - /* ADC switch control */ - SOC_DOUBLE("ADC1 Switch", AD1938_ADC_CTRL0, AD1938_ADCL1_MUTE, - AD1938_ADCR1_MUTE, 1, 1), - SOC_DOUBLE("ADC2 Switch", AD1938_ADC_CTRL0, AD1938_ADCL2_MUTE, - AD1938_ADCR2_MUTE, 1, 1), - - /* DAC switch control */ - SOC_DOUBLE("DAC1 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL1_MUTE, - AD1938_DACR1_MUTE, 1, 1), - SOC_DOUBLE("DAC2 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL2_MUTE, - AD1938_DACR2_MUTE, 1, 1), - SOC_DOUBLE("DAC3 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL3_MUTE, - AD1938_DACR3_MUTE, 1, 1), - SOC_DOUBLE("DAC4 Switch", AD1938_DAC_CHNL_MUTE, AD1938_DACL4_MUTE, - AD1938_DACR4_MUTE, 1, 1), - - /* ADC high-pass filter */ - SOC_SINGLE("ADC High Pass Filter Switch", AD1938_ADC_CTRL0, - AD1938_ADC_HIGHPASS_FILTER, 1, 0), - - /* DAC de-emphasis */ - SOC_ENUM("Playback Deemphasis", ad1938_deemp_enum), -}; - -static const struct snd_soc_dapm_widget ad1938_dapm_widgets[] = { - SND_SOC_DAPM_DAC("DAC", "Playback", AD1938_DAC_CTRL0, 0, 1), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_SUPPLY("ADC_PWR", AD1938_ADC_CTRL0, 0, 1, NULL, 0), - SND_SOC_DAPM_OUTPUT("DAC1OUT"), - SND_SOC_DAPM_OUTPUT("DAC2OUT"), - SND_SOC_DAPM_OUTPUT("DAC3OUT"), - SND_SOC_DAPM_OUTPUT("DAC4OUT"), - SND_SOC_DAPM_INPUT("ADC1IN"), - SND_SOC_DAPM_INPUT("ADC2IN"), -}; - -static const struct snd_soc_dapm_route audio_paths[] = { - { "DAC", NULL, "ADC_PWR" }, - { "ADC", NULL, "ADC_PWR" }, - { "DAC1OUT", "DAC1 Switch", "DAC" }, - { "DAC2OUT", "DAC2 Switch", "DAC" }, - { "DAC3OUT", "DAC3 Switch", "DAC" }, - { "DAC4OUT", "DAC4 Switch", "DAC" }, - { "ADC", "ADC1 Switch", "ADC1IN" }, - { "ADC", "ADC2 Switch", "ADC2IN" }, -}; - -/* - * DAI ops entries - */ - -static int ad1938_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - int reg; - - reg = codec->read(codec, AD1938_DAC_CTRL2); - reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg & - (~AD1938_DAC_MASTER_MUTE); - codec->write(codec, AD1938_DAC_CTRL2, reg); - - return 0; -} - -static inline int ad1938_pll_powerctrl(struct snd_soc_codec *codec, int cmd) -{ - int reg = codec->read(codec, AD1938_PLL_CLK_CTRL0); - reg = (cmd > 0) ? reg & (~AD1938_PLL_POWERDOWN) : reg | - AD1938_PLL_POWERDOWN; - codec->write(codec, AD1938_PLL_CLK_CTRL0, reg); - - return 0; -} - -static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, - unsigned int mask, int slots, int width) -{ - struct snd_soc_codec *codec = dai->codec; - int dac_reg = codec->read(codec, AD1938_DAC_CTRL1); - int adc_reg = codec->read(codec, AD1938_ADC_CTRL2); - - dac_reg &= ~AD1938_DAC_CHAN_MASK; - adc_reg &= ~AD1938_ADC_CHAN_MASK; - - switch (slots) { - case 2: - dac_reg |= AD1938_DAC_2_CHANNELS << AD1938_DAC_CHAN_SHFT; - adc_reg |= AD1938_ADC_2_CHANNELS << AD1938_ADC_CHAN_SHFT; - break; - case 4: - dac_reg |= AD1938_DAC_4_CHANNELS << AD1938_DAC_CHAN_SHFT; - adc_reg |= AD1938_ADC_4_CHANNELS << AD1938_ADC_CHAN_SHFT; - break; - case 8: - dac_reg |= AD1938_DAC_8_CHANNELS << AD1938_DAC_CHAN_SHFT; - adc_reg |= AD1938_ADC_8_CHANNELS << AD1938_ADC_CHAN_SHFT; - break; - case 16: - dac_reg |= AD1938_DAC_16_CHANNELS << AD1938_DAC_CHAN_SHFT; - adc_reg |= AD1938_ADC_16_CHANNELS << AD1938_ADC_CHAN_SHFT; - break; - default: - return -EINVAL; - } - - codec->write(codec, AD1938_DAC_CTRL1, dac_reg); - codec->write(codec, AD1938_ADC_CTRL2, adc_reg); - - return 0; -} - -static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - int adc_reg, dac_reg; - - adc_reg = codec->read(codec, AD1938_ADC_CTRL2); - dac_reg = codec->read(codec, AD1938_DAC_CTRL1); - - /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S - * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) - */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - adc_reg &= ~AD1938_ADC_SERFMT_MASK; - adc_reg |= AD1938_ADC_SERFMT_TDM; - break; - case SND_SOC_DAIFMT_DSP_A: - adc_reg &= ~AD1938_ADC_SERFMT_MASK; - adc_reg |= AD1938_ADC_SERFMT_AUX; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ - adc_reg &= ~AD1938_ADC_LEFT_HIGH; - adc_reg &= ~AD1938_ADC_BCLK_INV; - dac_reg &= ~AD1938_DAC_LEFT_HIGH; - dac_reg &= ~AD1938_DAC_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */ - adc_reg |= AD1938_ADC_LEFT_HIGH; - adc_reg &= ~AD1938_ADC_BCLK_INV; - dac_reg |= AD1938_DAC_LEFT_HIGH; - dac_reg &= ~AD1938_DAC_BCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */ - adc_reg &= ~AD1938_ADC_LEFT_HIGH; - adc_reg |= AD1938_ADC_BCLK_INV; - dac_reg &= ~AD1938_DAC_LEFT_HIGH; - dac_reg |= AD1938_DAC_BCLK_INV; - break; - - case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ - adc_reg |= AD1938_ADC_LEFT_HIGH; - adc_reg |= AD1938_ADC_BCLK_INV; - dac_reg |= AD1938_DAC_LEFT_HIGH; - dac_reg |= AD1938_DAC_BCLK_INV; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ - adc_reg |= AD1938_ADC_LCR_MASTER; - adc_reg |= AD1938_ADC_BCLK_MASTER; - dac_reg |= AD1938_DAC_LCR_MASTER; - dac_reg |= AD1938_DAC_BCLK_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */ - adc_reg |= AD1938_ADC_LCR_MASTER; - adc_reg &= ~AD1938_ADC_BCLK_MASTER; - dac_reg |= AD1938_DAC_LCR_MASTER; - dac_reg &= ~AD1938_DAC_BCLK_MASTER; - break; - case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */ - adc_reg &= ~AD1938_ADC_LCR_MASTER; - adc_reg |= AD1938_ADC_BCLK_MASTER; - dac_reg &= ~AD1938_DAC_LCR_MASTER; - dac_reg |= AD1938_DAC_BCLK_MASTER; - break; - case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */ - adc_reg &= ~AD1938_ADC_LCR_MASTER; - adc_reg &= ~AD1938_ADC_BCLK_MASTER; - dac_reg &= ~AD1938_DAC_LCR_MASTER; - dac_reg &= ~AD1938_DAC_BCLK_MASTER; - break; - default: - return -EINVAL; - } - - codec->write(codec, AD1938_ADC_CTRL2, adc_reg); - codec->write(codec, AD1938_DAC_CTRL1, dac_reg); - - return 0; -} - -static int ad1938_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - int word_len = 0, reg = 0; - - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - word_len = 3; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - word_len = 1; - break; - case SNDRV_PCM_FORMAT_S24_LE: - case SNDRV_PCM_FORMAT_S32_LE: - word_len = 0; - break; - } - - reg = codec->read(codec, AD1938_DAC_CTRL2); - reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len; - codec->write(codec, AD1938_DAC_CTRL2, reg); - - reg = codec->read(codec, AD1938_ADC_CTRL1); - reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len; - codec->write(codec, AD1938_ADC_CTRL1, reg); - - return 0; -} - -static int ad1938_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - ad1938_pll_powerctrl(codec, 1); - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - case SND_SOC_BIAS_OFF: - ad1938_pll_powerctrl(codec, 0); - break; - } - codec->bias_level = level; - return 0; -} - -/* - * interface to read/write ad1938 register - */ - -#define AD1938_SPI_ADDR 0x4 -#define AD1938_SPI_READ 0x1 -#define AD1938_SPI_BUFLEN 3 - -/* - * write to the ad1938 register space - */ - -static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 *reg_cache = codec->reg_cache; - int ret = 0; - - if (value != reg_cache[reg]) { - uint8_t buf[AD1938_SPI_BUFLEN]; - struct spi_transfer t = { - .tx_buf = buf, - .len = AD1938_SPI_BUFLEN, - }; - struct spi_message m; - - buf[0] = AD1938_SPI_ADDR << 1; - buf[1] = reg; - buf[2] = value; - spi_message_init(&m); - spi_message_add_tail(&t, &m); - ret = spi_sync(codec->control_data, &m); - if (ret == 0) - reg_cache[reg] = value; - } - - return ret; -} - -/* - * read from the ad1938 register space cache - */ - -static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *reg_cache = codec->reg_cache; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - return reg_cache[reg]; -} - -/* - * read from the ad1938 register space - */ - -static unsigned int ad1938_read_reg(struct snd_soc_codec *codec, - unsigned int reg) -{ - char w_buf[AD1938_SPI_BUFLEN]; - char r_buf[AD1938_SPI_BUFLEN]; - int ret; - - struct spi_transfer t = { - .tx_buf = w_buf, - .rx_buf = r_buf, - .len = AD1938_SPI_BUFLEN, - }; - struct spi_message m; - - w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ; - w_buf[1] = reg; - w_buf[2] = 0; - - spi_message_init(&m); - spi_message_add_tail(&t, &m); - ret = spi_sync(codec->control_data, &m); - if (ret == 0) - return r_buf[2]; - else - return -EIO; -} - -static int ad1938_fill_cache(struct snd_soc_codec *codec) -{ - int i; - u8 *reg_cache = codec->reg_cache; - struct spi_device *spi = codec->control_data; - - for (i = 0; i < codec->reg_cache_size; i++) { - int ret = ad1938_read_reg(codec, i); - if (ret == -EIO) { - dev_err(&spi->dev, "AD1938 SPI read failure\n"); - return ret; - } - reg_cache[i] = ret; - } - - return 0; -} - -static int __devinit ad1938_spi_probe(struct spi_device *spi) -{ - struct snd_soc_codec *codec; - struct ad1938_priv *ad1938; - - ad1938 = kzalloc(sizeof(struct ad1938_priv), GFP_KERNEL); - if (ad1938 == NULL) - return -ENOMEM; - - codec = &ad1938->codec; - codec->control_data = spi; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, ad1938); - - return ad1938_register(ad1938); -} - -static int __devexit ad1938_spi_remove(struct spi_device *spi) -{ - struct ad1938_priv *ad1938 = dev_get_drvdata(&spi->dev); - - ad1938_unregister(ad1938); - return 0; -} - -static struct spi_driver ad1938_spi_driver = { - .driver = { - .name = "ad1938", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = ad1938_spi_probe, - .remove = __devexit_p(ad1938_spi_remove), -}; - -static struct snd_soc_dai_ops ad1938_dai_ops = { - .hw_params = ad1938_hw_params, - .digital_mute = ad1938_mute, - .set_tdm_slot = ad1938_set_tdm_slot, - .set_fmt = ad1938_set_dai_fmt, -}; - -/* codec DAI instance */ -struct snd_soc_dai ad1938_dai = { - .name = "AD1938", - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 8, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 4, - .rates = SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE, - }, - .ops = &ad1938_dai_ops, -}; -EXPORT_SYMBOL_GPL(ad1938_dai); - -static int ad1938_register(struct ad1938_priv *ad1938) -{ - int ret; - struct snd_soc_codec *codec = &ad1938->codec; - - if (ad1938_codec) { - dev_err(codec->dev, "Another ad1938 is registered\n"); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - codec->private_data = ad1938; - codec->reg_cache = ad1938->reg_cache; - codec->reg_cache_size = AD1938_NUM_REGS; - codec->name = "AD1938"; - codec->owner = THIS_MODULE; - codec->dai = &ad1938_dai; - codec->num_dai = 1; - codec->write = ad1938_write_reg; - codec->read = ad1938_read_reg_cache; - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - ad1938_dai.dev = codec->dev; - ad1938_codec = codec; - - /* default setting for ad1938 */ - - /* unmute dac channels */ - codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0); - /* de-emphasis: 48kHz, powedown dac */ - codec->write(codec, AD1938_DAC_CTRL2, 0x1A); - /* powerdown dac, dac in tdm mode */ - codec->write(codec, AD1938_DAC_CTRL0, 0x41); - /* high-pass filter enable */ - codec->write(codec, AD1938_ADC_CTRL0, 0x3); - /* sata delay=1, adc aux mode */ - codec->write(codec, AD1938_ADC_CTRL1, 0x43); - /* pll input: mclki/xi */ - codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D); - codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04); - - ad1938_fill_cache(codec); - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - kfree(ad1938); - return ret; - } - - ret = snd_soc_register_dai(&ad1938_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - kfree(ad1938); - return ret; - } - - return 0; -} - -static void ad1938_unregister(struct ad1938_priv *ad1938) -{ - ad1938_set_bias_level(&ad1938->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&ad1938_dai); - snd_soc_unregister_codec(&ad1938->codec); - kfree(ad1938); - ad1938_codec = NULL; -} - -static int ad1938_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (ad1938_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = ad1938_codec; - codec = ad1938_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, ad1938_snd_controls, - ARRAY_SIZE(ad1938_snd_controls)); - snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets, - ARRAY_SIZE(ad1938_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); - snd_soc_dapm_new_widgets(codec); - - ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int ad1938_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -#ifdef CONFIG_PM -static int ad1938_suspend(struct platform_device *pdev, - pm_message_t state) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - ad1938_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int ad1938_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - if (codec->suspend_bias_level == SND_SOC_BIAS_ON) - ad1938_set_bias_level(codec, SND_SOC_BIAS_ON); - - return 0; -} -#else -#define ad1938_suspend NULL -#define ad1938_resume NULL -#endif - -struct snd_soc_codec_device soc_codec_dev_ad1938 = { - .probe = ad1938_probe, - .remove = ad1938_remove, - .suspend = ad1938_suspend, - .resume = ad1938_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ad1938); - -static int __init ad1938_init(void) -{ - int ret; - - ret = spi_register_driver(&ad1938_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register ad1938 SPI driver: %d\n", - ret); - } - - return ret; -} -module_init(ad1938_init); - -static void __exit ad1938_exit(void) -{ - spi_unregister_driver(&ad1938_spi_driver); -} -module_exit(ad1938_exit); - -MODULE_DESCRIPTION("ASoC ad1938 driver"); -MODULE_AUTHOR("Barry Song "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/ad1938.h b/trunk/sound/soc/codecs/ad1938.h deleted file mode 100644 index fe3c48cd2d5b..000000000000 --- a/trunk/sound/soc/codecs/ad1938.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * File: sound/soc/codecs/ad1836.h - * Based on: - * Author: Barry Song - * - * Created: May 25, 2009 - * Description: definitions for AD1938 registers - * - * Modified: - * - * Bugs: Enter bugs at http://blackfin.uclinux.org/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see the file COPYING, or write - * to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __AD1938_H__ -#define __AD1938_H__ - -#define AD1938_PLL_CLK_CTRL0 0 -#define AD1938_PLL_POWERDOWN 0x01 -#define AD1938_PLL_CLK_CTRL1 1 -#define AD1938_DAC_CTRL0 2 -#define AD1938_DAC_POWERDOWN 0x01 -#define AD1938_DAC_SERFMT_MASK 0xC0 -#define AD1938_DAC_SERFMT_STEREO (0 << 6) -#define AD1938_DAC_SERFMT_TDM (1 << 6) -#define AD1938_DAC_CTRL1 3 -#define AD1938_DAC_2_CHANNELS 0 -#define AD1938_DAC_4_CHANNELS 1 -#define AD1938_DAC_8_CHANNELS 2 -#define AD1938_DAC_16_CHANNELS 3 -#define AD1938_DAC_CHAN_SHFT 1 -#define AD1938_DAC_CHAN_MASK (3 << AD1938_DAC_CHAN_SHFT) -#define AD1938_DAC_LCR_MASTER (1 << 4) -#define AD1938_DAC_BCLK_MASTER (1 << 5) -#define AD1938_DAC_LEFT_HIGH (1 << 3) -#define AD1938_DAC_BCLK_INV (1 << 7) -#define AD1938_DAC_CTRL2 4 -#define AD1938_DAC_WORD_LEN_MASK 0xC -#define AD1938_DAC_MASTER_MUTE 1 -#define AD1938_DAC_CHNL_MUTE 5 -#define AD1938_DACL1_MUTE 0 -#define AD1938_DACR1_MUTE 1 -#define AD1938_DACL2_MUTE 2 -#define AD1938_DACR2_MUTE 3 -#define AD1938_DACL3_MUTE 4 -#define AD1938_DACR3_MUTE 5 -#define AD1938_DACL4_MUTE 6 -#define AD1938_DACR4_MUTE 7 -#define AD1938_DAC_L1_VOL 6 -#define AD1938_DAC_R1_VOL 7 -#define AD1938_DAC_L2_VOL 8 -#define AD1938_DAC_R2_VOL 9 -#define AD1938_DAC_L3_VOL 10 -#define AD1938_DAC_R3_VOL 11 -#define AD1938_DAC_L4_VOL 12 -#define AD1938_DAC_R4_VOL 13 -#define AD1938_ADC_CTRL0 14 -#define AD1938_ADC_POWERDOWN 0x01 -#define AD1938_ADC_HIGHPASS_FILTER 1 -#define AD1938_ADCL1_MUTE 2 -#define AD1938_ADCR1_MUTE 3 -#define AD1938_ADCL2_MUTE 4 -#define AD1938_ADCR2_MUTE 5 -#define AD1938_ADC_CTRL1 15 -#define AD1938_ADC_SERFMT_MASK 0x60 -#define AD1938_ADC_SERFMT_STEREO (0 << 5) -#define AD1938_ADC_SERFMT_TDM (1 << 2) -#define AD1938_ADC_SERFMT_AUX (2 << 5) -#define AD1938_ADC_WORD_LEN_MASK 0x3 -#define AD1938_ADC_CTRL2 16 -#define AD1938_ADC_2_CHANNELS 0 -#define AD1938_ADC_4_CHANNELS 1 -#define AD1938_ADC_8_CHANNELS 2 -#define AD1938_ADC_16_CHANNELS 3 -#define AD1938_ADC_CHAN_SHFT 4 -#define AD1938_ADC_CHAN_MASK (3 << AD1938_ADC_CHAN_SHFT) -#define AD1938_ADC_LCR_MASTER (1 << 3) -#define AD1938_ADC_BCLK_MASTER (1 << 6) -#define AD1938_ADC_LEFT_HIGH (1 << 2) -#define AD1938_ADC_BCLK_INV (1 << 1) - -#define AD1938_NUM_REGS 17 - -extern struct snd_soc_dai ad1938_dai; -extern struct snd_soc_codec_device soc_codec_dev_ad1938; -#endif diff --git a/trunk/sound/soc/codecs/ak4535.c b/trunk/sound/soc/codecs/ak4535.c index 0abec0d29a96..dd3380202766 100644 --- a/trunk/sound/soc/codecs/ak4535.c +++ b/trunk/sound/soc/codecs/ak4535.c @@ -59,6 +59,21 @@ static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec, return cache[reg]; } +static inline unsigned int ak4535_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + u8 data; + data = reg; + + if (codec->hw_write(codec->control_data, &data, 1) != 1) + return -EIO; + + if (codec->hw_read(codec->control_data, &data, 1) != 1) + return -EIO; + + return data; +}; + /* * write ak4535 register cache */ @@ -620,6 +635,7 @@ static int ak4535_probe(struct platform_device *pdev) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { codec->hw_write = (hw_write_t)i2c_master_send; + codec->hw_read = (hw_read_t)i2c_master_recv; ret = ak4535_add_i2c_device(pdev, setup); } #endif diff --git a/trunk/sound/soc/codecs/ak4642.c b/trunk/sound/soc/codecs/ak4642.c deleted file mode 100644 index e057c7b578df..000000000000 --- a/trunk/sound/soc/codecs/ak4642.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * ak4642.c -- AK4642/AK4643 ALSA Soc Audio driver - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto - * - * Based on wm8731.c by Richard Purdie - * Based on ak4535.c by Richard Purdie - * Based on wm8753.c by Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* ** CAUTION ** - * - * This is very simple driver. - * It can use headphone output / stereo input only - * - * AK4642 is not tested. - * AK4643 is tested. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ak4642.h" - -#define AK4642_VERSION "0.0.1" - -#define PW_MGMT1 0x00 -#define PW_MGMT2 0x01 -#define SG_SL1 0x02 -#define SG_SL2 0x03 -#define MD_CTL1 0x04 -#define MD_CTL2 0x05 -#define TIMER 0x06 -#define ALC_CTL1 0x07 -#define ALC_CTL2 0x08 -#define L_IVC 0x09 -#define L_DVC 0x0a -#define ALC_CTL3 0x0b -#define R_IVC 0x0c -#define R_DVC 0x0d -#define MD_CTL3 0x0e -#define MD_CTL4 0x0f -#define PW_MGMT3 0x10 -#define DF_S 0x11 -#define FIL3_0 0x12 -#define FIL3_1 0x13 -#define FIL3_2 0x14 -#define FIL3_3 0x15 -#define EQ_0 0x16 -#define EQ_1 0x17 -#define EQ_2 0x18 -#define EQ_3 0x19 -#define EQ_4 0x1a -#define EQ_5 0x1b -#define FIL1_0 0x1c -#define FIL1_1 0x1d -#define FIL1_2 0x1e -#define FIL1_3 0x1f -#define PW_MGMT4 0x20 -#define MD_CTL5 0x21 -#define LO_MS 0x22 -#define HP_MS 0x23 -#define SPK_MS 0x24 - -#define AK4642_CACHEREGNUM 0x25 - -struct snd_soc_codec_device soc_codec_dev_ak4642; - -/* codec private data */ -struct ak4642_priv { - struct snd_soc_codec codec; - unsigned int sysclk; -}; - -static struct snd_soc_codec *ak4642_codec; - -/* - * ak4642 register cache - */ -static const u16 ak4642_reg[AK4642_CACHEREGNUM] = { - 0x0000, 0x0000, 0x0001, 0x0000, - 0x0002, 0x0000, 0x0000, 0x0000, - 0x00e1, 0x00e1, 0x0018, 0x0000, - 0x00e1, 0x0018, 0x0011, 0x0008, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, -}; - -/* - * read ak4642 register cache - */ -static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg >= AK4642_CACHEREGNUM) - return -1; - return cache[reg]; -} - -/* - * write ak4642 register cache - */ -static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec, - u16 reg, unsigned int value) -{ - u16 *cache = codec->reg_cache; - if (reg >= AK4642_CACHEREGNUM) - return; - - cache[reg] = value; -} - -/* - * write to the AK4642 register space - */ -static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 data[2]; - - /* data is - * D15..D8 AK4642 register offset - * D7...D0 register data - */ - data[0] = reg & 0xff; - data[1] = value & 0xff; - - if (codec->hw_write(codec->control_data, data, 2) == 2) { - ak4642_write_reg_cache(codec, reg, value); - return 0; - } else - return -EIO; -} - -static int ak4642_sync(struct snd_soc_codec *codec) -{ - u16 *cache = codec->reg_cache; - int i, r = 0; - - for (i = 0; i < AK4642_CACHEREGNUM; i++) - r |= ak4642_write(codec, i, cache[i]); - - return r; -}; - -static int ak4642_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct snd_soc_codec *codec = dai->codec; - - if (is_play) { - /* - * start headphone output - * - * PLL, Master Mode - * Audio I/F Format :MSB justified (ADC & DAC) - * Sampling Frequency: 44.1kHz - * Digital Volume: −8dB - * Bass Boost Level : Middle - * - * This operation came from example code of - * "ASAHI KASEI AK4642" (japanese) manual p97. - * - * Example code use 0x39, 0x79 value for 0x01 address, - * But we need MCKO (0x02) bit now - */ - ak4642_write(codec, 0x05, 0x27); - ak4642_write(codec, 0x0f, 0x09); - ak4642_write(codec, 0x0e, 0x19); - ak4642_write(codec, 0x09, 0x91); - ak4642_write(codec, 0x0c, 0x91); - ak4642_write(codec, 0x0a, 0x28); - ak4642_write(codec, 0x0d, 0x28); - ak4642_write(codec, 0x00, 0x64); - ak4642_write(codec, 0x01, 0x3b); /* + MCKO bit */ - ak4642_write(codec, 0x01, 0x7b); /* + MCKO bit */ - } else { - /* - * start stereo input - * - * PLL Master Mode - * Audio I/F Format:MSB justified (ADC & DAC) - * Sampling Frequency:44.1kHz - * Pre MIC AMP:+20dB - * MIC Power On - * ALC setting:Refer to Table 35 - * ALC bit=“1” - * - * This operation came from example code of - * "ASAHI KASEI AK4642" (japanese) manual p94. - */ - ak4642_write(codec, 0x05, 0x27); - ak4642_write(codec, 0x02, 0x05); - ak4642_write(codec, 0x06, 0x3c); - ak4642_write(codec, 0x08, 0xe1); - ak4642_write(codec, 0x0b, 0x00); - ak4642_write(codec, 0x07, 0x21); - ak4642_write(codec, 0x00, 0x41); - ak4642_write(codec, 0x10, 0x01); - } - - return 0; -} - -static void ak4642_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct snd_soc_codec *codec = dai->codec; - - if (is_play) { - /* stop headphone output */ - ak4642_write(codec, 0x01, 0x3b); - ak4642_write(codec, 0x01, 0x0b); - ak4642_write(codec, 0x00, 0x40); - ak4642_write(codec, 0x0e, 0x11); - ak4642_write(codec, 0x0f, 0x08); - } else { - /* stop stereo input */ - ak4642_write(codec, 0x00, 0x40); - ak4642_write(codec, 0x10, 0x00); - ak4642_write(codec, 0x07, 0x01); - } -} - -static int ak4642_dai_set_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct ak4642_priv *ak4642 = codec->private_data; - - ak4642->sysclk = freq; - return 0; -} - -static struct snd_soc_dai_ops ak4642_dai_ops = { - .startup = ak4642_dai_startup, - .shutdown = ak4642_dai_shutdown, - .set_sysclk = ak4642_dai_set_sysclk, -}; - -struct snd_soc_dai ak4642_dai = { - .name = "AK4642", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = SNDRV_PCM_RATE_8000_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE }, - .ops = &ak4642_dai_ops, -}; -EXPORT_SYMBOL_GPL(ak4642_dai); - -static int ak4642_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - ak4642_sync(codec); - return 0; -} - -/* - * initialise the AK4642 driver - * register the mixer and dsp interfaces with the kernel - */ -static int ak4642_init(struct ak4642_priv *ak4642) -{ - struct snd_soc_codec *codec = &ak4642->codec; - int ret = 0; - - if (ak4642_codec) { - dev_err(codec->dev, "Another ak4642 is registered\n"); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->private_data = ak4642; - codec->name = "AK4642"; - codec->owner = THIS_MODULE; - codec->read = ak4642_read_reg_cache; - codec->write = ak4642_write; - codec->dai = &ak4642_dai; - codec->num_dai = 1; - codec->hw_write = (hw_write_t)i2c_master_send; - codec->reg_cache_size = ARRAY_SIZE(ak4642_reg); - codec->reg_cache = kmemdup(ak4642_reg, - sizeof(ak4642_reg), GFP_KERNEL); - - if (!codec->reg_cache) - return -ENOMEM; - - ak4642_dai.dev = codec->dev; - ak4642_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto reg_cache_err; - } - - ret = snd_soc_register_dai(&ak4642_dai); - if (ret) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - goto reg_cache_err; - } - - /* - * clock setting - * - * Audio I/F Format: MSB justified (ADC & DAC) - * BICK frequency at Master Mode: 64fs - * Input Master Clock Select at PLL Mode: 11.2896MHz - * MCKO: Enable - * Sampling Frequency: 44.1kHz - * - * This operation came from example code of - * "ASAHI KASEI AK4642" (japanese) manual p89. - * - * please fix-me - */ - ak4642_write(codec, 0x01, 0x08); - ak4642_write(codec, 0x04, 0x4a); - ak4642_write(codec, 0x05, 0x27); - ak4642_write(codec, 0x00, 0x40); - ak4642_write(codec, 0x01, 0x0b); - - return ret; - -reg_cache_err: - kfree(codec->reg_cache); - codec->reg_cache = NULL; - - return ret; -} - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static int ak4642_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct ak4642_priv *ak4642; - struct snd_soc_codec *codec; - int ret; - - ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL); - if (!ak4642) - return -ENOMEM; - - codec = &ak4642->codec; - codec->dev = &i2c->dev; - - i2c_set_clientdata(i2c, ak4642); - codec->control_data = i2c; - - ret = ak4642_init(ak4642); - if (ret < 0) - printk(KERN_ERR "failed to initialise AK4642\n"); - - return ret; -} - -static int ak4642_i2c_remove(struct i2c_client *client) -{ - struct ak4642_priv *ak4642 = i2c_get_clientdata(client); - - snd_soc_unregister_dai(&ak4642_dai); - snd_soc_unregister_codec(&ak4642->codec); - kfree(ak4642->codec.reg_cache); - kfree(ak4642); - ak4642_codec = NULL; - - return 0; -} - -static const struct i2c_device_id ak4642_i2c_id[] = { - { "ak4642", 0 }, - { "ak4643", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id); - -static struct i2c_driver ak4642_i2c_driver = { - .driver = { - .name = "AK4642 I2C Codec", - .owner = THIS_MODULE, - }, - .probe = ak4642_i2c_probe, - .remove = ak4642_i2c_remove, - .id_table = ak4642_i2c_id, -}; - -#endif - -static int ak4642_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - int ret; - - if (!ak4642_codec) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = ak4642_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "ak4642: failed to create pcms\n"); - goto pcm_err; - } - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - printk(KERN_ERR "ak4642: failed to register card\n"); - goto card_err; - } - - dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; - -} - -/* power down chip */ -static int ak4642_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_ak4642 = { - .probe = ak4642_probe, - .remove = ak4642_remove, - .resume = ak4642_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_ak4642); - -static int __init ak4642_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&ak4642_i2c_driver); -#endif - return ret; - -} -module_init(ak4642_modinit); - -static void __exit ak4642_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&ak4642_i2c_driver); -#endif - -} -module_exit(ak4642_exit); - -MODULE_DESCRIPTION("Soc AK4642 driver"); -MODULE_AUTHOR("Kuninori Morimoto "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/ak4642.h b/trunk/sound/soc/codecs/ak4642.h deleted file mode 100644 index e476833d314e..000000000000 --- a/trunk/sound/soc/codecs/ak4642.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * ak4642.h -- AK4642 Soc Audio driver - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto - * - * Based on ak4535.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _AK4642_H -#define _AK4642_H - -extern struct snd_soc_dai ak4642_dai; -extern struct snd_soc_codec_device soc_codec_dev_ak4642; - -#endif diff --git a/trunk/sound/soc/codecs/cs4270.c b/trunk/sound/soc/codecs/cs4270.c index ca1e24a8f12a..a32b8226c8a4 100644 --- a/trunk/sound/soc/codecs/cs4270.c +++ b/trunk/sound/soc/codecs/cs4270.c @@ -806,30 +806,15 @@ static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg) { struct cs4270_private *cs4270 = i2c_get_clientdata(client); struct snd_soc_codec *codec = &cs4270->codec; + int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; - return snd_soc_suspend_device(codec->dev); + return snd_soc_write(codec, CS4270_PWRCTL, reg); } static int cs4270_i2c_resume(struct i2c_client *client) { struct cs4270_private *cs4270 = i2c_get_clientdata(client); struct snd_soc_codec *codec = &cs4270->codec; - - return snd_soc_resume_device(codec->dev); -} - -static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - struct snd_soc_codec *codec = cs4270_codec; - int reg = snd_soc_read(codec, CS4270_PWRCTL) | CS4270_PWRCTL_PDN_ALL; - - return snd_soc_write(codec, CS4270_PWRCTL, reg); -} - -static int cs4270_soc_resume(struct platform_device *pdev) -{ - struct snd_soc_codec *codec = cs4270_codec; - struct i2c_client *i2c_client = codec->control_data; int reg; /* In case the device was put to hard reset during sleep, we need to @@ -840,7 +825,7 @@ static int cs4270_soc_resume(struct platform_device *pdev) for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) { u8 val = snd_soc_read(codec, reg); - if (i2c_smbus_write_byte_data(i2c_client, reg, val)) { + if (i2c_smbus_write_byte_data(client, reg, val)) { dev_err(codec->dev, "i2c write failed\n"); return -EIO; } @@ -855,8 +840,6 @@ static int cs4270_soc_resume(struct platform_device *pdev) #else #define cs4270_i2c_suspend NULL #define cs4270_i2c_resume NULL -#define cs4270_soc_suspend NULL -#define cs4270_soc_resume NULL #endif /* CONFIG_PM */ /* @@ -885,9 +868,7 @@ static struct i2c_driver cs4270_i2c_driver = { */ struct snd_soc_codec_device soc_codec_device_cs4270 = { .probe = cs4270_probe, - .remove = cs4270_remove, - .suspend = cs4270_soc_suspend, - .resume = cs4270_soc_resume, + .remove = cs4270_remove }; EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); diff --git a/trunk/sound/soc/codecs/cx20442.c b/trunk/sound/soc/codecs/cx20442.c deleted file mode 100644 index 38eac9c866e1..000000000000 --- a/trunk/sound/soc/codecs/cx20442.c +++ /dev/null @@ -1,501 +0,0 @@ -/* - * cx20442.c -- CX20442 ALSA Soc Audio driver - * - * Copyright 2009 Janusz Krzysztofik - * - * Initially based on sound/soc/codecs/wm8400.c - * Copyright 2008, 2009 Wolfson Microelectronics PLC. - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include - -#include -#include -#include - -#include "cx20442.h" - - -struct cx20442_priv { - struct snd_soc_codec codec; - u8 reg_cache[1]; -}; - -#define CX20442_PM 0x0 - -#define CX20442_TELIN 0 -#define CX20442_TELOUT 1 -#define CX20442_MIC 2 -#define CX20442_SPKOUT 3 -#define CX20442_AGC 4 - -static const struct snd_soc_dapm_widget cx20442_dapm_widgets[] = { - SND_SOC_DAPM_OUTPUT("TELOUT"), - SND_SOC_DAPM_OUTPUT("SPKOUT"), - SND_SOC_DAPM_OUTPUT("AGCOUT"), - - SND_SOC_DAPM_MIXER("SPKOUT Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_PGA("TELOUT Amp", CX20442_PM, CX20442_TELOUT, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPKOUT Amp", CX20442_PM, CX20442_SPKOUT, 0, NULL, 0), - SND_SOC_DAPM_PGA("SPKOUT AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0), - - SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), - SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), - - SND_SOC_DAPM_MIXER("Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), - - SND_SOC_DAPM_MICBIAS("TELIN Bias", CX20442_PM, CX20442_TELIN, 0), - SND_SOC_DAPM_MICBIAS("MIC Bias", CX20442_PM, CX20442_MIC, 0), - - SND_SOC_DAPM_PGA("MIC AGC", CX20442_PM, CX20442_AGC, 0, NULL, 0), - - SND_SOC_DAPM_INPUT("TELIN"), - SND_SOC_DAPM_INPUT("MIC"), - SND_SOC_DAPM_INPUT("AGCIN"), -}; - -static const struct snd_soc_dapm_route cx20442_audio_map[] = { - {"TELOUT", NULL, "TELOUT Amp"}, - - {"SPKOUT", NULL, "SPKOUT Mixer"}, - {"SPKOUT Mixer", NULL, "SPKOUT Amp"}, - - {"TELOUT Amp", NULL, "DAC"}, - {"SPKOUT Amp", NULL, "DAC"}, - - {"SPKOUT Mixer", NULL, "SPKOUT AGC"}, - {"SPKOUT AGC", NULL, "AGCIN"}, - - {"AGCOUT", NULL, "MIC AGC"}, - {"MIC AGC", NULL, "MIC"}, - - {"MIC Bias", NULL, "MIC"}, - {"Input Mixer", NULL, "MIC Bias"}, - - {"TELIN Bias", NULL, "TELIN"}, - {"Input Mixer", NULL, "TELIN Bias"}, - - {"ADC", NULL, "Input Mixer"}, -}; - -static int cx20442_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, cx20442_dapm_widgets, - ARRAY_SIZE(cx20442_dapm_widgets)); - - snd_soc_dapm_add_routes(codec, cx20442_audio_map, - ARRAY_SIZE(cx20442_audio_map)); - - snd_soc_dapm_new_widgets(codec); - return 0; -} - -static unsigned int cx20442_read_reg_cache(struct snd_soc_codec *codec, - unsigned int reg) -{ - u8 *reg_cache = codec->reg_cache; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - return reg_cache[reg]; -} - -enum v253_vls { - V253_VLS_NONE = 0, - V253_VLS_T, - V253_VLS_L, - V253_VLS_LT, - V253_VLS_S, - V253_VLS_ST, - V253_VLS_M, - V253_VLS_MST, - V253_VLS_S1, - V253_VLS_S1T, - V253_VLS_MS1T, - V253_VLS_M1, - V253_VLS_M1ST, - V253_VLS_M1S1T, - V253_VLS_H, - V253_VLS_HT, - V253_VLS_MS, - V253_VLS_MS1, - V253_VLS_M1S, - V253_VLS_M1S1, - V253_VLS_TEST, -}; - -static int cx20442_pm_to_v253_vls(u8 value) -{ - switch (value & ~(1 << CX20442_AGC)) { - case 0: - return V253_VLS_T; - case (1 << CX20442_SPKOUT): - case (1 << CX20442_MIC): - case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC): - return V253_VLS_M1S1; - case (1 << CX20442_TELOUT): - case (1 << CX20442_TELIN): - case (1 << CX20442_TELOUT) | (1 << CX20442_TELIN): - return V253_VLS_L; - case (1 << CX20442_TELOUT) | (1 << CX20442_MIC): - return V253_VLS_NONE; - } - return -EINVAL; -} -static int cx20442_pm_to_v253_vsp(u8 value) -{ - switch (value & ~(1 << CX20442_AGC)) { - case (1 << CX20442_SPKOUT): - case (1 << CX20442_MIC): - case (1 << CX20442_SPKOUT) | (1 << CX20442_MIC): - return (bool)(value & (1 << CX20442_AGC)); - } - return (value & (1 << CX20442_AGC)) ? -EINVAL : 0; -} - -static int cx20442_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u8 *reg_cache = codec->reg_cache; - int vls, vsp, old, len; - char buf[18]; - - if (reg >= codec->reg_cache_size) - return -EINVAL; - - /* hw_write and control_data pointers required for talking to the modem - * are expected to be set by the line discipline initialization code */ - if (!codec->hw_write || !codec->control_data) - return -EIO; - - old = reg_cache[reg]; - reg_cache[reg] = value; - - vls = cx20442_pm_to_v253_vls(value); - if (vls < 0) - return vls; - - vsp = cx20442_pm_to_v253_vsp(value); - if (vsp < 0) - return vsp; - - if ((vls == V253_VLS_T) || - (vls == cx20442_pm_to_v253_vls(old))) { - if (vsp == cx20442_pm_to_v253_vsp(old)) - return 0; - len = snprintf(buf, ARRAY_SIZE(buf), "at+vsp=%d\r", vsp); - } else if (vsp == cx20442_pm_to_v253_vsp(old)) - len = snprintf(buf, ARRAY_SIZE(buf), "at+vls=%d\r", vls); - else - len = snprintf(buf, ARRAY_SIZE(buf), - "at+vls=%d;+vsp=%d\r", vls, vsp); - - if (unlikely(len > (ARRAY_SIZE(buf) - 1))) - return -ENOMEM; - - dev_dbg(codec->dev, "%s: %s\n", __func__, buf); - if (codec->hw_write(codec->control_data, buf, len) != len) - return -EIO; - - return 0; -} - - -/* Moved up here as line discipline referres it during initialization */ -static struct snd_soc_codec *cx20442_codec; - - -/* - * Line discpline related code - * - * Any of the callback functions below can be used in two ways: - * 1) registerd by a machine driver as one of line discipline operations, - * 2) called from a machine's provided line discipline callback function - * in case when extra machine specific code must be run as well. - */ - -/* Modem init: echo off, digital speaker off, quiet off, voice mode */ -static const char *v253_init = "ate0m0q0+fclass=8\r"; - -/* Line discipline .open() */ -static int v253_open(struct tty_struct *tty) -{ - struct snd_soc_codec *codec = cx20442_codec; - int ret, len = strlen(v253_init); - - /* Doesn't make sense without write callback */ - if (!tty->ops->write) - return -EINVAL; - - /* Pass the codec structure address for use by other ldisc callbacks */ - tty->disc_data = codec; - - if (tty->ops->write(tty, v253_init, len) != len) { - ret = -EIO; - goto err; - } - /* Actual setup will be performed after the modem responds. */ - return 0; -err: - tty->disc_data = NULL; - return ret; -} - -/* Line discipline .close() */ -static void v253_close(struct tty_struct *tty) -{ - struct snd_soc_codec *codec = tty->disc_data; - - tty->disc_data = NULL; - - if (!codec) - return; - - /* Prevent the codec driver from further accessing the modem */ - codec->hw_write = NULL; - codec->control_data = NULL; - codec->pop_time = 0; -} - -/* Line discipline .hangup() */ -static int v253_hangup(struct tty_struct *tty) -{ - v253_close(tty); - return 0; -} - -/* Line discipline .receive_buf() */ -static void v253_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) -{ - struct snd_soc_codec *codec = tty->disc_data; - - if (!codec) - return; - - if (!codec->control_data) { - /* First modem response, complete setup procedure */ - - /* Set up codec driver access to modem controls */ - codec->control_data = tty; - codec->hw_write = (hw_write_t)tty->ops->write; - codec->pop_time = 1; - } -} - -/* Line discipline .write_wakeup() */ -static void v253_wakeup(struct tty_struct *tty) -{ -} - -struct tty_ldisc_ops v253_ops = { - .magic = TTY_LDISC_MAGIC, - .name = "cx20442", - .owner = THIS_MODULE, - .open = v253_open, - .close = v253_close, - .hangup = v253_hangup, - .receive_buf = v253_receive, - .write_wakeup = v253_wakeup, -}; -EXPORT_SYMBOL_GPL(v253_ops); - - -/* - * Codec DAI - */ - -struct snd_soc_dai cx20442_dai = { - .name = "CX20442", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, -}; -EXPORT_SYMBOL_GPL(cx20442_dai); - -static int cx20442_codec_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret; - - if (!cx20442_codec) { - dev_err(&pdev->dev, "cx20442 not yet discovered\n"); - return -ENODEV; - } - codec = cx20442_codec; - - socdev->card->codec = codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(&pdev->dev, "failed to create pcms\n"); - goto pcm_err; - } - - cx20442_add_widgets(codec); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register card\n"); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int cx20442_codec_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device cx20442_codec_dev = { - .probe = cx20442_codec_probe, - .remove = cx20442_codec_remove, -}; -EXPORT_SYMBOL_GPL(cx20442_codec_dev); - -static int cx20442_register(struct cx20442_priv *cx20442) -{ - struct snd_soc_codec *codec = &cx20442->codec; - int ret; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "CX20442"; - codec->owner = THIS_MODULE; - codec->private_data = cx20442; - - codec->dai = &cx20442_dai; - codec->num_dai = 1; - - codec->reg_cache = &cx20442->reg_cache; - codec->reg_cache_size = ARRAY_SIZE(cx20442->reg_cache); - codec->read = cx20442_read_reg_cache; - codec->write = cx20442_write; - - codec->bias_level = SND_SOC_BIAS_OFF; - - cx20442_dai.dev = codec->dev; - - cx20442_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&cx20442_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - cx20442_codec = NULL; - kfree(cx20442); - return ret; -} - -static void cx20442_unregister(struct cx20442_priv *cx20442) -{ - snd_soc_unregister_dai(&cx20442_dai); - snd_soc_unregister_codec(&cx20442->codec); - - cx20442_codec = NULL; - kfree(cx20442); -} - -static int cx20442_platform_probe(struct platform_device *pdev) -{ - struct cx20442_priv *cx20442; - struct snd_soc_codec *codec; - - cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL); - if (cx20442 == NULL) - return -ENOMEM; - - codec = &cx20442->codec; - - codec->control_data = NULL; - codec->hw_write = NULL; - codec->pop_time = 0; - - codec->dev = &pdev->dev; - platform_set_drvdata(pdev, cx20442); - - return cx20442_register(cx20442); -} - -static int __exit cx20442_platform_remove(struct platform_device *pdev) -{ - struct cx20442_priv *cx20442 = platform_get_drvdata(pdev); - - cx20442_unregister(cx20442); - return 0; -} - -static struct platform_driver cx20442_platform_driver = { - .driver = { - .name = "cx20442", - .owner = THIS_MODULE, - }, - .probe = cx20442_platform_probe, - .remove = __exit_p(cx20442_platform_remove), -}; - -static int __init cx20442_init(void) -{ - return platform_driver_register(&cx20442_platform_driver); -} -module_init(cx20442_init); - -static void __exit cx20442_exit(void) -{ - platform_driver_unregister(&cx20442_platform_driver); -} -module_exit(cx20442_exit); - -MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver"); -MODULE_AUTHOR("Janusz Krzysztofik"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:cx20442"); diff --git a/trunk/sound/soc/codecs/cx20442.h b/trunk/sound/soc/codecs/cx20442.h deleted file mode 100644 index 688a5eb62e17..000000000000 --- a/trunk/sound/soc/codecs/cx20442.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * cx20442.h -- audio driver for CX20442 - * - * Copyright 2009 Janusz Krzysztofik - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#ifndef _CX20442_CODEC_H -#define _CX20442_CODEC_H - -extern struct snd_soc_dai cx20442_dai; -extern struct snd_soc_codec_device cx20442_codec_dev; -extern struct tty_ldisc_ops v253_ops; - -#endif diff --git a/trunk/sound/soc/codecs/max9877.c b/trunk/sound/soc/codecs/max9877.c deleted file mode 100644 index 9e7e964a5fa3..000000000000 --- a/trunk/sound/soc/codecs/max9877.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * max9877.c -- amp driver for max9877 - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include - -#include "max9877.h" - -static struct i2c_client *i2c; - -static u8 max9877_regs[5] = { 0x40, 0x00, 0x00, 0x00, 0x49 }; - -static void max9877_write_regs(void) -{ - unsigned int i; - u8 data[6]; - - data[0] = MAX9877_INPUT_MODE; - for (i = 0; i < ARRAY_SIZE(max9877_regs); i++) - data[i + 1] = max9877_regs[i]; - - if (i2c_master_send(i2c, data, 6) != 6) - dev_err(&i2c->dev, "i2c write failed\n"); -} - -static int max9877_get_reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int invert = mc->invert; - - ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; - - if (invert) - ucontrol->value.integer.value[0] = - mask - ucontrol->value.integer.value[0]; - - return 0; -} - -static int max9877_set_reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int invert = mc->invert; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - - if (invert) - val = mask - val; - - if (((max9877_regs[reg] >> shift) & mask) == val) - return 0; - - max9877_regs[reg] &= ~(mask << shift); - max9877_regs[reg] |= val << shift; - max9877_write_regs(); - - return 1; -} - -static int max9877_get_2reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - - ucontrol->value.integer.value[0] = (max9877_regs[reg] >> shift) & mask; - ucontrol->value.integer.value[1] = (max9877_regs[reg2] >> shift) & mask; - - return 0; -} - -static int max9877_set_2reg(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct soc_mixer_control *mc = - (struct soc_mixer_control *)kcontrol->private_value; - unsigned int reg = mc->reg; - unsigned int reg2 = mc->rreg; - unsigned int shift = mc->shift; - unsigned int mask = mc->max; - unsigned int val = (ucontrol->value.integer.value[0] & mask); - unsigned int val2 = (ucontrol->value.integer.value[1] & mask); - unsigned int change = 1; - - if (((max9877_regs[reg] >> shift) & mask) == val) - change = 0; - - if (((max9877_regs[reg2] >> shift) & mask) == val2) - change = 0; - - if (change) { - max9877_regs[reg] &= ~(mask << shift); - max9877_regs[reg] |= val << shift; - max9877_regs[reg2] &= ~(mask << shift); - max9877_regs[reg2] |= val2 << shift; - max9877_write_regs(); - } - - return change; -} - -static int max9877_get_out_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK; - - if (value) - value -= 1; - - ucontrol->value.integer.value[0] = value; - return 0; -} - -static int max9877_set_out_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = ucontrol->value.integer.value[0]; - - value += 1; - - if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OUTMODE_MASK) == value) - return 0; - - max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OUTMODE_MASK; - max9877_regs[MAX9877_OUTPUT_MODE] |= value; - max9877_write_regs(); - return 1; -} - -static int max9877_get_osc_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = (max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK); - - value = value >> MAX9877_OSC_OFFSET; - - ucontrol->value.integer.value[0] = value; - return 0; -} - -static int max9877_set_osc_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - u8 value = ucontrol->value.integer.value[0]; - - value = value << MAX9877_OSC_OFFSET; - if ((max9877_regs[MAX9877_OUTPUT_MODE] & MAX9877_OSC_MASK) == value) - return 0; - - max9877_regs[MAX9877_OUTPUT_MODE] &= ~MAX9877_OSC_MASK; - max9877_regs[MAX9877_OUTPUT_MODE] |= value; - max9877_write_regs(); - return 1; -} - -static const unsigned int max9877_pgain_tlv[] = { - TLV_DB_RANGE_HEAD(2), - 0, 1, TLV_DB_SCALE_ITEM(0, 900, 0), - 2, 2, TLV_DB_SCALE_ITEM(2000, 0, 0), -}; - -static const unsigned int max9877_output_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), - 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), - 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), - 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), -}; - -static const char *max9877_out_mode[] = { - "INA -> SPK", - "INA -> HP", - "INA -> SPK and HP", - "INB -> SPK", - "INB -> HP", - "INB -> SPK and HP", - "INA + INB -> SPK", - "INA + INB -> HP", - "INA + INB -> SPK and HP", -}; - -static const char *max9877_osc_mode[] = { - "1176KHz", - "1100KHz", - "700KHz", -}; - -static const struct soc_enum max9877_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_out_mode), max9877_out_mode), - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(max9877_osc_mode), max9877_osc_mode), -}; - -static const struct snd_kcontrol_new max9877_controls[] = { - SOC_SINGLE_EXT_TLV("MAX9877 PGAINA Playback Volume", - MAX9877_INPUT_MODE, 0, 2, 0, - max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), - SOC_SINGLE_EXT_TLV("MAX9877 PGAINB Playback Volume", - MAX9877_INPUT_MODE, 2, 2, 0, - max9877_get_reg, max9877_set_reg, max9877_pgain_tlv), - SOC_SINGLE_EXT_TLV("MAX9877 Amp Speaker Playback Volume", - MAX9877_SPK_VOLUME, 0, 31, 0, - max9877_get_reg, max9877_set_reg, max9877_output_tlv), - SOC_DOUBLE_R_EXT_TLV("MAX9877 Amp HP Playback Volume", - MAX9877_HPL_VOLUME, MAX9877_HPR_VOLUME, 0, 31, 0, - max9877_get_2reg, max9877_set_2reg, max9877_output_tlv), - SOC_SINGLE_EXT("MAX9877 INB Stereo Switch", - MAX9877_INPUT_MODE, 4, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 INA Stereo Switch", - MAX9877_INPUT_MODE, 5, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Zero-crossing detection Switch", - MAX9877_INPUT_MODE, 6, 1, 0, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Bypass Mode Switch", - MAX9877_OUTPUT_MODE, 6, 1, 0, - max9877_get_reg, max9877_set_reg), - SOC_SINGLE_EXT("MAX9877 Shutdown Mode Switch", - MAX9877_OUTPUT_MODE, 7, 1, 1, - max9877_get_reg, max9877_set_reg), - SOC_ENUM_EXT("MAX9877 Output Mode", max9877_enum[0], - max9877_get_out_mode, max9877_set_out_mode), - SOC_ENUM_EXT("MAX9877 Oscillator Mode", max9877_enum[1], - max9877_get_osc_mode, max9877_set_osc_mode), -}; - -/* This function is called from ASoC machine driver */ -int max9877_add_controls(struct snd_soc_codec *codec) -{ - return snd_soc_add_controls(codec, max9877_controls, - ARRAY_SIZE(max9877_controls)); -} -EXPORT_SYMBOL_GPL(max9877_add_controls); - -static int __devinit max9877_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - i2c = client; - - max9877_write_regs(); - - return 0; -} - -static __devexit int max9877_i2c_remove(struct i2c_client *client) -{ - i2c = NULL; - - return 0; -} - -static const struct i2c_device_id max9877_i2c_id[] = { - { "max9877", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max9877_i2c_id); - -static struct i2c_driver max9877_i2c_driver = { - .driver = { - .name = "max9877", - .owner = THIS_MODULE, - }, - .probe = max9877_i2c_probe, - .remove = __devexit_p(max9877_i2c_remove), - .id_table = max9877_i2c_id, -}; - -static int __init max9877_init(void) -{ - return i2c_add_driver(&max9877_i2c_driver); -} -module_init(max9877_init); - -static void __exit max9877_exit(void) -{ - i2c_del_driver(&max9877_i2c_driver); -} -module_exit(max9877_exit); - -MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); -MODULE_AUTHOR("Joonyoung Shim "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/max9877.h b/trunk/sound/soc/codecs/max9877.h deleted file mode 100644 index 6da72290ac58..000000000000 --- a/trunk/sound/soc/codecs/max9877.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * max9877.h -- amp driver for max9877 - * - * Copyright (C) 2009 Samsung Electronics Co.Ltd - * Author: Joonyoung Shim - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#ifndef _MAX9877_H -#define _MAX9877_H - -#define MAX9877_INPUT_MODE 0x00 -#define MAX9877_SPK_VOLUME 0x01 -#define MAX9877_HPL_VOLUME 0x02 -#define MAX9877_HPR_VOLUME 0x03 -#define MAX9877_OUTPUT_MODE 0x04 - -/* MAX9877_INPUT_MODE */ -#define MAX9877_INB (1 << 4) -#define MAX9877_INA (1 << 5) -#define MAX9877_ZCD (1 << 6) - -/* MAX9877_OUTPUT_MODE */ -#define MAX9877_OUTMODE_MASK (15 << 0) -#define MAX9877_OSC_MASK (3 << 4) -#define MAX9877_OSC_OFFSET 4 -#define MAX9877_BYPASS (1 << 6) -#define MAX9877_SHDN (1 << 7) - -extern int max9877_add_controls(struct snd_soc_codec *codec); - -#endif diff --git a/trunk/sound/soc/codecs/spdif_transciever.c b/trunk/sound/soc/codecs/spdif_transciever.c index a63191141052..218b33adad90 100644 --- a/trunk/sound/soc/codecs/spdif_transciever.c +++ b/trunk/sound/soc/codecs/spdif_transciever.c @@ -21,8 +21,6 @@ #include "spdif_transciever.h" -MODULE_LICENSE("GPL"); - #define STUB_RATES SNDRV_PCM_RATE_8000_96000 #define STUB_FORMATS SNDRV_PCM_FMTBIT_S16_LE @@ -36,7 +34,6 @@ struct snd_soc_dai dit_stub_dai = { .formats = STUB_FORMATS, }, }; -EXPORT_SYMBOL_GPL(dit_stub_dai); static int spdif_dit_probe(struct platform_device *pdev) { diff --git a/trunk/sound/soc/codecs/stac9766.c b/trunk/sound/soc/codecs/stac9766.c index befc6488c39a..8ad4b7b3e3ba 100644 --- a/trunk/sound/soc/codecs/stac9766.c +++ b/trunk/sound/soc/codecs/stac9766.c @@ -149,7 +149,7 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, stac9766_ac97_write(codec, AC97_INT_PAGING, 1); return 0; } - if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) + if (reg / 2 > ARRAY_SIZE(stac9766_reg)) return -EIO; soc_ac97_ops.write(codec->ac97, reg, val); @@ -168,7 +168,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, stac9766_ac97_write(codec, AC97_INT_PAGING, 1); return val; } - if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) + if (reg / 2 > ARRAY_SIZE(stac9766_reg)) return -EIO; if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || diff --git a/trunk/sound/soc/codecs/tlv320aic3x.c b/trunk/sound/soc/codecs/tlv320aic3x.c index 3395cf945d56..cb0d1bf34b57 100644 --- a/trunk/sound/soc/codecs/tlv320aic3x.c +++ b/trunk/sound/soc/codecs/tlv320aic3x.c @@ -53,7 +53,6 @@ /* codec private data */ struct aic3x_priv { - struct snd_soc_codec codec; unsigned int sysclk; int master; }; @@ -146,8 +145,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg, u8 *value) { *value = reg & 0xff; - - value[0] = i2c_smbus_read_byte_data(codec->control_data, value[0]); + if (codec->hw_read(codec->control_data, value, 1) != 1) + return -EIO; aic3x_write_reg_cache(codec, reg, *value); return 0; @@ -1157,13 +1156,11 @@ static int aic3x_resume(struct platform_device *pdev) * initialise the AIC3X driver * register the mixer and dsp interfaces with the kernel */ -static int aic3x_init(struct snd_soc_codec *codec) +static int aic3x_init(struct snd_soc_device *socdev) { - int reg; - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); + struct snd_soc_codec *codec = socdev->card->codec; + struct aic3x_setup_data *setup = socdev->codec_data; + int reg, ret = 0; codec->name = "tlv320aic3x"; codec->owner = THIS_MODULE; @@ -1180,6 +1177,13 @@ static int aic3x_init(struct snd_soc_codec *codec) aic3x_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT); aic3x_write(codec, AIC3X_RESET, SOFT_RESET); + /* register pcms */ + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); + if (ret < 0) { + printk(KERN_ERR "aic3x: failed to create pcms\n"); + goto pcm_err; + } + /* DAC default volume and mute */ aic3x_write(codec, LDAC_VOL, DEFAULT_VOL | MUTE_ON); aic3x_write(codec, RDAC_VOL, DEFAULT_VOL | MUTE_ON); @@ -1246,51 +1250,30 @@ static int aic3x_init(struct snd_soc_codec *codec) /* off, with power on */ aic3x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; -} + /* setup GPIO functions */ + aic3x_write(codec, AIC3X_GPIO1_REG, (setup->gpio_func[0] & 0xf) << 4); + aic3x_write(codec, AIC3X_GPIO2_REG, (setup->gpio_func[1] & 0xf) << 4); -static struct snd_soc_codec *aic3x_codec; - -static int aic3x_register(struct snd_soc_codec *codec) -{ - int ret; - - ret = aic3x_init(codec); + snd_soc_add_controls(codec, aic3x_snd_controls, + ARRAY_SIZE(aic3x_snd_controls)); + aic3x_add_widgets(codec); + ret = snd_soc_init_card(socdev); if (ret < 0) { - dev_err(codec->dev, "Failed to initialise device\n"); - return ret; - } - - aic3x_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret) { - dev_err(codec->dev, "Failed to register codec\n"); - return ret; + printk(KERN_ERR "aic3x: failed to register card\n"); + goto card_err; } - ret = snd_soc_register_dai(&aic3x_dai); - if (ret) { - dev_err(codec->dev, "Failed to register dai\n"); - snd_soc_unregister_codec(codec); - return ret; - } + return ret; - return 0; +card_err: + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +pcm_err: + kfree(codec->reg_cache); + return ret; } -static int aic3x_unregister(struct aic3x_priv *aic3x) -{ - aic3x_set_bias_level(&aic3x->codec, SND_SOC_BIAS_OFF); - - snd_soc_unregister_dai(&aic3x_dai); - snd_soc_unregister_codec(&aic3x->codec); - - kfree(aic3x); - aic3x_codec = NULL; - - return 0; -} +static struct snd_soc_device *aic3x_socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) /* @@ -1305,36 +1288,28 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) static int aic3x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct snd_soc_codec *codec; - struct aic3x_priv *aic3x; - - aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); - if (aic3x == NULL) { - dev_err(&i2c->dev, "failed to create private data\n"); - return -ENOMEM; - } + struct snd_soc_device *socdev = aic3x_socdev; + struct snd_soc_codec *codec = socdev->card->codec; + int ret; - codec = &aic3x->codec; - codec->dev = &i2c->dev; - codec->private_data = aic3x; + i2c_set_clientdata(i2c, codec); codec->control_data = i2c; - codec->hw_write = (hw_write_t) i2c_master_send; - i2c_set_clientdata(i2c, aic3x); - - return aic3x_register(codec); + ret = aic3x_init(socdev); + if (ret < 0) + printk(KERN_ERR "aic3x: failed to initialise AIC3X\n"); + return ret; } static int aic3x_i2c_remove(struct i2c_client *client) { - struct aic3x_priv *aic3x = i2c_get_clientdata(client); - - return aic3x_unregister(aic3x); + struct snd_soc_codec *codec = i2c_get_clientdata(client); + kfree(codec->reg_cache); + return 0; } static const struct i2c_device_id aic3x_i2c_id[] = { { "tlv320aic3x", 0 }, - { "tlv320aic33", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); @@ -1345,28 +1320,56 @@ static struct i2c_driver aic3x_i2c_driver = { .name = "aic3x I2C Codec", .owner = THIS_MODULE, }, - .probe = aic3x_i2c_probe, + .probe = aic3x_i2c_probe, .remove = aic3x_i2c_remove, .id_table = aic3x_i2c_id, }; -static inline void aic3x_i2c_init(void) +static int aic3x_i2c_read(struct i2c_client *client, u8 *value, int len) { + value[0] = i2c_smbus_read_byte_data(client, value[0]); + return (len == 1); +} + +static int aic3x_add_i2c_device(struct platform_device *pdev, + const struct aic3x_setup_data *setup) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter; + struct i2c_client *client; int ret; ret = i2c_add_driver(&aic3x_i2c_driver); - if (ret) - printk(KERN_ERR "%s: error regsitering i2c driver, %d\n", - __func__, ret); -} + if (ret != 0) { + dev_err(&pdev->dev, "can't add i2c driver\n"); + return ret; + } -static inline void aic3x_i2c_exit(void) -{ + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = setup->i2c_address; + strlcpy(info.type, "tlv320aic3x", I2C_NAME_SIZE); + + adapter = i2c_get_adapter(setup->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "can't get i2c adapter %d\n", + setup->i2c_bus); + goto err_driver; + } + + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) { + dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", + (unsigned int)info.addr); + goto err_driver; + } + + return 0; + +err_driver: i2c_del_driver(&aic3x_i2c_driver); + return -ENODEV; } -#else -static inline void aic3x_i2c_init(void) { } -static inline void aic3x_i2c_exit(void) { } #endif static int aic3x_probe(struct platform_device *pdev) @@ -1374,51 +1377,43 @@ static int aic3x_probe(struct platform_device *pdev) struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct aic3x_setup_data *setup; struct snd_soc_codec *codec; + struct aic3x_priv *aic3x; int ret = 0; - codec = aic3x_codec; - if (!codec) { - dev_err(&pdev->dev, "Codec not registered\n"); - return -ENODEV; - } + printk(KERN_INFO "AIC3X Audio Codec %s\n", AIC3X_VERSION); - socdev->card->codec = codec; setup = socdev->codec_data; + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) + return -ENOMEM; - if (setup) { - /* setup GPIO functions */ - aic3x_write(codec, AIC3X_GPIO1_REG, - (setup->gpio_func[0] & 0xf) << 4); - aic3x_write(codec, AIC3X_GPIO2_REG, - (setup->gpio_func[1] & 0xf) << 4); - } - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - printk(KERN_ERR "aic3x: failed to create pcms\n"); - goto pcm_err; + aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); + if (aic3x == NULL) { + kfree(codec); + return -ENOMEM; } - snd_soc_add_controls(codec, aic3x_snd_controls, - ARRAY_SIZE(aic3x_snd_controls)); - - aic3x_add_widgets(codec); + codec->private_data = aic3x; + socdev->card->codec = codec; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); - ret = snd_soc_init_card(socdev); - if (ret < 0) { - printk(KERN_ERR "aic3x: failed to register card\n"); - goto card_err; + aic3x_socdev = socdev; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + if (setup->i2c_address) { + codec->hw_write = (hw_write_t) i2c_master_send; + codec->hw_read = (hw_read_t) aic3x_i2c_read; + ret = aic3x_add_i2c_device(pdev, setup); } +#else + /* Add other interfaces here */ +#endif - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - -pcm_err: - kfree(codec->reg_cache); + if (ret != 0) { + kfree(codec->private_data); + kfree(codec); + } return ret; } @@ -1433,8 +1428,12 @@ static int aic3x_remove(struct platform_device *pdev) snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); - - kfree(codec->reg_cache); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_unregister_device(codec->control_data); + i2c_del_driver(&aic3x_i2c_driver); +#endif + kfree(codec->private_data); + kfree(codec); return 0; } @@ -1449,15 +1448,13 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); static int __init aic3x_modinit(void) { - aic3x_i2c_init(); - - return 0; + return snd_soc_register_dai(&aic3x_dai); } module_init(aic3x_modinit); static void __exit aic3x_exit(void) { - aic3x_i2c_exit(); + snd_soc_unregister_dai(&aic3x_dai); } module_exit(aic3x_exit); diff --git a/trunk/sound/soc/codecs/tlv320aic3x.h b/trunk/sound/soc/codecs/tlv320aic3x.h index 9af1c886213c..ac827e578c4d 100644 --- a/trunk/sound/soc/codecs/tlv320aic3x.h +++ b/trunk/sound/soc/codecs/tlv320aic3x.h @@ -282,6 +282,8 @@ int aic3x_headset_detected(struct snd_soc_codec *codec); int aic3x_button_pressed(struct snd_soc_codec *codec); struct aic3x_setup_data { + int i2c_bus; + unsigned short i2c_address; unsigned int gpio_func[2]; }; diff --git a/trunk/sound/soc/codecs/twl4030.c b/trunk/sound/soc/codecs/twl4030.c index 4df7c6c61c76..4dbb853eef5a 100644 --- a/trunk/sound/soc/codecs/twl4030.c +++ b/trunk/sound/soc/codecs/twl4030.c @@ -225,11 +225,55 @@ static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute) return; if (mute) { + /* Bypass the reg_cache and mute the volumes + * Headset mute is done in it's own event handler + * Things to mute: Earpiece, PreDrivL/R, CarkitL/R + */ + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_EAR_GAIN), + TWL4030_REG_EAR_CTL); + + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_PREDL_GAIN), + TWL4030_REG_PREDL_CTL); + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_PREDR_GAIN), + TWL4030_REG_PREDL_CTL); + + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_PRECKL_GAIN), + TWL4030_REG_PRECKL_CTL); + reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL); + twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg_val & (~TWL4030_PRECKR_GAIN), + TWL4030_REG_PRECKR_CTL); + /* Disable PLL */ reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); reg_val &= ~TWL4030_APLL_EN; twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); } else { + /* Restore the volumes + * Headset mute is done in it's own event handler + * Things to restore: Earpiece, PreDrivL/R, CarkitL/R + */ + twl4030_write(codec, TWL4030_REG_EAR_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_EAR_CTL)); + + twl4030_write(codec, TWL4030_REG_PREDL_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_PREDL_CTL)); + twl4030_write(codec, TWL4030_REG_PREDR_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_PREDR_CTL)); + + twl4030_write(codec, TWL4030_REG_PRECKL_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_PRECKL_CTL)); + twl4030_write(codec, TWL4030_REG_PRECKR_CTL, + twl4030_read_reg_cache(codec, TWL4030_REG_PRECKR_CTL)); + /* Enable PLL */ reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); reg_val |= TWL4030_APLL_EN; @@ -399,20 +443,16 @@ SOC_DAPM_ENUM("Route", twl4030_vibrapath_enum); /* Left analog microphone selection */ static const struct snd_kcontrol_new twl4030_dapm_analoglmic_controls[] = { - SOC_DAPM_SINGLE("Main Mic Capture Switch", - TWL4030_REG_ANAMICL, 0, 1, 0), - SOC_DAPM_SINGLE("Headset Mic Capture Switch", - TWL4030_REG_ANAMICL, 1, 1, 0), - SOC_DAPM_SINGLE("AUXL Capture Switch", - TWL4030_REG_ANAMICL, 2, 1, 0), - SOC_DAPM_SINGLE("Carkit Mic Capture Switch", - TWL4030_REG_ANAMICL, 3, 1, 0), + SOC_DAPM_SINGLE("Main mic", TWL4030_REG_ANAMICL, 0, 1, 0), + SOC_DAPM_SINGLE("Headset mic", TWL4030_REG_ANAMICL, 1, 1, 0), + SOC_DAPM_SINGLE("AUXL", TWL4030_REG_ANAMICL, 2, 1, 0), + SOC_DAPM_SINGLE("Carkit mic", TWL4030_REG_ANAMICL, 3, 1, 0), }; /* Right analog microphone selection */ static const struct snd_kcontrol_new twl4030_dapm_analogrmic_controls[] = { - SOC_DAPM_SINGLE("Sub Mic Capture Switch", TWL4030_REG_ANAMICR, 0, 1, 0), - SOC_DAPM_SINGLE("AUXR Capture Switch", TWL4030_REG_ANAMICR, 2, 1, 0), + SOC_DAPM_SINGLE("Sub mic", TWL4030_REG_ANAMICR, 0, 1, 0), + SOC_DAPM_SINGLE("AUXR", TWL4030_REG_ANAMICR, 2, 1, 0), }; /* TX1 L/R Analog/Digital microphone selection */ @@ -520,41 +560,6 @@ static int micpath_event(struct snd_soc_dapm_widget *w, return 0; } -/* - * Output PGA builder: - * Handle the muting and unmuting of the given output (turning off the - * amplifier associated with the output pin) - * On mute bypass the reg_cache and mute the volume - * On unmute: restore the register content - * Outputs handled in this way: Earpiece, PreDrivL/R, CarkitL/R - */ -#define TWL4030_OUTPUT_PGA(pin_name, reg, mask) \ -static int pin_name##pga_event(struct snd_soc_dapm_widget *w, \ - struct snd_kcontrol *kcontrol, int event) \ -{ \ - u8 reg_val; \ - \ - switch (event) { \ - case SND_SOC_DAPM_POST_PMU: \ - twl4030_write(w->codec, reg, \ - twl4030_read_reg_cache(w->codec, reg)); \ - break; \ - case SND_SOC_DAPM_POST_PMD: \ - reg_val = twl4030_read_reg_cache(w->codec, reg); \ - twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, \ - reg_val & (~mask), \ - reg); \ - break; \ - } \ - return 0; \ -} - -TWL4030_OUTPUT_PGA(earpiece, TWL4030_REG_EAR_CTL, TWL4030_EAR_GAIN); -TWL4030_OUTPUT_PGA(predrivel, TWL4030_REG_PREDL_CTL, TWL4030_PREDL_GAIN); -TWL4030_OUTPUT_PGA(predriver, TWL4030_REG_PREDR_CTL, TWL4030_PREDR_GAIN); -TWL4030_OUTPUT_PGA(carkitl, TWL4030_REG_PRECKL_CTL, TWL4030_PRECKL_GAIN); -TWL4030_OUTPUT_PGA(carkitr, TWL4030_REG_PRECKR_CTL, TWL4030_PRECKR_GAIN); - static void handsfree_ramp(struct snd_soc_codec *codec, int reg, int ramp) { unsigned char hs_ctl; @@ -615,9 +620,6 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w, static void headset_ramp(struct snd_soc_codec *codec, int ramp) { - struct snd_soc_device *socdev = codec->socdev; - struct twl4030_setup_data *setup = socdev->codec_data; - unsigned char hs_gain, hs_pop; struct twl4030_priv *twl4030 = codec->private_data; /* Base values for ramp delay calculation: 2^19 - 2^26 */ @@ -627,17 +629,6 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) hs_gain = twl4030_read_reg_cache(codec, TWL4030_REG_HS_GAIN_SET); hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); - /* Enable external mute control, this dramatically reduces - * the pop-noise */ - if (setup && setup->hs_extmute) { - if (setup->set_hs_extmute) { - setup->set_hs_extmute(1); - } else { - hs_pop |= TWL4030_EXTMUTE; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - } - } - if (ramp) { /* Headset ramp-up according to the TRM */ hs_pop |= TWL4030_VMID_EN; @@ -645,9 +636,6 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) twl4030_write(codec, TWL4030_REG_HS_GAIN_SET, hs_gain); hs_pop |= TWL4030_RAMP_EN; twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - /* Wait ramp delay time + 1, so the VMID can settle */ - mdelay((ramp_base[(hs_pop & TWL4030_RAMP_DELAY) >> 2] / - twl4030->sysclk) + 1); } else { /* Headset ramp-down _not_ according to * the TRM, but in a way that it is working */ @@ -664,16 +652,6 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) hs_pop &= ~TWL4030_VMID_EN; twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); } - - /* Disable external mute */ - if (setup && setup->hs_extmute) { - if (setup->set_hs_extmute) { - setup->set_hs_extmute(0); - } else { - hs_pop &= ~TWL4030_EXTMUTE; - twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); - } - } } static int headsetlpga_event(struct snd_soc_dapm_widget *w, @@ -734,19 +712,7 @@ static int bypass_event(struct snd_soc_dapm_widget *w, reg = twl4030_read_reg_cache(w->codec, m->reg); - /* - * bypass_state[0:3] - analog HiFi bypass - * bypass_state[4] - analog voice bypass - * bypass_state[5] - digital voice bypass - * bypass_state[6:7] - digital HiFi bypass - */ - if (m->reg == TWL4030_REG_VSTPGA) { - /* Voice digital bypass */ - if (reg) - twl4030->bypass_state |= (1 << 5); - else - twl4030->bypass_state &= ~(1 << 5); - } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { + if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) { /* Analog bypass */ if (reg & (1 << m->shift)) twl4030->bypass_state |= @@ -760,6 +726,12 @@ static int bypass_event(struct snd_soc_dapm_widget *w, twl4030->bypass_state |= (1 << 4); else twl4030->bypass_state &= ~(1 << 4); + } else if (m->reg == TWL4030_REG_VSTPGA) { + /* Voice digital bypass */ + if (reg) + twl4030->bypass_state |= (1 << 5); + else + twl4030->bypass_state &= ~(1 << 5); } else { /* Digital bypass */ if (reg & (0x7 << m->shift)) @@ -952,7 +924,7 @@ static const struct soc_enum twl4030_op_modes_enum = ARRAY_SIZE(twl4030_op_modes_texts), twl4030_op_modes_texts); -static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, +int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); @@ -1033,16 +1005,6 @@ static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0); */ static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); -/* AVADC clock priority */ -static const char *twl4030_avadc_clk_priority_texts[] = { - "Voice high priority", "HiFi high priority" -}; - -static const struct soc_enum twl4030_avadc_clk_priority_enum = - SOC_ENUM_SINGLE(TWL4030_REG_AVADC_CTL, 2, - ARRAY_SIZE(twl4030_avadc_clk_priority_texts), - twl4030_avadc_clk_priority_texts); - static const char *twl4030_rampdelay_texts[] = { "27/20/14 ms", "55/40/27 ms", "109/81/55 ms", "218/161/109 ms", "437/323/218 ms", "874/645/437 ms", "1748/1291/874 ms", @@ -1144,8 +1106,6 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = { SOC_DOUBLE_TLV("Analog Capture Volume", TWL4030_REG_ANAMIC_GAIN, 0, 3, 5, 0, input_gain_tlv), - SOC_ENUM("AVADC Clock Priority", twl4030_avadc_clk_priority_enum), - SOC_ENUM("HS ramp delay", twl4030_rampdelay_enum), SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum), @@ -1248,22 +1208,13 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, &twl4030_dapm_earpiece_controls[0], ARRAY_SIZE(twl4030_dapm_earpiece_controls)), - SND_SOC_DAPM_PGA_E("Earpiece PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, earpiecepga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), /* PreDrivL/R */ SND_SOC_DAPM_MIXER("PredriveL Mixer", SND_SOC_NOPM, 0, 0, &twl4030_dapm_predrivel_controls[0], ARRAY_SIZE(twl4030_dapm_predrivel_controls)), - SND_SOC_DAPM_PGA_E("PredriveL PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, predrivelpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MIXER("PredriveR Mixer", SND_SOC_NOPM, 0, 0, &twl4030_dapm_predriver_controls[0], ARRAY_SIZE(twl4030_dapm_predriver_controls)), - SND_SOC_DAPM_PGA_E("PredriveR PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, predriverpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), /* HeadsetL/R */ SND_SOC_DAPM_MIXER("HeadsetL Mixer", SND_SOC_NOPM, 0, 0, &twl4030_dapm_hsol_controls[0], @@ -1281,28 +1232,22 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_MIXER("CarkitL Mixer", SND_SOC_NOPM, 0, 0, &twl4030_dapm_carkitl_controls[0], ARRAY_SIZE(twl4030_dapm_carkitl_controls)), - SND_SOC_DAPM_PGA_E("CarkitL PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, carkitlpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MIXER("CarkitR Mixer", SND_SOC_NOPM, 0, 0, &twl4030_dapm_carkitr_controls[0], ARRAY_SIZE(twl4030_dapm_carkitr_controls)), - SND_SOC_DAPM_PGA_E("CarkitR PGA", SND_SOC_NOPM, - 0, 0, NULL, 0, carkitrpga_event, - SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), /* Output MUX controls */ /* HandsfreeL/R */ SND_SOC_DAPM_MUX("HandsfreeL Mux", SND_SOC_NOPM, 0, 0, &twl4030_dapm_handsfreel_control), - SND_SOC_DAPM_SWITCH("HandsfreeL", SND_SOC_NOPM, 0, 0, + SND_SOC_DAPM_SWITCH("HandsfreeL Switch", SND_SOC_NOPM, 0, 0, &twl4030_dapm_handsfreelmute_control), SND_SOC_DAPM_PGA_E("HandsfreeL PGA", SND_SOC_NOPM, 0, 0, NULL, 0, handsfreelpga_event, SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_MUX("HandsfreeR Mux", SND_SOC_NOPM, 5, 0, &twl4030_dapm_handsfreer_control), - SND_SOC_DAPM_SWITCH("HandsfreeR", SND_SOC_NOPM, 0, 0, + SND_SOC_DAPM_SWITCH("HandsfreeR Switch", SND_SOC_NOPM, 0, 0, &twl4030_dapm_handsfreermute_control), SND_SOC_DAPM_PGA_E("HandsfreeR PGA", SND_SOC_NOPM, 0, 0, NULL, 0, handsfreerpga_event, @@ -1337,11 +1282,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { SND_SOC_DAPM_POST_REG), /* Analog input mixers for the capture amplifiers */ - SND_SOC_DAPM_MIXER("Analog Left", + SND_SOC_DAPM_MIXER("Analog Left Capture Route", TWL4030_REG_ANAMICL, 4, 0, &twl4030_dapm_analoglmic_controls[0], ARRAY_SIZE(twl4030_dapm_analoglmic_controls)), - SND_SOC_DAPM_MIXER("Analog Right", + SND_SOC_DAPM_MIXER("Analog Right Capture Route", TWL4030_REG_ANAMICR, 4, 0, &twl4030_dapm_analogrmic_controls[0], ARRAY_SIZE(twl4030_dapm_analogrmic_controls)), @@ -1381,19 +1326,16 @@ static const struct snd_soc_dapm_route intercon[] = { {"Earpiece Mixer", "AudioL1", "Analog L1 Playback Mixer"}, {"Earpiece Mixer", "AudioL2", "Analog L2 Playback Mixer"}, {"Earpiece Mixer", "AudioR1", "Analog R1 Playback Mixer"}, - {"Earpiece PGA", NULL, "Earpiece Mixer"}, /* PreDrivL */ {"PredriveL Mixer", "Voice", "Analog Voice Playback Mixer"}, {"PredriveL Mixer", "AudioL1", "Analog L1 Playback Mixer"}, {"PredriveL Mixer", "AudioL2", "Analog L2 Playback Mixer"}, {"PredriveL Mixer", "AudioR2", "Analog R2 Playback Mixer"}, - {"PredriveL PGA", NULL, "PredriveL Mixer"}, /* PreDrivR */ {"PredriveR Mixer", "Voice", "Analog Voice Playback Mixer"}, {"PredriveR Mixer", "AudioR1", "Analog R1 Playback Mixer"}, {"PredriveR Mixer", "AudioR2", "Analog R2 Playback Mixer"}, {"PredriveR Mixer", "AudioL2", "Analog L2 Playback Mixer"}, - {"PredriveR PGA", NULL, "PredriveR Mixer"}, /* HeadsetL */ {"HeadsetL Mixer", "Voice", "Analog Voice Playback Mixer"}, {"HeadsetL Mixer", "AudioL1", "Analog L1 Playback Mixer"}, @@ -1408,26 +1350,24 @@ static const struct snd_soc_dapm_route intercon[] = { {"CarkitL Mixer", "Voice", "Analog Voice Playback Mixer"}, {"CarkitL Mixer", "AudioL1", "Analog L1 Playback Mixer"}, {"CarkitL Mixer", "AudioL2", "Analog L2 Playback Mixer"}, - {"CarkitL PGA", NULL, "CarkitL Mixer"}, /* CarkitR */ {"CarkitR Mixer", "Voice", "Analog Voice Playback Mixer"}, {"CarkitR Mixer", "AudioR1", "Analog R1 Playback Mixer"}, {"CarkitR Mixer", "AudioR2", "Analog R2 Playback Mixer"}, - {"CarkitR PGA", NULL, "CarkitR Mixer"}, /* HandsfreeL */ {"HandsfreeL Mux", "Voice", "Analog Voice Playback Mixer"}, {"HandsfreeL Mux", "AudioL1", "Analog L1 Playback Mixer"}, {"HandsfreeL Mux", "AudioL2", "Analog L2 Playback Mixer"}, {"HandsfreeL Mux", "AudioR2", "Analog R2 Playback Mixer"}, - {"HandsfreeL", "Switch", "HandsfreeL Mux"}, - {"HandsfreeL PGA", NULL, "HandsfreeL"}, + {"HandsfreeL Switch", "Switch", "HandsfreeL Mux"}, + {"HandsfreeL PGA", NULL, "HandsfreeL Switch"}, /* HandsfreeR */ {"HandsfreeR Mux", "Voice", "Analog Voice Playback Mixer"}, {"HandsfreeR Mux", "AudioR1", "Analog R1 Playback Mixer"}, {"HandsfreeR Mux", "AudioR2", "Analog R2 Playback Mixer"}, {"HandsfreeR Mux", "AudioL2", "Analog L2 Playback Mixer"}, - {"HandsfreeR", "Switch", "HandsfreeR Mux"}, - {"HandsfreeR PGA", NULL, "HandsfreeR"}, + {"HandsfreeR Switch", "Switch", "HandsfreeR Mux"}, + {"HandsfreeR PGA", NULL, "HandsfreeR Switch"}, /* Vibra */ {"Vibra Mux", "AudioL1", "DAC Left1"}, {"Vibra Mux", "AudioR1", "DAC Right1"}, @@ -1437,29 +1377,29 @@ static const struct snd_soc_dapm_route intercon[] = { /* outputs */ {"OUTL", NULL, "Analog L2 Playback Mixer"}, {"OUTR", NULL, "Analog R2 Playback Mixer"}, - {"EARPIECE", NULL, "Earpiece PGA"}, - {"PREDRIVEL", NULL, "PredriveL PGA"}, - {"PREDRIVER", NULL, "PredriveR PGA"}, + {"EARPIECE", NULL, "Earpiece Mixer"}, + {"PREDRIVEL", NULL, "PredriveL Mixer"}, + {"PREDRIVER", NULL, "PredriveR Mixer"}, {"HSOL", NULL, "HeadsetL PGA"}, {"HSOR", NULL, "HeadsetR PGA"}, - {"CARKITL", NULL, "CarkitL PGA"}, - {"CARKITR", NULL, "CarkitR PGA"}, + {"CARKITL", NULL, "CarkitL Mixer"}, + {"CARKITR", NULL, "CarkitR Mixer"}, {"HFL", NULL, "HandsfreeL PGA"}, {"HFR", NULL, "HandsfreeR PGA"}, {"Vibra Route", "Audio", "Vibra Mux"}, {"VIBRA", NULL, "Vibra Route"}, /* Capture path */ - {"Analog Left", "Main Mic Capture Switch", "MAINMIC"}, - {"Analog Left", "Headset Mic Capture Switch", "HSMIC"}, - {"Analog Left", "AUXL Capture Switch", "AUXL"}, - {"Analog Left", "Carkit Mic Capture Switch", "CARKITMIC"}, + {"Analog Left Capture Route", "Main mic", "MAINMIC"}, + {"Analog Left Capture Route", "Headset mic", "HSMIC"}, + {"Analog Left Capture Route", "AUXL", "AUXL"}, + {"Analog Left Capture Route", "Carkit mic", "CARKITMIC"}, - {"Analog Right", "Sub Mic Capture Switch", "SUBMIC"}, - {"Analog Right", "AUXR Capture Switch", "AUXR"}, + {"Analog Right Capture Route", "Sub mic", "SUBMIC"}, + {"Analog Right Capture Route", "AUXR", "AUXR"}, - {"ADC Physical Left", NULL, "Analog Left"}, - {"ADC Physical Right", NULL, "Analog Right"}, + {"ADC Physical Left", NULL, "Analog Left Capture Route"}, + {"ADC Physical Right", NULL, "Analog Right Capture Route"}, {"Digimic0 Enable", NULL, "DIGIMIC0"}, {"Digimic1 Enable", NULL, "DIGIMIC1"}, @@ -1483,11 +1423,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, /* Analog bypass routes */ - {"Right1 Analog Loopback", "Switch", "Analog Right"}, - {"Left1 Analog Loopback", "Switch", "Analog Left"}, - {"Right2 Analog Loopback", "Switch", "Analog Right"}, - {"Left2 Analog Loopback", "Switch", "Analog Left"}, - {"Voice Analog Loopback", "Switch", "Analog Left"}, + {"Right1 Analog Loopback", "Switch", "Analog Right Capture Route"}, + {"Left1 Analog Loopback", "Switch", "Analog Left Capture Route"}, + {"Right2 Analog Loopback", "Switch", "Analog Right Capture Route"}, + {"Left2 Analog Loopback", "Switch", "Analog Left Capture Route"}, + {"Voice Analog Loopback", "Switch", "Analog Left Capture Route"}, {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, @@ -1669,6 +1609,8 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream, /* If the substream has 4 channel, do the necessary setup */ if (params_channels(params) == 4) { + u8 format, mode; + format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); @@ -1864,19 +1806,6 @@ static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int twl4030_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); - - if (tristate) - reg |= TWL4030_AIF_TRI_EN; - else - reg &= ~TWL4030_AIF_TRI_EN; - - return twl4030_write(codec, TWL4030_REG_AUDIO_IF, reg); -} - /* In case of voice mode, the RX1 L(VRX) for downlink and the TX2 L/R * (VTXL, VTXR) for uplink has to be enabled/disabled. */ static void twl4030_voice_enable(struct snd_soc_codec *codec, int direction, @@ -2019,7 +1948,7 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: + case SND_SOC_DAIFMT_CBS_CFM: format &= ~(TWL4030_VIF_SLAVE_EN); break; case SND_SOC_DAIFMT_CBS_CFS: @@ -2051,19 +1980,6 @@ static int twl4030_voice_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; } -static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_VOICE_IF); - - if (tristate) - reg |= TWL4030_VIF_TRI_EN; - else - reg &= ~TWL4030_VIF_TRI_EN; - - return twl4030_write(codec, TWL4030_REG_VOICE_IF, reg); -} - #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) @@ -2073,7 +1989,6 @@ static struct snd_soc_dai_ops twl4030_dai_ops = { .hw_params = twl4030_hw_params, .set_sysclk = twl4030_set_dai_sysclk, .set_fmt = twl4030_set_dai_fmt, - .set_tristate = twl4030_set_tristate, }; static struct snd_soc_dai_ops twl4030_dai_voice_ops = { @@ -2082,7 +1997,6 @@ static struct snd_soc_dai_ops twl4030_dai_voice_ops = { .hw_params = twl4030_voice_hw_params, .set_sysclk = twl4030_voice_set_dai_sysclk, .set_fmt = twl4030_voice_set_dai_fmt, - .set_tristate = twl4030_voice_set_tristate, }; struct snd_soc_dai twl4030_dai[] = { diff --git a/trunk/sound/soc/codecs/twl4030.h b/trunk/sound/soc/codecs/twl4030.h index 2b4bfa23f985..fe5f395d9e4f 100644 --- a/trunk/sound/soc/codecs/twl4030.h +++ b/trunk/sound/soc/codecs/twl4030.h @@ -274,8 +274,6 @@ extern struct snd_soc_codec_device soc_codec_dev_twl4030; struct twl4030_setup_data { unsigned int ramp_delay_value; unsigned int sysclk; - unsigned int hs_extmute:1; - void (*set_hs_extmute)(int mute); }; #endif /* End of __TWL4030_AUDIO_H__ */ diff --git a/trunk/sound/soc/codecs/uda134x.c b/trunk/sound/soc/codecs/uda134x.c index c33b92edbded..269b108e1de6 100644 --- a/trunk/sound/soc/codecs/uda134x.c +++ b/trunk/sound/soc/codecs/uda134x.c @@ -163,7 +163,7 @@ static int uda134x_mute(struct snd_soc_dai *dai, int mute) else mute_reg &= ~(1<<2); - uda134x_write(codec, UDA134X_DATA010, mute_reg); + uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2)); return 0; } diff --git a/trunk/sound/soc/codecs/uda1380.c b/trunk/sound/soc/codecs/uda1380.c index 92ec03442154..5b21594e0e58 100644 --- a/trunk/sound/soc/codecs/uda1380.c +++ b/trunk/sound/soc/codecs/uda1380.c @@ -5,7 +5,9 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * Copyright (c) 2007-2009 Philipp Zabel + * Copyright (c) 2007 Philipp Zabel + * Improved support for DAPM and audio routing/mixing capabilities, + * added TLV support. * * Modified by Richard Purdie to fit into SoC * codec model. @@ -17,32 +19,26 @@ #include #include #include +#include #include #include -#include +#include #include #include #include #include #include #include +#include #include #include #include -#include #include "uda1380.h" +static struct work_struct uda1380_work; static struct snd_soc_codec *uda1380_codec; -/* codec private data */ -struct uda1380_priv { - struct snd_soc_codec codec; - u16 reg_cache[UDA1380_CACHEREGNUM]; - unsigned int dac_clk; - struct work_struct work; -}; - /* * uda1380 register cache */ @@ -477,7 +473,6 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - struct uda1380_priv *uda1380 = codec->private_data; int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER); switch (cmd) { @@ -485,13 +480,13 @@ static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: uda1380_write_reg_cache(codec, UDA1380_MIXER, mixer & ~R14_SILENCE); - schedule_work(&uda1380->work); + schedule_work(&uda1380_work); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: uda1380_write_reg_cache(codec, UDA1380_MIXER, mixer | R14_SILENCE); - schedule_work(&uda1380->work); + schedule_work(&uda1380_work); break; } return 0; @@ -675,33 +670,44 @@ static int uda1380_resume(struct platform_device *pdev) return 0; } -static int uda1380_probe(struct platform_device *pdev) +/* + * initialise the UDA1380 driver + * register mixer and dsp interfaces with the kernel + */ +static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct uda1380_platform_data *pdata; + struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; - if (uda1380_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } + codec->name = "UDA1380"; + codec->owner = THIS_MODULE; + codec->read = uda1380_read_reg_cache; + codec->write = uda1380_write; + codec->set_bias_level = uda1380_set_bias_level; + codec->dai = uda1380_dai; + codec->num_dai = ARRAY_SIZE(uda1380_dai); + codec->reg_cache = kmemdup(uda1380_reg, sizeof(uda1380_reg), + GFP_KERNEL); + if (codec->reg_cache == NULL) + return -ENOMEM; + codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); + codec->reg_cache_step = 1; + uda1380_reset(codec); - socdev->card->codec = uda1380_codec; - codec = uda1380_codec; - pdata = codec->dev->platform_data; + uda1380_codec = codec; + INIT_WORK(&uda1380_work, uda1380_flush_work); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); + pr_err("uda1380: failed to create pcms\n"); goto pcm_err; } /* power on device */ uda1380_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* set clock input */ - switch (pdata->dac_clk) { + switch (dac_clk) { case UDA1380_DAC_CLK_SYSCLK: uda1380_write(codec, UDA1380_CLK, 0); break; @@ -710,12 +716,13 @@ static int uda1380_probe(struct platform_device *pdev) break; } + /* uda1380 init */ snd_soc_add_controls(codec, uda1380_snd_controls, ARRAY_SIZE(uda1380_snd_controls)); uda1380_add_widgets(codec); ret = snd_soc_init_card(socdev); if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); + pr_err("uda1380: failed to register card\n"); goto card_err; } @@ -725,201 +732,165 @@ static int uda1380_probe(struct platform_device *pdev) snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); pcm_err: + kfree(codec->reg_cache); return ret; } -/* power down chip */ -static int uda1380_remove(struct platform_device *pdev) +static struct snd_soc_device *uda1380_socdev; + +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + +static int uda1380_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) { - struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_device *socdev = uda1380_socdev; + struct uda1380_setup_data *setup = socdev->codec_data; struct snd_soc_codec *codec = socdev->card->codec; + int ret; - if (codec->control_data) - uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); + i2c_set_clientdata(i2c, codec); + codec->control_data = i2c; - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); + ret = uda1380_init(socdev, setup->dac_clk); + if (ret < 0) + pr_err("uda1380: failed to initialise UDA1380\n"); - return 0; + return ret; } -struct snd_soc_codec_device soc_codec_dev_uda1380 = { - .probe = uda1380_probe, - .remove = uda1380_remove, - .suspend = uda1380_suspend, - .resume = uda1380_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); - -static int uda1380_register(struct uda1380_priv *uda1380) +static int uda1380_i2c_remove(struct i2c_client *client) { - int ret, i; - struct snd_soc_codec *codec = &uda1380->codec; - struct uda1380_platform_data *pdata = codec->dev->platform_data; - - if (uda1380_codec) { - dev_err(codec->dev, "Another UDA1380 is registered\n"); - return -EINVAL; - } - - if (!pdata || !pdata->gpio_power || !pdata->gpio_reset) - return -EINVAL; - - ret = gpio_request(pdata->gpio_power, "uda1380 power"); - if (ret) - goto err_out; - ret = gpio_request(pdata->gpio_reset, "uda1380 reset"); - if (ret) - goto err_gpio; - - gpio_direction_output(pdata->gpio_power, 1); - - /* we may need to have the clock running here - pH5 */ - gpio_direction_output(pdata->gpio_reset, 1); - udelay(5); - gpio_set_value(pdata->gpio_reset, 0); + struct snd_soc_codec *codec = i2c_get_clientdata(client); + kfree(codec->reg_cache); + return 0; +} - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); +static const struct i2c_device_id uda1380_i2c_id[] = { + { "uda1380", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); - codec->private_data = uda1380; - codec->name = "UDA1380"; - codec->owner = THIS_MODULE; - codec->read = uda1380_read_reg_cache; - codec->write = uda1380_write; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = uda1380_set_bias_level; - codec->dai = uda1380_dai; - codec->num_dai = ARRAY_SIZE(uda1380_dai); - codec->reg_cache_size = ARRAY_SIZE(uda1380_reg); - codec->reg_cache = &uda1380->reg_cache; - codec->reg_cache_step = 1; +static struct i2c_driver uda1380_i2c_driver = { + .driver = { + .name = "UDA1380 I2C Codec", + .owner = THIS_MODULE, + }, + .probe = uda1380_i2c_probe, + .remove = uda1380_i2c_remove, + .id_table = uda1380_i2c_id, +}; - memcpy(codec->reg_cache, uda1380_reg, sizeof(uda1380_reg)); +static int uda1380_add_i2c_device(struct platform_device *pdev, + const struct uda1380_setup_data *setup) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter; + struct i2c_client *client; + int ret; - ret = uda1380_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_reset; + ret = i2c_add_driver(&uda1380_i2c_driver); + if (ret != 0) { + dev_err(&pdev->dev, "can't add i2c driver\n"); + return ret; } - INIT_WORK(&uda1380->work, uda1380_flush_work); - - for (i = 0; i < ARRAY_SIZE(uda1380_dai); i++) - uda1380_dai[i].dev = codec->dev; + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = setup->i2c_address; + strlcpy(info.type, "uda1380", I2C_NAME_SIZE); - uda1380_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_reset; + adapter = i2c_get_adapter(setup->i2c_bus); + if (!adapter) { + dev_err(&pdev->dev, "can't get i2c adapter %d\n", + setup->i2c_bus); + goto err_driver; } - ret = snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_dai; + client = i2c_new_device(adapter, &info); + i2c_put_adapter(adapter); + if (!client) { + dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", + (unsigned int)info.addr); + goto err_driver; } return 0; -err_dai: - snd_soc_unregister_codec(codec); -err_reset: - gpio_set_value(pdata->gpio_power, 0); - gpio_free(pdata->gpio_reset); -err_gpio: - gpio_free(pdata->gpio_power); -err_out: - return ret; -} - -static void uda1380_unregister(struct uda1380_priv *uda1380) -{ - struct snd_soc_codec *codec = &uda1380->codec; - struct uda1380_platform_data *pdata = codec->dev->platform_data; - - snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); - snd_soc_unregister_codec(&uda1380->codec); - - gpio_set_value(pdata->gpio_power, 0); - gpio_free(pdata->gpio_reset); - gpio_free(pdata->gpio_power); - - kfree(uda1380); - uda1380_codec = NULL; +err_driver: + i2c_del_driver(&uda1380_i2c_driver); + return -ENODEV; } +#endif -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int uda1380_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +static int uda1380_probe(struct platform_device *pdev) { - struct uda1380_priv *uda1380; + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct uda1380_setup_data *setup; struct snd_soc_codec *codec; int ret; - uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL); - if (uda1380 == NULL) + setup = socdev->codec_data; + codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); + if (codec == NULL) return -ENOMEM; - codec = &uda1380->codec; - codec->hw_write = (hw_write_t)i2c_master_send; + socdev->card->codec = codec; + mutex_init(&codec->mutex); + INIT_LIST_HEAD(&codec->dapm_widgets); + INIT_LIST_HEAD(&codec->dapm_paths); - i2c_set_clientdata(i2c, uda1380); - codec->control_data = i2c; + uda1380_socdev = socdev; + ret = -ENODEV; - codec->dev = &i2c->dev; +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + if (setup->i2c_address) { + codec->hw_write = (hw_write_t)i2c_master_send; + ret = uda1380_add_i2c_device(pdev, setup); + } +#endif - ret = uda1380_register(uda1380); if (ret != 0) - kfree(uda1380); - + kfree(codec); return ret; } -static int __devexit uda1380_i2c_remove(struct i2c_client *i2c) +/* power down chip */ +static int uda1380_remove(struct platform_device *pdev) { - struct uda1380_priv *uda1380 = i2c_get_clientdata(i2c); - uda1380_unregister(uda1380); + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_codec *codec = socdev->card->codec; + + if (codec->control_data) + uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF); + + snd_soc_free_pcms(socdev); + snd_soc_dapm_free(socdev); +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) + i2c_unregister_device(codec->control_data); + i2c_del_driver(&uda1380_i2c_driver); +#endif + kfree(codec); + return 0; } -static const struct i2c_device_id uda1380_i2c_id[] = { - { "uda1380", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); - -static struct i2c_driver uda1380_i2c_driver = { - .driver = { - .name = "UDA1380 I2C Codec", - .owner = THIS_MODULE, - }, - .probe = uda1380_i2c_probe, - .remove = __devexit_p(uda1380_i2c_remove), - .id_table = uda1380_i2c_id, +struct snd_soc_codec_device soc_codec_dev_uda1380 = { + .probe = uda1380_probe, + .remove = uda1380_remove, + .suspend = uda1380_suspend, + .resume = uda1380_resume, }; -#endif +EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); static int __init uda1380_modinit(void) { - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&uda1380_i2c_driver); - if (ret != 0) - pr_err("Failed to register UDA1380 I2C driver: %d\n", ret); -#endif - return 0; + return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); } module_init(uda1380_modinit); static void __exit uda1380_exit(void) { -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&uda1380_i2c_driver); -#endif + snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); } module_exit(uda1380_exit); diff --git a/trunk/sound/soc/codecs/uda1380.h b/trunk/sound/soc/codecs/uda1380.h index 9cefa8a54770..c55c17a52a12 100644 --- a/trunk/sound/soc/codecs/uda1380.h +++ b/trunk/sound/soc/codecs/uda1380.h @@ -72,6 +72,14 @@ #define R22_SKIP_DCFIL 0x0002 #define R23_AGC_EN 0x0001 +struct uda1380_setup_data { + int i2c_bus; + unsigned short i2c_address; + int dac_clk; +#define UDA1380_DAC_CLK_SYSCLK 0 +#define UDA1380_DAC_CLK_WSPLL 1 +}; + #define UDA1380_DAI_DUPLEX 0 /* playback and capture on single DAI */ #define UDA1380_DAI_PLAYBACK 1 /* playback DAI */ #define UDA1380_DAI_CAPTURE 2 /* capture DAI */ diff --git a/trunk/sound/soc/codecs/wm8350.c b/trunk/sound/soc/codecs/wm8350.c index 3ff0373dff89..e7348d341b76 100644 --- a/trunk/sound/soc/codecs/wm8350.c +++ b/trunk/sound/soc/codecs/wm8350.c @@ -63,8 +63,6 @@ struct wm8350_data { struct wm8350_jack_data hpl; struct wm8350_jack_data hpr; struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; - int fll_freq_out; - int fll_freq_in; }; static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec, @@ -408,6 +406,7 @@ static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; +static const char *wm8350_dacfilter[] = { "Normal", "Sloping" }; static const char *wm8350_adcfilter[] = { "None", "High Pass" }; static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; static const char *wm8350_lr[] = { "Left", "Right" }; @@ -417,6 +416,7 @@ static const struct soc_enum wm8350_enum[] = { SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol), SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem), SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes), + SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter), SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter), SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp), SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol), @@ -444,9 +444,10 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = { 0, 255, 0, dac_pcm_tlv), SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), - SOC_ENUM("Capture PCM Filter", wm8350_enum[4]), - SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]), - SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]), + SOC_ENUM("Playback PCM Filter", wm8350_enum[4]), + SOC_ENUM("Capture PCM Filter", wm8350_enum[5]), + SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]), + SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]), SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume", WM8350_ADC_DIGITAL_VOLUME_L, WM8350_ADC_DIGITAL_VOLUME_R, @@ -612,7 +613,7 @@ SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1); /* Out4 Capture Mux */ static const struct snd_kcontrol_new wm8350_out4_capture_controls = -SOC_DAPM_ENUM("Route", wm8350_enum[7]); +SOC_DAPM_ENUM("Route", wm8350_enum[8]); static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = { @@ -992,7 +993,6 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai) { struct snd_soc_codec *codec = codec_dai->codec; - struct wm8350 *wm8350 = codec->control_data; u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & ~WM8350_AIF_WL_MASK; @@ -1012,19 +1012,6 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, } wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); - - /* The sloping stopband filter is recommended for use with - * lower sample rates to improve performance. - */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (params_rate(params) < 24000) - wm8350_set_bits(wm8350, WM8350_DAC_MUTE_VOLUME, - WM8350_DAC_SB_FILT); - else - wm8350_clear_bits(wm8350, WM8350_DAC_MUTE_VOLUME, - WM8350_DAC_SB_FILT); - } - return 0; } @@ -1106,14 +1093,10 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; struct wm8350 *wm8350 = codec->control_data; - struct wm8350_data *priv = codec->private_data; struct _fll_div fll_div; int ret = 0; u16 fll_1, fll_4; - if (freq_in == priv->fll_freq_in && freq_out == priv->fll_freq_out) - return 0; - /* power down FLL - we need to do this for reconfiguration */ wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); @@ -1148,9 +1131,6 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai, wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); - priv->fll_freq_out = freq_out; - priv->fll_freq_in = freq_in; - return 0; } @@ -1680,21 +1660,6 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m) -{ - return snd_soc_suspend_device(&pdev->dev); -} - -static int wm8350_codec_resume(struct platform_device *pdev) -{ - return snd_soc_resume_device(&pdev->dev); -} -#else -#define wm8350_codec_suspend NULL -#define wm8350_codec_resume NULL -#endif - static struct platform_driver wm8350_codec_driver = { .driver = { .name = "wm8350-codec", @@ -1702,8 +1667,6 @@ static struct platform_driver wm8350_codec_driver = { }, .probe = wm8350_codec_probe, .remove = __devexit_p(wm8350_codec_remove), - .suspend = wm8350_codec_suspend, - .resume = wm8350_codec_resume, }; static __init int wm8350_init(void) diff --git a/trunk/sound/soc/codecs/wm8400.c b/trunk/sound/soc/codecs/wm8400.c index b9ef4d915221..502eefac1ecd 100644 --- a/trunk/sound/soc/codecs/wm8400.c +++ b/trunk/sound/soc/codecs/wm8400.c @@ -1022,15 +1022,10 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (freq_in == wm8400->fll_in && freq_out == wm8400->fll_out) return 0; - if (freq_out) { + if (freq_out != 0) { ret = fll_factors(wm8400, &factors, freq_in, freq_out); if (ret != 0) return ret; - } else { - /* Bodge GCC 4.4.0 uninitialised variable warning - it - * doesn't seem capable of working out that we exit if - * freq_out is 0 before any of the uses. */ - memset(&factors, 0, sizeof(factors)); } wm8400->fll_out = freq_out; @@ -1045,7 +1040,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, reg &= ~WM8400_FLL_OSC_ENA; wm8400_write(codec, WM8400_FLL_CONTROL_1, reg); - if (!freq_out) + if (freq_out == 0) return 0; reg &= ~(WM8400_FLL_REF_FREQ | WM8400_FLL_FRATIO_MASK); @@ -1558,21 +1553,6 @@ static int __exit wm8400_codec_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM -static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg) -{ - return snd_soc_suspend_device(&pdev->dev); -} - -static int wm8400_pdev_resume(struct platform_device *pdev) -{ - return snd_soc_resume_device(&pdev->dev); -} -#else -#define wm8400_pdev_suspend NULL -#define wm8400_pdev_resume NULL -#endif - static struct platform_driver wm8400_codec_driver = { .driver = { .name = "wm8400-codec", @@ -1580,8 +1560,6 @@ static struct platform_driver wm8400_codec_driver = { }, .probe = wm8400_codec_probe, .remove = __exit_p(wm8400_codec_remove), - .suspend = wm8400_pdev_suspend, - .resume = wm8400_pdev_resume, }; static int __init wm8400_codec_init(void) diff --git a/trunk/sound/soc/codecs/wm8510.c b/trunk/sound/soc/codecs/wm8510.c index 060d5d06ba95..c8b8dba85890 100644 --- a/trunk/sound/soc/codecs/wm8510.c +++ b/trunk/sound/soc/codecs/wm8510.c @@ -58,7 +58,55 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { #define WM8510_POWER1_BIASEN 0x08 #define WM8510_POWER1_BUFIOEN 0x10 -#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0) +/* + * read wm8510 register cache + */ +static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg == WM8510_RESET) + return 0; + if (reg >= WM8510_CACHEREGNUM) + return -1; + return cache[reg]; +} + +/* + * write wm8510 register cache + */ +static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec, + u16 reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg >= WM8510_CACHEREGNUM) + return; + cache[reg] = value; +} + +/* + * write to the WM8510 register space + */ +static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + /* data is + * D15..D9 WM8510 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8510_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +#define wm8510_reset(c) wm8510_write(c, WM8510_RESET, 0) static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; @@ -279,27 +327,27 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = snd_soc_read(codec, WM8510_CLOCK); - snd_soc_write(codec, WM8510_CLOCK, reg & 0x0ff); + reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); + wm8510_write(codec, WM8510_CLOCK, reg & 0x0ff); /* Turn off PLL */ - reg = snd_soc_read(codec, WM8510_POWER1); - snd_soc_write(codec, WM8510_POWER1, reg & 0x1df); + reg = wm8510_read_reg_cache(codec, WM8510_POWER1); + wm8510_write(codec, WM8510_POWER1, reg & 0x1df); return 0; } pll_factors(freq_out*4, freq_in); - snd_soc_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); - snd_soc_write(codec, WM8510_PLLK1, pll_div.k >> 18); - snd_soc_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff); - reg = snd_soc_read(codec, WM8510_POWER1); - snd_soc_write(codec, WM8510_POWER1, reg | 0x020); + wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); + wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18); + wm8510_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); + wm8510_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff); + reg = wm8510_read_reg_cache(codec, WM8510_POWER1); + wm8510_write(codec, WM8510_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_read(codec, WM8510_CLOCK); - snd_soc_write(codec, WM8510_CLOCK, reg | 0x100); + reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); + wm8510_write(codec, WM8510_CLOCK, reg | 0x100); return 0; } @@ -315,24 +363,24 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8510_OPCLKDIV: - reg = snd_soc_read(codec, WM8510_GPIO) & 0x1cf; - snd_soc_write(codec, WM8510_GPIO, reg | div); + reg = wm8510_read_reg_cache(codec, WM8510_GPIO) & 0x1cf; + wm8510_write(codec, WM8510_GPIO, reg | div); break; case WM8510_MCLKDIV: - reg = snd_soc_read(codec, WM8510_CLOCK) & 0x11f; - snd_soc_write(codec, WM8510_CLOCK, reg | div); + reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f; + wm8510_write(codec, WM8510_CLOCK, reg | div); break; case WM8510_ADCCLK: - reg = snd_soc_read(codec, WM8510_ADC) & 0x1f7; - snd_soc_write(codec, WM8510_ADC, reg | div); + reg = wm8510_read_reg_cache(codec, WM8510_ADC) & 0x1f7; + wm8510_write(codec, WM8510_ADC, reg | div); break; case WM8510_DACCLK: - reg = snd_soc_read(codec, WM8510_DAC) & 0x1f7; - snd_soc_write(codec, WM8510_DAC, reg | div); + reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0x1f7; + wm8510_write(codec, WM8510_DAC, reg | div); break; case WM8510_BCLKDIV: - reg = snd_soc_read(codec, WM8510_CLOCK) & 0x1e3; - snd_soc_write(codec, WM8510_CLOCK, reg | div); + reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1e3; + wm8510_write(codec, WM8510_CLOCK, reg | div); break; default: return -EINVAL; @@ -346,7 +394,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, { struct snd_soc_codec *codec = codec_dai->codec; u16 iface = 0; - u16 clk = snd_soc_read(codec, WM8510_CLOCK) & 0x1fe; + u16 clk = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1fe; /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -393,8 +441,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8510_IFACE, iface); - snd_soc_write(codec, WM8510_CLOCK, clk); + wm8510_write(codec, WM8510_IFACE, iface); + wm8510_write(codec, WM8510_CLOCK, clk); return 0; } @@ -405,8 +453,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f; - u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1; + u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; + u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; /* bit size */ switch (params_format(params)) { @@ -445,20 +493,20 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, break; } - snd_soc_write(codec, WM8510_IFACE, iface); - snd_soc_write(codec, WM8510_ADD, adn); + wm8510_write(codec, WM8510_IFACE, iface); + wm8510_write(codec, WM8510_ADD, adn); return 0; } static int wm8510_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8510_DAC) & 0xffbf; + u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf; if (mute) - snd_soc_write(codec, WM8510_DAC, mute_reg | 0x40); + wm8510_write(codec, WM8510_DAC, mute_reg | 0x40); else - snd_soc_write(codec, WM8510_DAC, mute_reg); + wm8510_write(codec, WM8510_DAC, mute_reg); return 0; } @@ -466,13 +514,13 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) static int wm8510_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; + u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3; switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: power1 |= 0x1; /* VMID 50k */ - snd_soc_write(codec, WM8510_POWER1, power1); + wm8510_write(codec, WM8510_POWER1, power1); break; case SND_SOC_BIAS_STANDBY: @@ -480,18 +528,18 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Initial cap charge at VMID 5k */ - snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); + wm8510_write(codec, WM8510_POWER1, power1 | 0x3); mdelay(100); } power1 |= 0x2; /* VMID 500k */ - snd_soc_write(codec, WM8510_POWER1, power1); + wm8510_write(codec, WM8510_POWER1, power1); break; case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8510_POWER1, 0); - snd_soc_write(codec, WM8510_POWER2, 0); - snd_soc_write(codec, WM8510_POWER3, 0); + wm8510_write(codec, WM8510_POWER1, 0); + wm8510_write(codec, WM8510_POWER2, 0); + wm8510_write(codec, WM8510_POWER3, 0); break; } @@ -529,7 +577,6 @@ struct snd_soc_dai wm8510_dai = { .rates = WM8510_RATES, .formats = WM8510_FORMATS,}, .ops = &wm8510_dai_ops, - .symmetric_rates = 1, }; EXPORT_SYMBOL_GPL(wm8510_dai); @@ -565,14 +612,15 @@ static int wm8510_resume(struct platform_device *pdev) * initialise the WM8510 driver * register the mixer and dsp interfaces with the kernel */ -static int wm8510_init(struct snd_soc_device *socdev, - enum snd_soc_control_type control) +static int wm8510_init(struct snd_soc_device *socdev) { struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "WM8510"; codec->owner = THIS_MODULE; + codec->read = wm8510_read_reg_cache; + codec->write = wm8510_write; codec->set_bias_level = wm8510_set_bias_level; codec->dai = &wm8510_dai; codec->num_dai = 1; @@ -582,20 +630,13 @@ static int wm8510_init(struct snd_soc_device *socdev, if (codec->reg_cache == NULL) return -ENOMEM; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", - ret); - goto err; - } - wm8510_reset(codec); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8510: failed to create pcms\n"); - goto err; + goto pcm_err; } /* power on device */ @@ -614,7 +655,7 @@ static int wm8510_init(struct snd_soc_device *socdev, card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -err: +pcm_err: kfree(codec->reg_cache); return ret; } @@ -637,7 +678,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, codec); codec->control_data = i2c; - ret = wm8510_init(socdev, SND_SOC_I2C); + ret = wm8510_init(socdev); if (ret < 0) pr_err("failed to initialise WM8510\n"); @@ -717,7 +758,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi) codec->control_data = spi; - ret = wm8510_init(socdev, SND_SOC_SPI); + ret = wm8510_init(socdev); if (ret < 0) dev_err(&spi->dev, "failed to initialise WM8510\n"); @@ -738,6 +779,30 @@ static struct spi_driver wm8510_spi_driver = { .probe = wm8510_spi_probe, .remove = __devexit_p(wm8510_spi_remove), }; + +static int wm8510_spi_write(struct spi_device *spi, const char *data, int len) +{ + struct spi_transfer t; + struct spi_message m; + u8 msg[2]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} #endif /* CONFIG_SPI_MASTER */ static int wm8510_probe(struct platform_device *pdev) @@ -762,11 +827,13 @@ static int wm8510_probe(struct platform_device *pdev) wm8510_socdev = socdev; #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { + codec->hw_write = (hw_write_t)i2c_master_send; ret = wm8510_add_i2c_device(pdev, setup); } #endif #if defined(CONFIG_SPI_MASTER) if (setup->spi) { + codec->hw_write = (hw_write_t)wm8510_spi_write; ret = spi_register_driver(&wm8510_spi_driver); if (ret != 0) printk(KERN_ERR "can't add spi driver"); diff --git a/trunk/sound/soc/codecs/wm8523.c b/trunk/sound/soc/codecs/wm8523.c deleted file mode 100644 index 25870a4652fb..000000000000 --- a/trunk/sound/soc/codecs/wm8523.c +++ /dev/null @@ -1,699 +0,0 @@ -/* - * wm8523.c -- WM8523 ALSA SoC Audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8523.h" - -static struct snd_soc_codec *wm8523_codec; -struct snd_soc_codec_device soc_codec_dev_wm8523; - -#define WM8523_NUM_SUPPLIES 2 -static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { - "AVDD", - "LINEVDD", -}; - -#define WM8523_NUM_RATES 7 - -/* codec private data */ -struct wm8523_priv { - struct snd_soc_codec codec; - u16 reg_cache[WM8523_REGISTER_COUNT]; - struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; - unsigned int sysclk; - unsigned int rate_constraint_list[WM8523_NUM_RATES]; - struct snd_pcm_hw_constraint_list rate_constraint; -}; - -static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { - 0x8523, /* R0 - DEVICE_ID */ - 0x0001, /* R1 - REVISION */ - 0x0000, /* R2 - PSCTRL1 */ - 0x1812, /* R3 - AIF_CTRL1 */ - 0x0000, /* R4 - AIF_CTRL2 */ - 0x0001, /* R5 - DAC_CTRL3 */ - 0x0190, /* R6 - DAC_GAINL */ - 0x0190, /* R7 - DAC_GAINR */ - 0x0000, /* R8 - ZERO_DETECT */ -}; - -static int wm8523_volatile_register(unsigned int reg) -{ - switch (reg) { - case WM8523_DEVICE_ID: - case WM8523_REVISION: - return 1; - default: - return 0; - } -} - -static int wm8523_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8523_DEVICE_ID, 0); -} - -static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); - -static const char *wm8523_zd_count_text[] = { - "1024", - "2048", -}; - -static const struct soc_enum wm8523_zc_count = - SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); - -static const struct snd_kcontrol_new wm8523_snd_controls[] = { -SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, - 0, 448, 0, dac_tlv), -SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0), -SOC_SINGLE("Playback Deemphasis Switch", WM8523_AIF_CTRL1, 8, 1, 0), -SOC_DOUBLE("Playback Switch", WM8523_DAC_CTRL3, 2, 3, 1, 1), -SOC_SINGLE("Volume Ramp Up Switch", WM8523_DAC_CTRL3, 1, 1, 0), -SOC_SINGLE("Volume Ramp Down Switch", WM8523_DAC_CTRL3, 0, 1, 0), -SOC_ENUM("Zero Detect Count", wm8523_zc_count), -}; - -static const struct snd_soc_dapm_widget wm8523_dapm_widgets[] = { -SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_OUTPUT("LINEVOUTL"), -SND_SOC_DAPM_OUTPUT("LINEVOUTR"), -}; - -static const struct snd_soc_dapm_route intercon[] = { - { "LINEVOUTL", NULL, "DAC" }, - { "LINEVOUTR", NULL, "DAC" }, -}; - -static int wm8523_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, wm8523_dapm_widgets, - ARRAY_SIZE(wm8523_dapm_widgets)); - - snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); - - snd_soc_dapm_new_widgets(codec); - return 0; -} - -static struct { - int value; - int ratio; -} lrclk_ratios[WM8523_NUM_RATES] = { - { 1, 128 }, - { 2, 192 }, - { 3, 256 }, - { 4, 384 }, - { 5, 512 }, - { 6, 768 }, - { 7, 1152 }, -}; - -static int wm8523_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8523_priv *wm8523 = codec->private_data; - - /* The set of sample rates that can be supported depends on the - * MCLK supplied to the CODEC - enforce this. - */ - if (!wm8523->sysclk) { - dev_err(codec->dev, - "No MCLK configured, call set_sysclk() on init\n"); - return -EINVAL; - } - - return 0; - snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &wm8523->rate_constraint); - - return 0; -} - -static int wm8523_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_device *socdev = rtd->socdev; - struct snd_soc_codec *codec = socdev->card->codec; - struct wm8523_priv *wm8523 = codec->private_data; - int i; - u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); - u16 aifctrl2 = snd_soc_read(codec, WM8523_AIF_CTRL2); - - /* Find a supported LRCLK ratio */ - for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { - if (wm8523->sysclk / params_rate(params) == - lrclk_ratios[i].ratio) - break; - } - - /* Should never happen, should be handled by constraints */ - if (i == ARRAY_SIZE(lrclk_ratios)) { - dev_err(codec->dev, "MCLK/fs ratio %d unsupported\n", - wm8523->sysclk / params_rate(params)); - return -EINVAL; - } - - aifctrl2 &= ~WM8523_SR_MASK; - aifctrl2 |= lrclk_ratios[i].value; - - aifctrl1 &= ~WM8523_WL_MASK; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - aifctrl1 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S24_LE: - aifctrl1 |= 0x10; - break; - case SNDRV_PCM_FORMAT_S32_LE: - aifctrl1 |= 0x18; - break; - } - - snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1); - snd_soc_write(codec, WM8523_AIF_CTRL2, aifctrl2); - - return 0; -} - -static int wm8523_set_dai_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8523_priv *wm8523 = codec->private_data; - unsigned int val; - int i; - - wm8523->sysclk = freq; - - wm8523->rate_constraint.count = 0; - for (i = 0; i < ARRAY_SIZE(lrclk_ratios); i++) { - val = freq / lrclk_ratios[i].ratio; - /* Check that it's a standard rate since core can't - * cope with others and having the odd rates confuses - * constraint matching. - */ - switch (val) { - case 8000: - case 11025: - case 16000: - case 22050: - case 32000: - case 44100: - case 48000: - case 64000: - case 88200: - case 96000: - case 176400: - case 192000: - dev_dbg(codec->dev, "Supported sample rate: %dHz\n", - val); - wm8523->rate_constraint_list[i] = val; - wm8523->rate_constraint.count++; - break; - default: - dev_dbg(codec->dev, "Skipping sample rate: %dHz\n", - val); - } - } - - /* Need at least one supported rate... */ - if (wm8523->rate_constraint.count == 0) - return -EINVAL; - - return 0; -} - - -static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 aifctrl1 = snd_soc_read(codec, WM8523_AIF_CTRL1); - - aifctrl1 &= ~(WM8523_BCLK_INV_MASK | WM8523_LRCLK_INV_MASK | - WM8523_FMT_MASK | WM8523_AIF_MSTR_MASK); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - aifctrl1 |= WM8523_AIF_MSTR; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - aifctrl1 |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aifctrl1 |= 0x0001; - break; - case SND_SOC_DAIFMT_DSP_A: - aifctrl1 |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - aifctrl1 |= 0x0023; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aifctrl1 |= WM8523_BCLK_INV | WM8523_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aifctrl1 |= WM8523_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aifctrl1 |= WM8523_LRCLK_INV; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8523_AIF_CTRL1, aifctrl1); - - return 0; -} - -static int wm8523_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8523_priv *wm8523 = codec->private_data; - int ret, i; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - /* Full power on */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 3); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) { - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, - "Failed to enable supplies: %d\n", - ret); - return ret; - } - - /* Initial power up */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 1); - - /* Sync back default/cached values */ - for (i = WM8523_AIF_CTRL1; - i < WM8523_MAX_REGISTER; i++) - snd_soc_write(codec, i, wm8523->reg_cache[i]); - - - msleep(100); - } - - /* Power up to mute */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 2); - - break; - - case SND_SOC_BIAS_OFF: - /* The chip runs through the power down sequence for us. */ - snd_soc_update_bits(codec, WM8523_PSCTRL1, - WM8523_SYS_ENA_MASK, 0); - msleep(100); - - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - break; - } - codec->bias_level = level; - return 0; -} - -#define WM8523_RATES SNDRV_PCM_RATE_8000_192000 - -#define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_ops wm8523_dai_ops = { - .startup = wm8523_startup, - .hw_params = wm8523_hw_params, - .set_sysclk = wm8523_set_dai_sysclk, - .set_fmt = wm8523_set_dai_fmt, -}; - -struct snd_soc_dai wm8523_dai = { - .name = "WM8523", - .playback = { - .stream_name = "Playback", - .channels_min = 2, /* Mono modes not yet supported */ - .channels_max = 2, - .rates = WM8523_RATES, - .formats = WM8523_FORMATS, - }, - .ops = &wm8523_dai_ops, -}; -EXPORT_SYMBOL_GPL(wm8523_dai); - -#ifdef CONFIG_PM -static int wm8523_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8523_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8523_suspend NULL -#define wm8523_resume NULL -#endif - -static int wm8523_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8523_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8523_codec; - codec = wm8523_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8523_snd_controls, - ARRAY_SIZE(wm8523_snd_controls)); - wm8523_add_widgets(codec); - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -static int wm8523_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8523 = { - .probe = wm8523_probe, - .remove = wm8523_remove, - .suspend = wm8523_suspend, - .resume = wm8523_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8523); - -static int wm8523_register(struct wm8523_priv *wm8523, - enum snd_soc_control_type control) -{ - int ret; - struct snd_soc_codec *codec = &wm8523->codec; - int i; - - if (wm8523_codec) { - dev_err(codec->dev, "Another WM8523 is registered\n"); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->private_data = wm8523; - codec->name = "WM8523"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8523_set_bias_level; - codec->dai = &wm8523_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8523_REGISTER_COUNT; - codec->reg_cache = &wm8523->reg_cache; - codec->volatile_register = wm8523_volatile_register; - - wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; - wm8523->rate_constraint.count = - ARRAY_SIZE(wm8523->rate_constraint_list); - - memcpy(codec->reg_cache, wm8523_reg, sizeof(wm8523_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) - wm8523->supplies[i].supply = wm8523_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), - wm8523->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_get; - } - - ret = snd_soc_read(codec, WM8523_DEVICE_ID); - if (ret < 0) { - dev_err(codec->dev, "Failed to read ID register\n"); - goto err_enable; - } - if (ret != wm8523_reg[WM8523_DEVICE_ID]) { - dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); - ret = -EINVAL; - goto err_enable; - } - - ret = snd_soc_read(codec, WM8523_REVISION); - if (ret < 0) { - dev_err(codec->dev, "Failed to read revision register\n"); - goto err_enable; - } - dev_info(codec->dev, "revision %c\n", - (ret & WM8523_CHIP_REV_MASK) + 'A'); - - ret = wm8523_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err_enable; - } - - wm8523_dai.dev = codec->dev; - - /* Change some default settings - latch VU and enable ZC */ - wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; - wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; - - wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Bias level configuration will have done an extra enable */ - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - - wm8523_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - return ret; - } - - ret = snd_soc_register_dai(&wm8523_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - return ret; - } - - return 0; - -err_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err_get: - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); -err: - kfree(wm8523); - return ret; -} - -static void wm8523_unregister(struct wm8523_priv *wm8523) -{ - wm8523_set_bias_level(&wm8523->codec, SND_SOC_BIAS_OFF); - regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); - snd_soc_unregister_dai(&wm8523_dai); - snd_soc_unregister_codec(&wm8523->codec); - kfree(wm8523); - wm8523_codec = NULL; -} - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8523_priv *wm8523; - struct snd_soc_codec *codec; - - wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); - if (wm8523 == NULL) - return -ENOMEM; - - codec = &wm8523->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - - i2c_set_clientdata(i2c, wm8523); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - - return wm8523_register(wm8523, SND_SOC_I2C); -} - -static __devexit int wm8523_i2c_remove(struct i2c_client *client) -{ - struct wm8523_priv *wm8523 = i2c_get_clientdata(client); - wm8523_unregister(wm8523); - return 0; -} - -#ifdef CONFIG_PM -static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) -{ - return snd_soc_suspend_device(&i2c->dev); -} - -static int wm8523_i2c_resume(struct i2c_client *i2c) -{ - return snd_soc_resume_device(&i2c->dev); -} -#else -#define wm8523_i2c_suspend NULL -#define wm8523_i2c_resume NULL -#endif - -static const struct i2c_device_id wm8523_i2c_id[] = { - { "wm8523", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); - -static struct i2c_driver wm8523_i2c_driver = { - .driver = { - .name = "WM8523", - .owner = THIS_MODULE, - }, - .probe = wm8523_i2c_probe, - .remove = __devexit_p(wm8523_i2c_remove), - .suspend = wm8523_i2c_suspend, - .resume = wm8523_i2c_resume, - .id_table = wm8523_i2c_id, -}; -#endif - -static int __init wm8523_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8523_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8523 I2C driver: %d\n", - ret); - } -#endif - return 0; -} -module_init(wm8523_modinit); - -static void __exit wm8523_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8523_i2c_driver); -#endif -} -module_exit(wm8523_exit); - -MODULE_DESCRIPTION("ASoC WM8523 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8523.h b/trunk/sound/soc/codecs/wm8523.h deleted file mode 100644 index 1aa9ce3e1357..000000000000 --- a/trunk/sound/soc/codecs/wm8523.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * wm8523.h -- WM8423 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics, plc - * - * Author: Mark Brown - * - * Based on wm8753.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8523_H -#define _WM8523_H - -/* - * Register values. - */ -#define WM8523_DEVICE_ID 0x00 -#define WM8523_REVISION 0x01 -#define WM8523_PSCTRL1 0x02 -#define WM8523_AIF_CTRL1 0x03 -#define WM8523_AIF_CTRL2 0x04 -#define WM8523_DAC_CTRL3 0x05 -#define WM8523_DAC_GAINL 0x06 -#define WM8523_DAC_GAINR 0x07 -#define WM8523_ZERO_DETECT 0x08 - -#define WM8523_REGISTER_COUNT 9 -#define WM8523_MAX_REGISTER 0x08 - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - DEVICE_ID - */ -#define WM8523_CHIP_ID_MASK 0xFFFF /* CHIP_ID - [15:0] */ -#define WM8523_CHIP_ID_SHIFT 0 /* CHIP_ID - [15:0] */ -#define WM8523_CHIP_ID_WIDTH 16 /* CHIP_ID - [15:0] */ - -/* - * R1 (0x01) - REVISION - */ -#define WM8523_CHIP_REV_MASK 0x0007 /* CHIP_REV - [2:0] */ -#define WM8523_CHIP_REV_SHIFT 0 /* CHIP_REV - [2:0] */ -#define WM8523_CHIP_REV_WIDTH 3 /* CHIP_REV - [2:0] */ - -/* - * R2 (0x02) - PSCTRL1 - */ -#define WM8523_SYS_ENA_MASK 0x0003 /* SYS_ENA - [1:0] */ -#define WM8523_SYS_ENA_SHIFT 0 /* SYS_ENA - [1:0] */ -#define WM8523_SYS_ENA_WIDTH 2 /* SYS_ENA - [1:0] */ - -/* - * R3 (0x03) - AIF_CTRL1 - */ -#define WM8523_TDM_MODE_MASK 0x1800 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_MODE_SHIFT 11 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_MODE_WIDTH 2 /* TDM_MODE - [12:11] */ -#define WM8523_TDM_SLOT_MASK 0x0600 /* TDM_SLOT - [10:9] */ -#define WM8523_TDM_SLOT_SHIFT 9 /* TDM_SLOT - [10:9] */ -#define WM8523_TDM_SLOT_WIDTH 2 /* TDM_SLOT - [10:9] */ -#define WM8523_DEEMPH 0x0100 /* DEEMPH */ -#define WM8523_DEEMPH_MASK 0x0100 /* DEEMPH */ -#define WM8523_DEEMPH_SHIFT 8 /* DEEMPH */ -#define WM8523_DEEMPH_WIDTH 1 /* DEEMPH */ -#define WM8523_AIF_MSTR 0x0080 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_MASK 0x0080 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_SHIFT 7 /* AIF_MSTR */ -#define WM8523_AIF_MSTR_WIDTH 1 /* AIF_MSTR */ -#define WM8523_LRCLK_INV 0x0040 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_MASK 0x0040 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_SHIFT 6 /* LRCLK_INV */ -#define WM8523_LRCLK_INV_WIDTH 1 /* LRCLK_INV */ -#define WM8523_BCLK_INV 0x0020 /* BCLK_INV */ -#define WM8523_BCLK_INV_MASK 0x0020 /* BCLK_INV */ -#define WM8523_BCLK_INV_SHIFT 5 /* BCLK_INV */ -#define WM8523_BCLK_INV_WIDTH 1 /* BCLK_INV */ -#define WM8523_WL_MASK 0x0018 /* WL - [4:3] */ -#define WM8523_WL_SHIFT 3 /* WL - [4:3] */ -#define WM8523_WL_WIDTH 2 /* WL - [4:3] */ -#define WM8523_FMT_MASK 0x0007 /* FMT - [2:0] */ -#define WM8523_FMT_SHIFT 0 /* FMT - [2:0] */ -#define WM8523_FMT_WIDTH 3 /* FMT - [2:0] */ - -/* - * R4 (0x04) - AIF_CTRL2 - */ -#define WM8523_DAC_OP_MUX_MASK 0x00C0 /* DAC_OP_MUX - [7:6] */ -#define WM8523_DAC_OP_MUX_SHIFT 6 /* DAC_OP_MUX - [7:6] */ -#define WM8523_DAC_OP_MUX_WIDTH 2 /* DAC_OP_MUX - [7:6] */ -#define WM8523_BCLKDIV_MASK 0x0038 /* BCLKDIV - [5:3] */ -#define WM8523_BCLKDIV_SHIFT 3 /* BCLKDIV - [5:3] */ -#define WM8523_BCLKDIV_WIDTH 3 /* BCLKDIV - [5:3] */ -#define WM8523_SR_MASK 0x0007 /* SR - [2:0] */ -#define WM8523_SR_SHIFT 0 /* SR - [2:0] */ -#define WM8523_SR_WIDTH 3 /* SR - [2:0] */ - -/* - * R5 (0x05) - DAC_CTRL3 - */ -#define WM8523_ZC 0x0010 /* ZC */ -#define WM8523_ZC_MASK 0x0010 /* ZC */ -#define WM8523_ZC_SHIFT 4 /* ZC */ -#define WM8523_ZC_WIDTH 1 /* ZC */ -#define WM8523_DACR 0x0008 /* DACR */ -#define WM8523_DACR_MASK 0x0008 /* DACR */ -#define WM8523_DACR_SHIFT 3 /* DACR */ -#define WM8523_DACR_WIDTH 1 /* DACR */ -#define WM8523_DACL 0x0004 /* DACL */ -#define WM8523_DACL_MASK 0x0004 /* DACL */ -#define WM8523_DACL_SHIFT 2 /* DACL */ -#define WM8523_DACL_WIDTH 1 /* DACL */ -#define WM8523_VOL_UP_RAMP 0x0002 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_MASK 0x0002 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_SHIFT 1 /* VOL_UP_RAMP */ -#define WM8523_VOL_UP_RAMP_WIDTH 1 /* VOL_UP_RAMP */ -#define WM8523_VOL_DOWN_RAMP 0x0001 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_MASK 0x0001 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_SHIFT 0 /* VOL_DOWN_RAMP */ -#define WM8523_VOL_DOWN_RAMP_WIDTH 1 /* VOL_DOWN_RAMP */ - -/* - * R6 (0x06) - DAC_GAINL - */ -#define WM8523_DACL_VU 0x0200 /* DACL_VU */ -#define WM8523_DACL_VU_MASK 0x0200 /* DACL_VU */ -#define WM8523_DACL_VU_SHIFT 9 /* DACL_VU */ -#define WM8523_DACL_VU_WIDTH 1 /* DACL_VU */ -#define WM8523_DACL_VOL_MASK 0x01FF /* DACL_VOL - [8:0] */ -#define WM8523_DACL_VOL_SHIFT 0 /* DACL_VOL - [8:0] */ -#define WM8523_DACL_VOL_WIDTH 9 /* DACL_VOL - [8:0] */ - -/* - * R7 (0x07) - DAC_GAINR - */ -#define WM8523_DACR_VU 0x0200 /* DACR_VU */ -#define WM8523_DACR_VU_MASK 0x0200 /* DACR_VU */ -#define WM8523_DACR_VU_SHIFT 9 /* DACR_VU */ -#define WM8523_DACR_VU_WIDTH 1 /* DACR_VU */ -#define WM8523_DACR_VOL_MASK 0x01FF /* DACR_VOL - [8:0] */ -#define WM8523_DACR_VOL_SHIFT 0 /* DACR_VOL - [8:0] */ -#define WM8523_DACR_VOL_WIDTH 9 /* DACR_VOL - [8:0] */ - -/* - * R8 (0x08) - ZERO_DETECT - */ -#define WM8523_ZD_COUNT_MASK 0x0003 /* ZD_COUNT - [1:0] */ -#define WM8523_ZD_COUNT_SHIFT 0 /* ZD_COUNT - [1:0] */ -#define WM8523_ZD_COUNT_WIDTH 2 /* ZD_COUNT - [1:0] */ - -extern struct snd_soc_dai wm8523_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8523; - -#endif diff --git a/trunk/sound/soc/codecs/wm8580.c b/trunk/sound/soc/codecs/wm8580.c index 6bded8c78150..86c4b24db817 100644 --- a/trunk/sound/soc/codecs/wm8580.c +++ b/trunk/sound/soc/codecs/wm8580.c @@ -24,8 +24,6 @@ #include #include #include -#include - #include #include #include @@ -189,22 +187,82 @@ struct pll_state { unsigned int out; }; -#define WM8580_NUM_SUPPLIES 3 -static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { - "AVDD", - "DVDD", - "PVDD", -}; - /* codec private data */ struct wm8580_priv { struct snd_soc_codec codec; - struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; u16 reg_cache[WM8580_MAX_REGISTER + 1]; struct pll_state a; struct pll_state b; }; + +/* + * read wm8580 register cache + */ +static inline unsigned int wm8580_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); + return cache[reg]; +} + +/* + * write wm8580 register cache + */ +static inline void wm8580_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + + cache[reg] = value; +} + +/* + * write to the WM8580 register space + */ +static int wm8580_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + BUG_ON(reg >= ARRAY_SIZE(wm8580_reg)); + + /* Registers are 9 bits wide */ + value &= 0x1ff; + + switch (reg) { + case WM8580_RESET: + /* Uncached */ + break; + default: + if (value == wm8580_read_reg_cache(codec, reg)) + return 0; + } + + /* data is + * D15..D9 WM8580 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8580_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +static inline unsigned int wm8580_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + default: + return wm8580_read_reg_cache(codec, reg); + } +} + static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); static int wm8580_out_vu(struct snd_kcontrol *kcontrol, @@ -213,22 +271,25 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; unsigned int reg = mc->reg; unsigned int reg2 = mc->rreg; int ret; + u16 val; /* Clear the register cache so we write without VU set */ - reg_cache[reg] = 0; - reg_cache[reg2] = 0; + wm8580_write_reg_cache(codec, reg, 0); + wm8580_write_reg_cache(codec, reg2, 0); ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); if (ret < 0) return ret; /* Now write again with the volume update bit set */ - snd_soc_update_bits(codec, reg, 0x100, 0x100); - snd_soc_update_bits(codec, reg2, 0x100, 0x100); + val = wm8580_read_reg_cache(codec, reg); + wm8580_write(codec, reg, val | 0x0100); + + val = wm8580_read_reg_cache(codec, reg2); + wm8580_write(codec, reg2, val | 0x0100); return 0; } @@ -451,27 +512,27 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, /* Always disable the PLL - it is not safe to leave it running * while reprogramming it. */ - reg = snd_soc_read(codec, WM8580_PWRDN2); - snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask); + reg = wm8580_read(codec, WM8580_PWRDN2); + wm8580_write(codec, WM8580_PWRDN2, reg | pwr_mask); if (!freq_in || !freq_out) return 0; - snd_soc_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); - snd_soc_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8580_PLLA3 + offset, + wm8580_write(codec, WM8580_PLLA1 + offset, pll_div.k & 0x1ff); + wm8580_write(codec, WM8580_PLLA2 + offset, (pll_div.k >> 9) & 0xff); + wm8580_write(codec, WM8580_PLLA3 + offset, (pll_div.k >> 18 & 0xf) | (pll_div.n << 4)); - reg = snd_soc_read(codec, WM8580_PLLA4 + offset); - reg &= ~0x1b; + reg = wm8580_read(codec, WM8580_PLLA4 + offset); + reg &= ~0x3f; reg |= pll_div.prescale | pll_div.postscale << 1 | pll_div.freqmode << 3; - snd_soc_write(codec, WM8580_PLLA4 + offset, reg); + wm8580_write(codec, WM8580_PLLA4 + offset, reg); /* All done, turn it on */ - reg = snd_soc_read(codec, WM8580_PWRDN2); - snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); + reg = wm8580_read(codec, WM8580_PWRDN2); + wm8580_write(codec, WM8580_PWRDN2, reg & ~pwr_mask); return 0; } @@ -486,7 +547,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 paifb = snd_soc_read(codec, WM8580_PAIF3 + dai->id); + u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); paifb &= ~WM8580_AIF_LENGTH_MASK; /* bit size */ @@ -506,7 +567,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_soc_write(codec, WM8580_PAIF3 + dai->id, paifb); + wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb); return 0; } @@ -518,8 +579,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int aifb; int can_invert_lrclk; - aifa = snd_soc_read(codec, WM8580_PAIF1 + codec_dai->id); - aifb = snd_soc_read(codec, WM8580_PAIF3 + codec_dai->id); + aifa = wm8580_read(codec, WM8580_PAIF1 + codec_dai->id); + aifb = wm8580_read(codec, WM8580_PAIF3 + codec_dai->id); aifb &= ~(WM8580_AIF_FMT_MASK | WM8580_AIF_LRP | WM8580_AIF_BCP); @@ -585,8 +646,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); - snd_soc_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); + wm8580_write(codec, WM8580_PAIF1 + codec_dai->id, aifa); + wm8580_write(codec, WM8580_PAIF3 + codec_dai->id, aifb); return 0; } @@ -599,7 +660,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8580_MCLK: - reg = snd_soc_read(codec, WM8580_PLLB4); + reg = wm8580_read(codec, WM8580_PLLB4); reg &= ~WM8580_PLLB4_MCLKOUTSRC_MASK; switch (div) { @@ -621,11 +682,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, default: return -EINVAL; } - snd_soc_write(codec, WM8580_PLLB4, reg); + wm8580_write(codec, WM8580_PLLB4, reg); break; case WM8580_DAC_CLKSEL: - reg = snd_soc_read(codec, WM8580_CLKSEL); + reg = wm8580_read(codec, WM8580_CLKSEL); reg &= ~WM8580_CLKSEL_DAC_CLKSEL_MASK; switch (div) { @@ -643,11 +704,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, default: return -EINVAL; } - snd_soc_write(codec, WM8580_CLKSEL, reg); + wm8580_write(codec, WM8580_CLKSEL, reg); break; case WM8580_CLKOUTSRC: - reg = snd_soc_read(codec, WM8580_PLLB4); + reg = wm8580_read(codec, WM8580_PLLB4); reg &= ~WM8580_PLLB4_CLKOUTSRC_MASK; switch (div) { @@ -669,7 +730,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai, default: return -EINVAL; } - snd_soc_write(codec, WM8580_PLLB4, reg); + wm8580_write(codec, WM8580_PLLB4, reg); break; default: @@ -684,14 +745,14 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute) struct snd_soc_codec *codec = codec_dai->codec; unsigned int reg; - reg = snd_soc_read(codec, WM8580_DAC_CONTROL5); + reg = wm8580_read(codec, WM8580_DAC_CONTROL5); if (mute) reg |= WM8580_DAC_CONTROL5_MUTEALL; else reg &= ~WM8580_DAC_CONTROL5_MUTEALL; - snd_soc_write(codec, WM8580_DAC_CONTROL5, reg); + wm8580_write(codec, WM8580_DAC_CONTROL5, reg); return 0; } @@ -708,20 +769,20 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Power up and get individual control of the DACs */ - reg = snd_soc_read(codec, WM8580_PWRDN1); + reg = wm8580_read(codec, WM8580_PWRDN1); reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD); - snd_soc_write(codec, WM8580_PWRDN1, reg); + wm8580_write(codec, WM8580_PWRDN1, reg); /* Make VMID high impedence */ - reg = snd_soc_read(codec, WM8580_ADC_CONTROL1); + reg = wm8580_read(codec, WM8580_ADC_CONTROL1); reg &= ~0x100; - snd_soc_write(codec, WM8580_ADC_CONTROL1, reg); + wm8580_write(codec, WM8580_ADC_CONTROL1, reg); } break; case SND_SOC_BIAS_OFF: - reg = snd_soc_read(codec, WM8580_PWRDN1); - snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); + reg = wm8580_read(codec, WM8580_PWRDN1); + wm8580_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN); break; } codec->bias_level = level; @@ -832,8 +893,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = { }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); -static int wm8580_register(struct wm8580_priv *wm8580, - enum snd_soc_control_type control) +static int wm8580_register(struct wm8580_priv *wm8580) { int ret, i; struct snd_soc_codec *codec = &wm8580->codec; @@ -851,6 +911,8 @@ static int wm8580_register(struct wm8580_priv *wm8580, codec->private_data = wm8580; codec->name = "WM8580"; codec->owner = THIS_MODULE; + codec->read = wm8580_read_reg_cache; + codec->write = wm8580_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8580_set_bias_level; codec->dai = wm8580_dai; @@ -860,34 +922,11 @@ static int wm8580_register(struct wm8580_priv *wm8580, memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) - wm8580->supplies[i].supply = wm8580_supply_names[i]; - - ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), - wm8580->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to request supplies: %d\n", ret); - goto err; - } - - ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), - wm8580->supplies); - if (ret != 0) { - dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); - goto err_regulator_get; - } - /* Get the codec into a known state */ - ret = snd_soc_write(codec, WM8580_RESET, 0); + ret = wm8580_write(codec, WM8580_RESET, 0); if (ret != 0) { dev_err(codec->dev, "Failed to reset codec: %d\n", ret); - goto err_regulator_enable; + goto err; } for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) @@ -900,7 +939,7 @@ static int wm8580_register(struct wm8580_priv *wm8580, ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err_regulator_enable; + goto err; } ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); @@ -913,10 +952,6 @@ static int wm8580_register(struct wm8580_priv *wm8580, err_codec: snd_soc_unregister_codec(codec); -err_regulator_enable: - regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); -err_regulator_get: - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); err: kfree(wm8580); return ret; @@ -927,8 +962,6 @@ static void wm8580_unregister(struct wm8580_priv *wm8580) wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); snd_soc_unregister_codec(&wm8580->codec); - regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); - regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); kfree(wm8580); wm8580_codec = NULL; } @@ -945,13 +978,14 @@ static int wm8580_i2c_probe(struct i2c_client *i2c, return -ENOMEM; codec = &wm8580->codec; + codec->hw_write = (hw_write_t)i2c_master_send; i2c_set_clientdata(i2c, wm8580); codec->control_data = i2c; codec->dev = &i2c->dev; - return wm8580_register(wm8580, SND_SOC_I2C); + return wm8580_register(wm8580); } static int wm8580_i2c_remove(struct i2c_client *client) @@ -961,21 +995,6 @@ static int wm8580_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8580_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8580_i2c_suspend NULL -#define wm8580_i2c_resume NULL -#endif - static const struct i2c_device_id wm8580_i2c_id[] = { { "wm8580", 0 }, { } @@ -989,8 +1008,6 @@ static struct i2c_driver wm8580_i2c_driver = { }, .probe = wm8580_i2c_probe, .remove = wm8580_i2c_remove, - .suspend = wm8580_i2c_suspend, - .resume = wm8580_i2c_resume, .id_table = wm8580_i2c_id, }; #endif diff --git a/trunk/sound/soc/codecs/wm8728.c b/trunk/sound/soc/codecs/wm8728.c index 16e969a762c3..e7ff2121ede9 100644 --- a/trunk/sound/soc/codecs/wm8728.c +++ b/trunk/sound/soc/codecs/wm8728.c @@ -43,6 +43,45 @@ static const u16 wm8728_reg_defaults[] = { 0x100, }; +static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); + return cache[reg]; +} + +static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec, + u16 reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults)); + cache[reg] = value; +} + +/* + * write to the WM8728 register space + */ +static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + /* data is + * D15..D9 WM8728 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8728_write_reg_cache(codec, reg, value); + + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); static const struct snd_kcontrol_new wm8728_snd_controls[] = { @@ -82,12 +121,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec) static int wm8728_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8728_DACCTL); + u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); if (mute) - snd_soc_write(codec, WM8728_DACCTL, mute_reg | 1); + wm8728_write(codec, WM8728_DACCTL, mute_reg | 1); else - snd_soc_write(codec, WM8728_DACCTL, mute_reg & ~1); + wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1); return 0; } @@ -99,7 +138,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 dac = snd_soc_read(codec, WM8728_DACCTL); + u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); dac &= ~0x18; @@ -116,7 +155,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_soc_write(codec, WM8728_DACCTL, dac); + wm8728_write(codec, WM8728_DACCTL, dac); return 0; } @@ -125,7 +164,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = snd_soc_read(codec, WM8728_IFCTL); + u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL); /* Currently only I2S is supported by the driver, though the * hardware is more flexible. @@ -165,7 +204,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8728_IFCTL, iface); + wm8728_write(codec, WM8728_IFCTL, iface); return 0; } @@ -181,19 +220,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Power everything up... */ - reg = snd_soc_read(codec, WM8728_DACCTL); - snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); + reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); + wm8728_write(codec, WM8728_DACCTL, reg & ~0x4); /* ..then sync in the register cache. */ for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) - snd_soc_write(codec, i, - snd_soc_read(codec, i)); + wm8728_write(codec, i, + wm8728_read_reg_cache(codec, i)); } break; case SND_SOC_BIAS_OFF: - reg = snd_soc_read(codec, WM8728_DACCTL); - snd_soc_write(codec, WM8728_DACCTL, reg | 0x4); + reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); + wm8728_write(codec, WM8728_DACCTL, reg | 0x4); break; } codec->bias_level = level; @@ -248,14 +287,15 @@ static int wm8728_resume(struct platform_device *pdev) * initialise the WM8728 driver * register the mixer and dsp interfaces with the kernel */ -static int wm8728_init(struct snd_soc_device *socdev, - enum snd_soc_control_type control) +static int wm8728_init(struct snd_soc_device *socdev) { struct snd_soc_codec *codec = socdev->card->codec; int ret = 0; codec->name = "WM8728"; codec->owner = THIS_MODULE; + codec->read = wm8728_read_reg_cache; + codec->write = wm8728_write; codec->set_bias_level = wm8728_set_bias_level; codec->dai = &wm8728_dai; codec->num_dai = 1; @@ -267,18 +307,11 @@ static int wm8728_init(struct snd_soc_device *socdev, if (codec->reg_cache == NULL) return -ENOMEM; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", - ret); - goto err; - } - /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8728: failed to create pcms\n"); - goto err; + goto pcm_err; } /* power on device */ @@ -298,7 +331,7 @@ static int wm8728_init(struct snd_soc_device *socdev, card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -err: +pcm_err: kfree(codec->reg_cache); return ret; } @@ -324,7 +357,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, codec); codec->control_data = i2c; - ret = wm8728_init(socdev, SND_SOC_I2C); + ret = wm8728_init(socdev); if (ret < 0) pr_err("failed to initialise WM8728\n"); @@ -404,7 +437,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi) codec->control_data = spi; - ret = wm8728_init(socdev, SND_SOC_SPI); + ret = wm8728_init(socdev); if (ret < 0) dev_err(&spi->dev, "failed to initialise WM8728\n"); @@ -425,6 +458,30 @@ static struct spi_driver wm8728_spi_driver = { .probe = wm8728_spi_probe, .remove = __devexit_p(wm8728_spi_remove), }; + +static int wm8728_spi_write(struct spi_device *spi, const char *data, int len) +{ + struct spi_transfer t; + struct spi_message m; + u8 msg[2]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} #endif /* CONFIG_SPI_MASTER */ static int wm8728_probe(struct platform_device *pdev) @@ -449,11 +506,13 @@ static int wm8728_probe(struct platform_device *pdev) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { + codec->hw_write = (hw_write_t)i2c_master_send; ret = wm8728_add_i2c_device(pdev, setup); } #endif #if defined(CONFIG_SPI_MASTER) if (setup->spi) { + codec->hw_write = (hw_write_t)wm8728_spi_write; ret = spi_register_driver(&wm8728_spi_driver); if (ret != 0) printk(KERN_ERR "can't add spi driver"); diff --git a/trunk/sound/soc/codecs/wm8731.c b/trunk/sound/soc/codecs/wm8731.c index d3fd4f28d96e..7a205876ef4f 100644 --- a/trunk/sound/soc/codecs/wm8731.c +++ b/trunk/sound/soc/codecs/wm8731.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "wm8731.h" @@ -40,6 +39,9 @@ struct wm8731_priv { unsigned int sysclk; }; +#ifdef CONFIG_SPI_MASTER +static int wm8731_spi_write(struct spi_device *spi, const char *data, int len); +#endif /* * wm8731 register cache @@ -48,12 +50,60 @@ struct wm8731_priv { * There is no point in caching the reset register */ static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { - 0x0097, 0x0097, 0x0079, 0x0079, - 0x000a, 0x0008, 0x009f, 0x000a, - 0x0000, 0x0000 + 0x0097, 0x0097, 0x0079, 0x0079, + 0x000a, 0x0008, 0x009f, 0x000a, + 0x0000, 0x0000 }; -#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0) +/* + * read wm8731 register cache + */ +static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg == WM8731_RESET) + return 0; + if (reg >= WM8731_CACHEREGNUM) + return -1; + return cache[reg]; +} + +/* + * write wm8731 register cache + */ +static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec, + u16 reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg >= WM8731_CACHEREGNUM) + return; + cache[reg] = value; +} + +/* + * write to the WM8731 register space + */ +static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + /* data is + * D15..D9 WM8731 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8731_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0) static const char *wm8731_input_select[] = {"Line In", "Mic"}; static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; @@ -63,26 +113,20 @@ static const struct soc_enum wm8731_enum[] = { SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph), }; -static const DECLARE_TLV_DB_SCALE(in_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -1500, 300, 0); -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); - static const struct snd_kcontrol_new wm8731_snd_controls[] = { -SOC_DOUBLE_R_TLV("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, - 0, 127, 0, out_tlv), +SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V, + 0, 127, 0), SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V, 7, 1, 0), -SOC_DOUBLE_R_TLV("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0, - in_tlv), +SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0), SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1), SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0), -SOC_SINGLE("Mic Capture Switch", WM8731_APANA, 1, 1, 1), +SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1), -SOC_SINGLE_TLV("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1, - sidetone_tlv), +SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1), SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1), SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0), @@ -216,12 +260,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct wm8731_priv *wm8731 = codec->private_data; - u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3; + u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; int i = get_coeff(wm8731->sysclk, params_rate(params)); u16 srate = (coeff_div[i].sr << 2) | (coeff_div[i].bosr << 1) | coeff_div[i].usb; - snd_soc_write(codec, WM8731_SRATE, srate); + wm8731_write(codec, WM8731_SRATE, srate); /* bit size */ switch (params_format(params)) { @@ -235,7 +279,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, break; } - snd_soc_write(codec, WM8731_IFACE, iface); + wm8731_write(codec, WM8731_IFACE, iface); return 0; } @@ -247,7 +291,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = socdev->card->codec; /* set active */ - snd_soc_write(codec, WM8731_ACTIVE, 0x0001); + wm8731_write(codec, WM8731_ACTIVE, 0x0001); return 0; } @@ -262,19 +306,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream, /* deactivate */ if (!codec->active) { udelay(50); - snd_soc_write(codec, WM8731_ACTIVE, 0x0); + wm8731_write(codec, WM8731_ACTIVE, 0x0); } } static int wm8731_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7; + u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7; if (mute) - snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8); + wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8); else - snd_soc_write(codec, WM8731_APDIGI, mute_reg); + wm8731_write(codec, WM8731_APDIGI, mute_reg); return 0; } @@ -352,7 +396,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, } /* set iface */ - snd_soc_write(codec, WM8731_IFACE, iface); + wm8731_write(codec, WM8731_IFACE, iface); return 0; } @@ -368,12 +412,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: /* Clear PWROFF, gate CLKOUT, everything else as-is */ - reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f; - snd_soc_write(codec, WM8731_PWR, reg | 0x0040); + reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; + wm8731_write(codec, WM8731_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8731_ACTIVE, 0x0); - snd_soc_write(codec, WM8731_PWR, 0xffff); + wm8731_write(codec, WM8731_ACTIVE, 0x0); + wm8731_write(codec, WM8731_PWR, 0xffff); break; } codec->bias_level = level; @@ -413,17 +457,15 @@ struct snd_soc_dai wm8731_dai = { .rates = WM8731_RATES, .formats = WM8731_FORMATS,}, .ops = &wm8731_dai_ops, - .symmetric_rates = 1, }; EXPORT_SYMBOL_GPL(wm8731_dai); -#ifdef CONFIG_PM static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->card->codec; - snd_soc_write(codec, WM8731_ACTIVE, 0x0); + wm8731_write(codec, WM8731_ACTIVE, 0x0); wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); return 0; } @@ -446,10 +488,6 @@ static int wm8731_resume(struct platform_device *pdev) wm8731_set_bias_level(codec, codec->suspend_bias_level); return 0; } -#else -#define wm8731_suspend NULL -#define wm8731_resume NULL -#endif static int wm8731_probe(struct platform_device *pdev) { @@ -509,16 +547,15 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = { }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); -static int wm8731_register(struct wm8731_priv *wm8731, - enum snd_soc_control_type control) +static int wm8731_register(struct wm8731_priv *wm8731) { int ret; struct snd_soc_codec *codec = &wm8731->codec; + u16 reg; if (wm8731_codec) { dev_err(codec->dev, "Another WM8731 is registered\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } mutex_init(&codec->mutex); @@ -528,6 +565,8 @@ static int wm8731_register(struct wm8731_priv *wm8731, codec->private_data = wm8731; codec->name = "WM8731"; codec->owner = THIS_MODULE; + codec->read = wm8731_read_reg_cache; + codec->write = wm8731_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8731_set_bias_level; codec->dai = &wm8731_dai; @@ -537,16 +576,10 @@ static int wm8731_register(struct wm8731_priv *wm8731, memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - ret = wm8731_reset(codec); if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err; + dev_err(codec->dev, "Failed to issue reset\n"); + return ret; } wm8731_dai.dev = codec->dev; @@ -554,36 +587,35 @@ static int wm8731_register(struct wm8731_priv *wm8731, wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ - snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0); - snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0); - snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0); - snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0); + reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); + wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); + reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); + wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); + reg = wm8731_read_reg_cache(codec, WM8731_LINVOL); + wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100); + reg = wm8731_read_reg_cache(codec, WM8731_RINVOL); + wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100); /* Disable bypass path by default */ - snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0); + reg = wm8731_read_reg_cache(codec, WM8731_APANA); + wm8731_write(codec, WM8731_APANA, reg & ~0x4); wm8731_codec = codec; ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; + return ret; } ret = snd_soc_register_dai(&wm8731_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); snd_soc_unregister_codec(codec); - goto err_codec; + return ret; } return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8731); - return ret; } static void wm8731_unregister(struct wm8731_priv *wm8731) @@ -596,6 +628,30 @@ static void wm8731_unregister(struct wm8731_priv *wm8731) } #if defined(CONFIG_SPI_MASTER) +static int wm8731_spi_write(struct spi_device *spi, const char *data, int len) +{ + struct spi_transfer t; + struct spi_message m; + u8 msg[2]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} + static int __devinit wm8731_spi_probe(struct spi_device *spi) { struct snd_soc_codec *codec; @@ -607,11 +663,12 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi) codec = &wm8731->codec; codec->control_data = spi; + codec->hw_write = (hw_write_t)wm8731_spi_write; codec->dev = &spi->dev; dev_set_drvdata(&spi->dev, wm8731); - return wm8731_register(wm8731, SND_SOC_SPI); + return wm8731_register(wm8731); } static int __devexit wm8731_spi_remove(struct spi_device *spi) @@ -623,21 +680,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return snd_soc_suspend_device(&spi->dev); -} - -static int wm8731_spi_resume(struct spi_device *spi) -{ - return snd_soc_resume_device(&spi->dev); -} -#else -#define wm8731_spi_suspend NULL -#define wm8731_spi_resume NULL -#endif - static struct spi_driver wm8731_spi_driver = { .driver = { .name = "wm8731", @@ -645,8 +687,6 @@ static struct spi_driver wm8731_spi_driver = { .owner = THIS_MODULE, }, .probe = wm8731_spi_probe, - .suspend = wm8731_spi_suspend, - .resume = wm8731_spi_resume, .remove = __devexit_p(wm8731_spi_remove), }; #endif /* CONFIG_SPI_MASTER */ @@ -663,13 +703,14 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c, return -ENOMEM; codec = &wm8731->codec; + codec->hw_write = (hw_write_t)i2c_master_send; i2c_set_clientdata(i2c, wm8731); codec->control_data = i2c; codec->dev = &i2c->dev; - return wm8731_register(wm8731, SND_SOC_I2C); + return wm8731_register(wm8731); } static __devexit int wm8731_i2c_remove(struct i2c_client *client) @@ -679,21 +720,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) -{ - return snd_soc_suspend_device(&i2c->dev); -} - -static int wm8731_i2c_resume(struct i2c_client *i2c) -{ - return snd_soc_resume_device(&i2c->dev); -} -#else -#define wm8731_i2c_suspend NULL -#define wm8731_i2c_resume NULL -#endif - static const struct i2c_device_id wm8731_i2c_id[] = { { "wm8731", 0 }, { } @@ -707,8 +733,6 @@ static struct i2c_driver wm8731_i2c_driver = { }, .probe = wm8731_i2c_probe, .remove = __devexit_p(wm8731_i2c_remove), - .suspend = wm8731_i2c_suspend, - .resume = wm8731_i2c_resume, .id_table = wm8731_i2c_id, }; #endif diff --git a/trunk/sound/soc/codecs/wm8750.c b/trunk/sound/soc/codecs/wm8750.c index 4ba1e7e93fb4..b64509b01a49 100644 --- a/trunk/sound/soc/codecs/wm8750.c +++ b/trunk/sound/soc/codecs/wm8750.c @@ -55,7 +55,50 @@ static const u16 wm8750_reg[] = { 0x0079, 0x0079, 0x0079, /* 40 */ }; -#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) +/* + * read wm8750 register cache + */ +static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg > WM8750_CACHE_REGNUM) + return -1; + return cache[reg]; +} + +/* + * write wm8750 register cache + */ +static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg > WM8750_CACHE_REGNUM) + return; + cache[reg] = value; +} + +static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + /* data is + * D15..D9 WM8753 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8750_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +#define wm8750_reset(c) wm8750_write(c, WM8750_RESET, 0) /* * WM8750 Controls @@ -551,7 +594,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8750_IFACE, iface); + wm8750_write(codec, WM8750_IFACE, iface); return 0; } @@ -563,8 +606,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct wm8750_priv *wm8750 = codec->private_data; - u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; - u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; + u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; + u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; int coeff = get_coeff(wm8750->sysclk, params_rate(params)); /* bit size */ @@ -583,9 +626,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, } /* set iface & srate */ - snd_soc_write(codec, WM8750_IFACE, iface); + wm8750_write(codec, WM8750_IFACE, iface); if (coeff >= 0) - snd_soc_write(codec, WM8750_SRATE, srate | + wm8750_write(codec, WM8750_SRATE, srate | (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); return 0; @@ -594,35 +637,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, static int wm8750_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7; + u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7; if (mute) - snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8); + wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8); else - snd_soc_write(codec, WM8750_ADCDAC, mute_reg); + wm8750_write(codec, WM8750_ADCDAC, mute_reg); return 0; } static int wm8750_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e; + u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: /* set vmid to 50k and unmute dac */ - snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); + wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); break; case SND_SOC_BIAS_PREPARE: /* set vmid to 5k for quick power up */ - snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); + wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); break; case SND_SOC_BIAS_STANDBY: /* mute dac and set vmid to 500k, enable VREF */ - snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141); + wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141); break; case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8750_PWR1, 0x0001); + wm8750_write(codec, WM8750_PWR1, 0x0001); break; } codec->bias_level = level; @@ -711,14 +754,15 @@ static int wm8750_resume(struct platform_device *pdev) * initialise the WM8750 driver * register the mixer and dsp interfaces with the kernel */ -static int wm8750_init(struct snd_soc_device *socdev, - enum snd_soc_control_type control) +static int wm8750_init(struct snd_soc_device *socdev) { struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8750"; codec->owner = THIS_MODULE; + codec->read = wm8750_read_reg_cache; + codec->write = wm8750_write; codec->set_bias_level = wm8750_set_bias_level; codec->dai = &wm8750_dai; codec->num_dai = 1; @@ -727,23 +771,13 @@ static int wm8750_init(struct snd_soc_device *socdev, if (codec->reg_cache == NULL) return -ENOMEM; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); - goto err; - } - - ret = wm8750_reset(codec); - if (ret < 0) { - printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); - goto err; - } + wm8750_reset(codec); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8750: failed to create pcms\n"); - goto err; + goto pcm_err; } /* charge output caps */ @@ -752,22 +786,22 @@ static int wm8750_init(struct snd_soc_device *socdev, schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000)); /* set the update bits */ - reg = snd_soc_read(codec, WM8750_LDAC); - snd_soc_write(codec, WM8750_LDAC, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_RDAC); - snd_soc_write(codec, WM8750_RDAC, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_LOUT1V); - snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_ROUT1V); - snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_LOUT2V); - snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_ROUT2V); - snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_LINVOL); - snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100); - reg = snd_soc_read(codec, WM8750_RINVOL); - snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); + reg = wm8750_read_reg_cache(codec, WM8750_LDAC); + wm8750_write(codec, WM8750_LDAC, reg | 0x0100); + reg = wm8750_read_reg_cache(codec, WM8750_RDAC); + wm8750_write(codec, WM8750_RDAC, reg | 0x0100); + reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V); + wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100); + reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V); + wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100); + reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V); + wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100); + reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V); + wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100); + reg = wm8750_read_reg_cache(codec, WM8750_LINVOL); + wm8750_write(codec, WM8750_LINVOL, reg | 0x0100); + reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); + wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); snd_soc_add_controls(codec, wm8750_snd_controls, ARRAY_SIZE(wm8750_snd_controls)); @@ -782,7 +816,7 @@ static int wm8750_init(struct snd_soc_device *socdev, card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -err: +pcm_err: kfree(codec->reg_cache); return ret; } @@ -810,7 +844,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c, i2c_set_clientdata(i2c, codec); codec->control_data = i2c; - ret = wm8750_init(socdev, SND_SOC_I2C); + ret = wm8750_init(socdev); if (ret < 0) pr_err("failed to initialise WM8750\n"); @@ -890,7 +924,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi) codec->control_data = spi; - ret = wm8750_init(socdev, SND_SOC_SPI); + ret = wm8750_init(socdev); if (ret < 0) dev_err(&spi->dev, "failed to initialise WM8750\n"); @@ -911,6 +945,30 @@ static struct spi_driver wm8750_spi_driver = { .probe = wm8750_spi_probe, .remove = __devexit_p(wm8750_spi_remove), }; + +static int wm8750_spi_write(struct spi_device *spi, const char *data, int len) +{ + struct spi_transfer t; + struct spi_message m; + u8 msg[2]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} #endif static int wm8750_probe(struct platform_device *pdev) @@ -944,11 +1002,13 @@ static int wm8750_probe(struct platform_device *pdev) #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) if (setup->i2c_address) { + codec->hw_write = (hw_write_t)i2c_master_send; ret = wm8750_add_i2c_device(pdev, setup); } #endif #if defined(CONFIG_SPI_MASTER) if (setup->spi) { + codec->hw_write = (hw_write_t)wm8750_spi_write; ret = spi_register_driver(&wm8750_spi_driver); if (ret != 0) printk(KERN_ERR "can't add spi driver"); diff --git a/trunk/sound/soc/codecs/wm8753.c b/trunk/sound/soc/codecs/wm8753.c index d80d414cfbbd..49c4b2898aff 100644 --- a/trunk/sound/soc/codecs/wm8753.c +++ b/trunk/sound/soc/codecs/wm8753.c @@ -1766,21 +1766,6 @@ static int wm8753_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8753_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8753_i2c_suspend NULL -#define wm8753_i2c_resume NULL -#endif - static const struct i2c_device_id wm8753_i2c_id[] = { { "wm8753", 0 }, { } @@ -1794,8 +1779,6 @@ static struct i2c_driver wm8753_i2c_driver = { }, .probe = wm8753_i2c_probe, .remove = wm8753_i2c_remove, - .suspend = wm8753_i2c_suspend, - .resume = wm8753_i2c_resume, .id_table = wm8753_i2c_id, }; #endif @@ -1851,22 +1834,6 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return snd_soc_suspend_device(&spi->dev); -} - -static int wm8753_spi_resume(struct spi_device *spi) -{ - return snd_soc_resume_device(&spi->dev); -} - -#else -#define wm8753_spi_suspend NULL -#define wm8753_spi_resume NULL -#endif - static struct spi_driver wm8753_spi_driver = { .driver = { .name = "wm8753", @@ -1875,8 +1842,6 @@ static struct spi_driver wm8753_spi_driver = { }, .probe = wm8753_spi_probe, .remove = __devexit_p(wm8753_spi_remove), - .suspend = wm8753_spi_suspend, - .resume = wm8753_spi_resume, }; #endif diff --git a/trunk/sound/soc/codecs/wm8776.c b/trunk/sound/soc/codecs/wm8776.c deleted file mode 100644 index a9829aa26e53..000000000000 --- a/trunk/sound/soc/codecs/wm8776.c +++ /dev/null @@ -1,744 +0,0 @@ -/* - * wm8776.c -- WM8776 ALSA SoC Audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: Input ALC/limiter support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8776.h" - -static struct snd_soc_codec *wm8776_codec; -struct snd_soc_codec_device soc_codec_dev_wm8776; - -/* codec private data */ -struct wm8776_priv { - struct snd_soc_codec codec; - u16 reg_cache[WM8776_CACHEREGNUM]; - int sysclk[2]; -}; - -#ifdef CONFIG_SPI_MASTER -static int wm8776_spi_write(struct spi_device *spi, const char *data, int len); -#endif - -static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { - 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ - 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ - 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */ - 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */ - 0xa6, 0x01, 0x01 -}; - -static int wm8776_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8776_RESET, 0); -} - -static const DECLARE_TLV_DB_SCALE(hp_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -10350, 50, 1); - -static const struct snd_kcontrol_new wm8776_snd_controls[] = { -SOC_DOUBLE_R_TLV("Headphone Playback Volume", WM8776_HPLVOL, WM8776_HPRVOL, - 0, 127, 0, hp_tlv), -SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8776_DACLVOL, WM8776_DACRVOL, - 0, 255, 0, dac_tlv), -SOC_SINGLE("Digital Playback ZC Switch", WM8776_DACCTRL1, 0, 1, 0), - -SOC_SINGLE("Deemphasis Switch", WM8776_DACCTRL2, 0, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8776_ADCLVOL, WM8776_ADCRVOL, - 0, 255, 0, adc_tlv), -SOC_DOUBLE("Capture Switch", WM8776_ADCMUX, 7, 6, 1, 1), -SOC_DOUBLE_R("Capture ZC Switch", WM8776_ADCLVOL, WM8776_ADCRVOL, 8, 1, 0), -SOC_SINGLE("Capture HPF Switch", WM8776_ADCIFCTRL, 8, 1, 1), -}; - -static const struct snd_kcontrol_new inmix_controls[] = { -SOC_DAPM_SINGLE("AIN1 Switch", WM8776_ADCMUX, 0, 1, 0), -SOC_DAPM_SINGLE("AIN2 Switch", WM8776_ADCMUX, 1, 1, 0), -SOC_DAPM_SINGLE("AIN3 Switch", WM8776_ADCMUX, 2, 1, 0), -SOC_DAPM_SINGLE("AIN4 Switch", WM8776_ADCMUX, 3, 1, 0), -SOC_DAPM_SINGLE("AIN5 Switch", WM8776_ADCMUX, 4, 1, 0), -}; - -static const struct snd_kcontrol_new outmix_controls[] = { -SOC_DAPM_SINGLE("DAC Switch", WM8776_OUTMUX, 0, 1, 0), -SOC_DAPM_SINGLE("AUX Switch", WM8776_OUTMUX, 1, 1, 0), -SOC_DAPM_SINGLE("Bypass Switch", WM8776_OUTMUX, 2, 1, 0), -}; - -static const struct snd_soc_dapm_widget wm8776_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("AUX"), -SND_SOC_DAPM_INPUT("AUX"), - -SND_SOC_DAPM_INPUT("AIN1"), -SND_SOC_DAPM_INPUT("AIN2"), -SND_SOC_DAPM_INPUT("AIN3"), -SND_SOC_DAPM_INPUT("AIN4"), -SND_SOC_DAPM_INPUT("AIN5"), - -SND_SOC_DAPM_MIXER("Input Mixer", WM8776_PWRDOWN, 6, 1, - inmix_controls, ARRAY_SIZE(inmix_controls)), - -SND_SOC_DAPM_ADC("ADC", "Capture", WM8776_PWRDOWN, 1, 1), -SND_SOC_DAPM_DAC("DAC", "Playback", WM8776_PWRDOWN, 2, 1), - -SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, - outmix_controls, ARRAY_SIZE(outmix_controls)), - -SND_SOC_DAPM_PGA("Headphone PGA", WM8776_PWRDOWN, 3, 1, NULL, 0), - -SND_SOC_DAPM_OUTPUT("VOUT"), - -SND_SOC_DAPM_OUTPUT("HPOUTL"), -SND_SOC_DAPM_OUTPUT("HPOUTR"), -}; - -static const struct snd_soc_dapm_route routes[] = { - { "Input Mixer", "AIN1 Switch", "AIN1" }, - { "Input Mixer", "AIN2 Switch", "AIN2" }, - { "Input Mixer", "AIN3 Switch", "AIN3" }, - { "Input Mixer", "AIN4 Switch", "AIN4" }, - { "Input Mixer", "AIN5 Switch", "AIN5" }, - - { "ADC", NULL, "Input Mixer" }, - - { "Output Mixer", "DAC Switch", "DAC" }, - { "Output Mixer", "AUX Switch", "AUX" }, - { "Output Mixer", "Bypass Switch", "Input Mixer" }, - - { "VOUT", NULL, "Output Mixer" }, - - { "Headphone PGA", NULL, "Output Mixer" }, - - { "HPOUTL", NULL, "Headphone PGA" }, - { "HPOUTR", NULL, "Headphone PGA" }, -}; - -static int wm8776_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - int reg, iface, master; - - switch (dai->id) { - case WM8776_DAI_DAC: - reg = WM8776_DACIFCTRL; - master = 0x80; - break; - case WM8776_DAI_ADC: - reg = WM8776_ADCIFCTRL; - master = 0x100; - break; - default: - return -EINVAL; - } - - iface = 0; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - break; - case SND_SOC_DAIFMT_CBS_CFS: - master = 0; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0002; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0001; - break; - /* FIXME: CHECK A/B */ - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; - break; - case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0007; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x00c; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x008; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x004; - break; - default: - return -EINVAL; - } - - /* Finally, write out the values */ - snd_soc_update_bits(codec, reg, 0xf, iface); - snd_soc_update_bits(codec, WM8776_MSTRCTRL, 0x180, master); - - return 0; -} - -static int mclk_ratios[] = { - 128, - 192, - 256, - 384, - 512, - 768, -}; - -static int wm8776_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8776_priv *wm8776 = codec->private_data; - int iface_reg, iface; - int ratio_shift, master; - int i; - - iface = 0; - - switch (dai->id) { - case WM8776_DAI_DAC: - iface_reg = WM8776_DACIFCTRL; - master = 0x80; - ratio_shift = 4; - break; - case WM8776_DAI_ADC: - iface_reg = WM8776_ADCIFCTRL; - master = 0x100; - ratio_shift = 0; - break; - default: - return -EINVAL; - } - - - /* Set word length */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x10; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x20; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x30; - break; - } - - /* Only need to set MCLK/LRCLK ratio if we're master */ - if (snd_soc_read(codec, WM8776_MSTRCTRL) & master) { - for (i = 0; i < ARRAY_SIZE(mclk_ratios); i++) { - if (wm8776->sysclk[dai->id] / params_rate(params) - == mclk_ratios[i]) - break; - } - - if (i == ARRAY_SIZE(mclk_ratios)) { - dev_err(codec->dev, - "Unable to configure MCLK ratio %d/%d\n", - wm8776->sysclk[dai->id], params_rate(params)); - return -EINVAL; - } - - dev_dbg(codec->dev, "MCLK is %dfs\n", mclk_ratios[i]); - - snd_soc_update_bits(codec, WM8776_MSTRCTRL, - 0x7 << ratio_shift, i << ratio_shift); - } else { - dev_dbg(codec->dev, "DAI in slave mode\n"); - } - - snd_soc_update_bits(codec, iface_reg, 0x30, iface); - - return 0; -} - -static int wm8776_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - - return snd_soc_write(codec, WM8776_DACMUTE, !!mute); -} - -static int wm8776_set_sysclk(struct snd_soc_dai *dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8776_priv *wm8776 = codec->private_data; - - BUG_ON(dai->id >= ARRAY_SIZE(wm8776->sysclk)); - - wm8776->sysclk[dai->id] = freq; - - return 0; -} - -static int wm8776_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) { - /* Disable the global powerdown; DAPM does the rest */ - snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); - } - - break; - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1); - break; - } - - codec->bias_level = level; - return 0; -} - -#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ - SNDRV_PCM_RATE_96000) - - -#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) - -static struct snd_soc_dai_ops wm8776_dac_ops = { - .digital_mute = wm8776_mute, - .hw_params = wm8776_hw_params, - .set_fmt = wm8776_set_fmt, - .set_sysclk = wm8776_set_sysclk, -}; - -static struct snd_soc_dai_ops wm8776_adc_ops = { - .hw_params = wm8776_hw_params, - .set_fmt = wm8776_set_fmt, - .set_sysclk = wm8776_set_sysclk, -}; - -struct snd_soc_dai wm8776_dai[] = { - { - .name = "WM8776 Playback", - .id = WM8776_DAI_DAC, - .playback = { - .stream_name = "Playback", - .channels_min = 2, - .channels_max = 2, - .rates = WM8776_RATES, - .formats = WM8776_FORMATS, - }, - .ops = &wm8776_dac_ops, - }, - { - .name = "WM8776 Capture", - .id = WM8776_DAI_ADC, - .capture = { - .stream_name = "Capture", - .channels_min = 2, - .channels_max = 2, - .rates = WM8776_RATES, - .formats = WM8776_FORMATS, - }, - .ops = &wm8776_adc_ops, - }, -}; -EXPORT_SYMBOL_GPL(wm8776_dai); - -#ifdef CONFIG_PM -static int wm8776_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8776_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8776_suspend NULL -#define wm8776_resume NULL -#endif - -static int wm8776_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8776_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8776_codec; - codec = wm8776_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8776_snd_controls, - ARRAY_SIZE(wm8776_snd_controls)); - snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, - ARRAY_SIZE(wm8776_dapm_widgets)); - snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8776_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8776 = { - .probe = wm8776_probe, - .remove = wm8776_remove, - .suspend = wm8776_suspend, - .resume = wm8776_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8776); - -static int wm8776_register(struct wm8776_priv *wm8776, - enum snd_soc_control_type control) -{ - int ret, i; - struct snd_soc_codec *codec = &wm8776->codec; - - if (wm8776_codec) { - dev_err(codec->dev, "Another WM8776 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->private_data = wm8776; - codec->name = "WM8776"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8776_set_bias_level; - codec->dai = wm8776_dai; - codec->num_dai = ARRAY_SIZE(wm8776_dai); - codec->reg_cache_size = WM8776_CACHEREGNUM; - codec->reg_cache = &wm8776->reg_cache; - - memcpy(codec->reg_cache, wm8776_reg, sizeof(wm8776_reg)); - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - for (i = 0; i < ARRAY_SIZE(wm8776_dai); i++) - wm8776_dai[i].dev = codec->dev; - - ret = wm8776_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset: %d\n", ret); - goto err; - } - - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - /* Latch the update bits; right channel only since we always - * update both. */ - snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); - snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); - - wm8776_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8776); - return ret; -} - -static void wm8776_unregister(struct wm8776_priv *wm8776) -{ - wm8776_set_bias_level(&wm8776->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dais(wm8776_dai, ARRAY_SIZE(wm8776_dai)); - snd_soc_unregister_codec(&wm8776->codec); - kfree(wm8776); - wm8776_codec = NULL; -} - -#if defined(CONFIG_SPI_MASTER) -static int wm8776_spi_write(struct spi_device *spi, const char *data, int len) -{ - struct spi_transfer t; - struct spi_message m; - u8 msg[2]; - - if (len <= 0) - return 0; - - msg[0] = data[0]; - msg[1] = data[1]; - - spi_message_init(&m); - memset(&t, 0, (sizeof t)); - - t.tx_buf = &msg[0]; - t.len = len; - - spi_message_add_tail(&t, &m); - spi_sync(spi, &m); - - return len; -} - -static int __devinit wm8776_spi_probe(struct spi_device *spi) -{ - struct snd_soc_codec *codec; - struct wm8776_priv *wm8776; - - wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); - if (wm8776 == NULL) - return -ENOMEM; - - codec = &wm8776->codec; - codec->control_data = spi; - codec->hw_write = (hw_write_t)wm8776_spi_write; - codec->dev = &spi->dev; - - dev_set_drvdata(&spi->dev, wm8776); - - return wm8776_register(wm8776, SND_SOC_SPI); -} - -static int __devexit wm8776_spi_remove(struct spi_device *spi) -{ - struct wm8776_priv *wm8776 = dev_get_drvdata(&spi->dev); - - wm8776_unregister(wm8776); - - return 0; -} - -#ifdef CONFIG_PM -static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return snd_soc_suspend_device(&spi->dev); -} - -static int wm8776_spi_resume(struct spi_device *spi) -{ - return snd_soc_resume_device(&spi->dev); -} -#else -#define wm8776_spi_suspend NULL -#define wm8776_spi_resume NULL -#endif - -static struct spi_driver wm8776_spi_driver = { - .driver = { - .name = "wm8776", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = wm8776_spi_probe, - .suspend = wm8776_spi_suspend, - .resume = wm8776_spi_resume, - .remove = __devexit_p(wm8776_spi_remove), -}; -#endif /* CONFIG_SPI_MASTER */ - -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8776_priv *wm8776; - struct snd_soc_codec *codec; - - wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL); - if (wm8776 == NULL) - return -ENOMEM; - - codec = &wm8776->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - - i2c_set_clientdata(i2c, wm8776); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - - return wm8776_register(wm8776, SND_SOC_I2C); -} - -static __devexit int wm8776_i2c_remove(struct i2c_client *client) -{ - struct wm8776_priv *wm8776 = i2c_get_clientdata(client); - wm8776_unregister(wm8776); - return 0; -} - -#ifdef CONFIG_PM -static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) -{ - return snd_soc_suspend_device(&i2c->dev); -} - -static int wm8776_i2c_resume(struct i2c_client *i2c) -{ - return snd_soc_resume_device(&i2c->dev); -} -#else -#define wm8776_i2c_suspend NULL -#define wm8776_i2c_resume NULL -#endif - -static const struct i2c_device_id wm8776_i2c_id[] = { - { "wm8776", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); - -static struct i2c_driver wm8776_i2c_driver = { - .driver = { - .name = "wm8776", - .owner = THIS_MODULE, - }, - .probe = wm8776_i2c_probe, - .remove = __devexit_p(wm8776_i2c_remove), - .suspend = wm8776_i2c_suspend, - .resume = wm8776_i2c_resume, - .id_table = wm8776_i2c_id, -}; -#endif - -static int __init wm8776_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&wm8776_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8776 I2C driver: %d\n", - ret); - } -#endif -#if defined(CONFIG_SPI_MASTER) - ret = spi_register_driver(&wm8776_spi_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8776 SPI driver: %d\n", - ret); - } -#endif - return 0; -} -module_init(wm8776_modinit); - -static void __exit wm8776_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&wm8776_i2c_driver); -#endif -#if defined(CONFIG_SPI_MASTER) - spi_unregister_driver(&wm8776_spi_driver); -#endif -} -module_exit(wm8776_exit); - -MODULE_DESCRIPTION("ASoC WM8776 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8776.h b/trunk/sound/soc/codecs/wm8776.h deleted file mode 100644 index 6606d25d2d83..000000000000 --- a/trunk/sound/soc/codecs/wm8776.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * wm8776.h -- WM8776 ASoC driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8776_H -#define _WM8776_H - -/* Registers */ - -#define WM8776_HPLVOL 0x00 -#define WM8776_HPRVOL 0x01 -#define WM8776_HPMASTER 0x02 -#define WM8776_DACLVOL 0x03 -#define WM8776_DACRVOL 0x04 -#define WM8776_DACMASTER 0x05 -#define WM8776_PHASESWAP 0x06 -#define WM8776_DACCTRL1 0x07 -#define WM8776_DACMUTE 0x08 -#define WM8776_DACCTRL2 0x09 -#define WM8776_DACIFCTRL 0x0a -#define WM8776_ADCIFCTRL 0x0b -#define WM8776_MSTRCTRL 0x0c -#define WM8776_PWRDOWN 0x0d -#define WM8776_ADCLVOL 0x0e -#define WM8776_ADCRVOL 0x0f -#define WM8776_ALCCTRL1 0x10 -#define WM8776_ALCCTRL2 0x11 -#define WM8776_ALCCTRL3 0x12 -#define WM8776_NOISEGATE 0x13 -#define WM8776_LIMITER 0x14 -#define WM8776_ADCMUX 0x15 -#define WM8776_OUTMUX 0x16 -#define WM8776_RESET 0x17 - -#define WM8776_CACHEREGNUM 0x17 - -#define WM8776_DAI_DAC 0 -#define WM8776_DAI_ADC 1 - -extern struct snd_soc_dai wm8776_dai[]; -extern struct snd_soc_codec_device soc_codec_dev_wm8776; - -#endif diff --git a/trunk/sound/soc/codecs/wm8900.c b/trunk/sound/soc/codecs/wm8900.c index 5e9c855c0036..3c78945244b8 100644 --- a/trunk/sound/soc/codecs/wm8900.c +++ b/trunk/sound/soc/codecs/wm8900.c @@ -116,7 +116,6 @@ #define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c #define WM8900_REG_DACCTRL_MUTE 0x004 -#define WM8900_REG_DACCTRL_DAC_SB_FILT 0x100 #define WM8900_REG_DACCTRL_AIF_LRCLKRATE 0x400 #define WM8900_REG_AUDIO3_ADCLRC_DIR 0x0800 @@ -183,20 +182,111 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = { /* Remaining registers all zero */ }; -static int wm8900_volatile_register(unsigned int reg) +/* + * read wm8900 register cache + */ +static inline unsigned int wm8900_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + BUG_ON(reg >= WM8900_MAXREG); + + if (reg == WM8900_REG_ID) + return 0; + + return cache[reg]; +} + +/* + * write wm8900 register cache + */ +static inline void wm8900_write_reg_cache(struct snd_soc_codec *codec, + u16 reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + + BUG_ON(reg >= WM8900_MAXREG); + + cache[reg] = value; +} + +/* + * write to the WM8900 register space + */ +static int wm8900_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[3]; + + if (value == wm8900_read_reg_cache(codec, reg)) + return 0; + + /* data is + * D15..D9 WM8900 register offset + * D8...D0 register data + */ + data[0] = reg; + data[1] = value >> 8; + data[2] = value & 0x00ff; + + wm8900_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 3) == 3) + return 0; + else + return -EIO; +} + +/* + * Read from the wm8900. + */ +static unsigned int wm8900_chip_read(struct snd_soc_codec *codec, u8 reg) +{ + struct i2c_msg xfer[2]; + u16 data; + int ret; + struct i2c_client *client = codec->control_data; + + BUG_ON(reg != WM8900_REG_ID && reg != WM8900_REG_POWER1); + + /* Write register */ + xfer[0].addr = client->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = ® + + /* Read data */ + xfer[1].addr = client->addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = 2; + xfer[1].buf = (u8 *)&data; + + ret = i2c_transfer(client->adapter, xfer, 2); + if (ret != 2) { + printk(KERN_CRIT "i2c_transfer returned %d\n", ret); + return 0; + } + + return (data >> 8) | ((data & 0xff) << 8); +} + +/* + * Read from the WM8900 register space. Most registers can't be read + * and are therefore supplied from cache. + */ +static unsigned int wm8900_read(struct snd_soc_codec *codec, unsigned int reg) { switch (reg) { case WM8900_REG_ID: - case WM8900_REG_POWER1: - return 1; + return wm8900_chip_read(codec, reg); default: - return 0; + return wm8900_read_reg_cache(codec, reg); } } static void wm8900_reset(struct snd_soc_codec *codec) { - snd_soc_write(codec, WM8900_REG_RESET, 0); + wm8900_write(codec, WM8900_REG_RESET, 0); memcpy(codec->reg_cache, wm8900_reg_defaults, sizeof(codec->reg_cache)); @@ -206,14 +296,14 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - u16 hpctl1 = snd_soc_read(codec, WM8900_REG_HPCTL1); + u16 hpctl1 = wm8900_read(codec, WM8900_REG_HPCTL1); switch (event) { case SND_SOC_DAPM_PRE_PMU: /* Clamp headphone outputs */ hpctl1 = WM8900_REG_HPCTL1_HP_CLAMP_IP | WM8900_REG_HPCTL1_HP_CLAMP_OP; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); break; case SND_SOC_DAPM_POST_PMU: @@ -222,41 +312,41 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w, hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT | WM8900_REG_HPCTL1_HP_SHORT2 | WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); msleep(400); /* Enable the output stage */ hpctl1 &= ~WM8900_REG_HPCTL1_HP_CLAMP_OP; hpctl1 |= WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); /* Remove the shorts */ hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT2; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); hpctl1 &= ~WM8900_REG_HPCTL1_HP_SHORT; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); break; case SND_SOC_DAPM_PRE_PMD: /* Short the output */ hpctl1 |= WM8900_REG_HPCTL1_HP_SHORT; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); /* Disable the output stage */ hpctl1 &= ~WM8900_REG_HPCTL1_HP_OPSTAGE_ENA; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); /* Clamp the outputs and power down input */ hpctl1 |= WM8900_REG_HPCTL1_HP_CLAMP_IP | WM8900_REG_HPCTL1_HP_CLAMP_OP; hpctl1 &= ~WM8900_REG_HPCTL1_HP_IPSTAGE_ENA; - snd_soc_write(codec, WM8900_REG_HPCTL1, hpctl1); + wm8900_write(codec, WM8900_REG_HPCTL1, hpctl1); break; case SND_SOC_DAPM_POST_PMD: /* Disable everything */ - snd_soc_write(codec, WM8900_REG_HPCTL1, 0); + wm8900_write(codec, WM8900_REG_HPCTL1, 0); break; default: @@ -349,6 +439,7 @@ SOC_SINGLE("DAC Soft Mute Switch", WM8900_REG_DACCTRL, 6, 1, 1), SOC_ENUM("DAC Mute Rate", dac_mute_rate), SOC_SINGLE("DAC Mono Switch", WM8900_REG_DACCTRL, 9, 1, 0), SOC_ENUM("DAC Deemphasis", dac_deemphasis), +SOC_SINGLE("DAC Sloping Stopband Filter Switch", WM8900_REG_DACCTRL, 8, 1, 0), SOC_SINGLE("DAC Sigma-Delta Modulator Clock Switch", WM8900_REG_DACCTRL, 12, 1, 0), @@ -632,7 +723,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, struct snd_soc_codec *codec = socdev->card->codec; u16 reg; - reg = snd_soc_read(codec, WM8900_REG_AUDIO1) & ~0x60; + reg = wm8900_read(codec, WM8900_REG_AUDIO1) & ~0x60; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: @@ -650,18 +741,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - snd_soc_write(codec, WM8900_REG_AUDIO1, reg); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - reg = snd_soc_read(codec, WM8900_REG_DACCTRL); - - if (params_rate(params) <= 24000) - reg |= WM8900_REG_DACCTRL_DAC_SB_FILT; - else - reg &= ~WM8900_REG_DACCTRL_DAC_SB_FILT; - - snd_soc_write(codec, WM8900_REG_DACCTRL, reg); - } + wm8900_write(codec, WM8900_REG_AUDIO1, reg); return 0; } @@ -754,18 +834,18 @@ static int wm8900_set_fll(struct snd_soc_codec *codec, return 0; /* The digital side should be disabled during any change. */ - reg = snd_soc_read(codec, WM8900_REG_POWER1); - snd_soc_write(codec, WM8900_REG_POWER1, + reg = wm8900_read(codec, WM8900_REG_POWER1); + wm8900_write(codec, WM8900_REG_POWER1, reg & (~WM8900_REG_POWER1_FLL_ENA)); /* Disable the FLL? */ if (!freq_in || !freq_out) { - reg = snd_soc_read(codec, WM8900_REG_CLOCKING1); - snd_soc_write(codec, WM8900_REG_CLOCKING1, + reg = wm8900_read(codec, WM8900_REG_CLOCKING1); + wm8900_write(codec, WM8900_REG_CLOCKING1, reg & (~WM8900_REG_CLOCKING1_MCLK_SRC)); - reg = snd_soc_read(codec, WM8900_REG_FLLCTL1); - snd_soc_write(codec, WM8900_REG_FLLCTL1, + reg = wm8900_read(codec, WM8900_REG_FLLCTL1); + wm8900_write(codec, WM8900_REG_FLLCTL1, reg & (~WM8900_REG_FLLCTL1_OSC_ENA)); wm8900->fll_in = freq_in; @@ -782,33 +862,33 @@ static int wm8900_set_fll(struct snd_soc_codec *codec, /* The osclilator *MUST* be enabled before we enable the * digital circuit. */ - snd_soc_write(codec, WM8900_REG_FLLCTL1, + wm8900_write(codec, WM8900_REG_FLLCTL1, fll_div.fll_ratio | WM8900_REG_FLLCTL1_OSC_ENA); - snd_soc_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5); - snd_soc_write(codec, WM8900_REG_FLLCTL5, + wm8900_write(codec, WM8900_REG_FLLCTL4, fll_div.n >> 5); + wm8900_write(codec, WM8900_REG_FLLCTL5, (fll_div.fllclk_div << 6) | (fll_div.n & 0x1f)); if (fll_div.k) { - snd_soc_write(codec, WM8900_REG_FLLCTL2, + wm8900_write(codec, WM8900_REG_FLLCTL2, (fll_div.k >> 8) | 0x100); - snd_soc_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff); + wm8900_write(codec, WM8900_REG_FLLCTL3, fll_div.k & 0xff); } else - snd_soc_write(codec, WM8900_REG_FLLCTL2, 0); + wm8900_write(codec, WM8900_REG_FLLCTL2, 0); if (fll_div.fll_slow_lock_ref) - snd_soc_write(codec, WM8900_REG_FLLCTL6, + wm8900_write(codec, WM8900_REG_FLLCTL6, WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF); else - snd_soc_write(codec, WM8900_REG_FLLCTL6, 0); + wm8900_write(codec, WM8900_REG_FLLCTL6, 0); - reg = snd_soc_read(codec, WM8900_REG_POWER1); - snd_soc_write(codec, WM8900_REG_POWER1, + reg = wm8900_read(codec, WM8900_REG_POWER1); + wm8900_write(codec, WM8900_REG_POWER1, reg | WM8900_REG_POWER1_FLL_ENA); reenable: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING1); - snd_soc_write(codec, WM8900_REG_CLOCKING1, + reg = wm8900_read(codec, WM8900_REG_CLOCKING1); + wm8900_write(codec, WM8900_REG_CLOCKING1, reg | WM8900_REG_CLOCKING1_MCLK_SRC); return 0; @@ -828,38 +908,38 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8900_BCLK_DIV: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING1); - snd_soc_write(codec, WM8900_REG_CLOCKING1, + reg = wm8900_read(codec, WM8900_REG_CLOCKING1); + wm8900_write(codec, WM8900_REG_CLOCKING1, div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK)); break; case WM8900_OPCLK_DIV: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING1); - snd_soc_write(codec, WM8900_REG_CLOCKING1, + reg = wm8900_read(codec, WM8900_REG_CLOCKING1); + wm8900_write(codec, WM8900_REG_CLOCKING1, div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK)); break; case WM8900_DAC_LRCLK: - reg = snd_soc_read(codec, WM8900_REG_AUDIO4); - snd_soc_write(codec, WM8900_REG_AUDIO4, + reg = wm8900_read(codec, WM8900_REG_AUDIO4); + wm8900_write(codec, WM8900_REG_AUDIO4, div | (reg & WM8900_LRC_MASK)); break; case WM8900_ADC_LRCLK: - reg = snd_soc_read(codec, WM8900_REG_AUDIO3); - snd_soc_write(codec, WM8900_REG_AUDIO3, + reg = wm8900_read(codec, WM8900_REG_AUDIO3); + wm8900_write(codec, WM8900_REG_AUDIO3, div | (reg & WM8900_LRC_MASK)); break; case WM8900_DAC_CLKDIV: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING2); - snd_soc_write(codec, WM8900_REG_CLOCKING2, + reg = wm8900_read(codec, WM8900_REG_CLOCKING2); + wm8900_write(codec, WM8900_REG_CLOCKING2, div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV)); break; case WM8900_ADC_CLKDIV: - reg = snd_soc_read(codec, WM8900_REG_CLOCKING2); - snd_soc_write(codec, WM8900_REG_CLOCKING2, + reg = wm8900_read(codec, WM8900_REG_CLOCKING2); + wm8900_write(codec, WM8900_REG_CLOCKING2, div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV)); break; case WM8900_LRCLK_MODE: - reg = snd_soc_read(codec, WM8900_REG_DACCTRL); - snd_soc_write(codec, WM8900_REG_DACCTRL, + reg = wm8900_read(codec, WM8900_REG_DACCTRL); + wm8900_write(codec, WM8900_REG_DACCTRL, div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE)); break; default: @@ -876,10 +956,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; unsigned int clocking1, aif1, aif3, aif4; - clocking1 = snd_soc_read(codec, WM8900_REG_CLOCKING1); - aif1 = snd_soc_read(codec, WM8900_REG_AUDIO1); - aif3 = snd_soc_read(codec, WM8900_REG_AUDIO3); - aif4 = snd_soc_read(codec, WM8900_REG_AUDIO4); + clocking1 = wm8900_read(codec, WM8900_REG_CLOCKING1); + aif1 = wm8900_read(codec, WM8900_REG_AUDIO1); + aif3 = wm8900_read(codec, WM8900_REG_AUDIO3); + aif4 = wm8900_read(codec, WM8900_REG_AUDIO4); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -975,10 +1055,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8900_REG_CLOCKING1, clocking1); - snd_soc_write(codec, WM8900_REG_AUDIO1, aif1); - snd_soc_write(codec, WM8900_REG_AUDIO3, aif3); - snd_soc_write(codec, WM8900_REG_AUDIO4, aif4); + wm8900_write(codec, WM8900_REG_CLOCKING1, clocking1); + wm8900_write(codec, WM8900_REG_AUDIO1, aif1); + wm8900_write(codec, WM8900_REG_AUDIO3, aif3); + wm8900_write(codec, WM8900_REG_AUDIO4, aif4); return 0; } @@ -988,14 +1068,14 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute) struct snd_soc_codec *codec = codec_dai->codec; u16 reg; - reg = snd_soc_read(codec, WM8900_REG_DACCTRL); + reg = wm8900_read(codec, WM8900_REG_DACCTRL); if (mute) reg |= WM8900_REG_DACCTRL_MUTE; else reg &= ~WM8900_REG_DACCTRL_MUTE; - snd_soc_write(codec, WM8900_REG_DACCTRL, reg); + wm8900_write(codec, WM8900_REG_DACCTRL, reg); return 0; } @@ -1044,11 +1124,11 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: /* Enable thermal shutdown */ - reg = snd_soc_read(codec, WM8900_REG_GPIO); - snd_soc_write(codec, WM8900_REG_GPIO, + reg = wm8900_read(codec, WM8900_REG_GPIO); + wm8900_write(codec, WM8900_REG_GPIO, reg | WM8900_REG_GPIO_TEMP_ENA); - reg = snd_soc_read(codec, WM8900_REG_ADDCTL); - snd_soc_write(codec, WM8900_REG_ADDCTL, + reg = wm8900_read(codec, WM8900_REG_ADDCTL); + wm8900_write(codec, WM8900_REG_ADDCTL, reg | WM8900_REG_ADDCTL_TEMP_SD); break; @@ -1059,69 +1139,69 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec, /* Charge capacitors if initial power up */ if (codec->bias_level == SND_SOC_BIAS_OFF) { /* STARTUP_BIAS_ENA on */ - snd_soc_write(codec, WM8900_REG_POWER1, + wm8900_write(codec, WM8900_REG_POWER1, WM8900_REG_POWER1_STARTUP_BIAS_ENA); /* Startup bias mode */ - snd_soc_write(codec, WM8900_REG_ADDCTL, + wm8900_write(codec, WM8900_REG_ADDCTL, WM8900_REG_ADDCTL_BIAS_SRC | WM8900_REG_ADDCTL_VMID_SOFTST); /* VMID 2x50k */ - snd_soc_write(codec, WM8900_REG_POWER1, + wm8900_write(codec, WM8900_REG_POWER1, WM8900_REG_POWER1_STARTUP_BIAS_ENA | 0x1); /* Allow capacitors to charge */ schedule_timeout_interruptible(msecs_to_jiffies(400)); /* Enable bias */ - snd_soc_write(codec, WM8900_REG_POWER1, + wm8900_write(codec, WM8900_REG_POWER1, WM8900_REG_POWER1_STARTUP_BIAS_ENA | WM8900_REG_POWER1_BIAS_ENA | 0x1); - snd_soc_write(codec, WM8900_REG_ADDCTL, 0); + wm8900_write(codec, WM8900_REG_ADDCTL, 0); - snd_soc_write(codec, WM8900_REG_POWER1, + wm8900_write(codec, WM8900_REG_POWER1, WM8900_REG_POWER1_BIAS_ENA | 0x1); } - reg = snd_soc_read(codec, WM8900_REG_POWER1); - snd_soc_write(codec, WM8900_REG_POWER1, + reg = wm8900_read(codec, WM8900_REG_POWER1); + wm8900_write(codec, WM8900_REG_POWER1, (reg & WM8900_REG_POWER1_FLL_ENA) | WM8900_REG_POWER1_BIAS_ENA | 0x1); - snd_soc_write(codec, WM8900_REG_POWER2, + wm8900_write(codec, WM8900_REG_POWER2, WM8900_REG_POWER2_SYSCLK_ENA); - snd_soc_write(codec, WM8900_REG_POWER3, 0); + wm8900_write(codec, WM8900_REG_POWER3, 0); break; case SND_SOC_BIAS_OFF: /* Startup bias enable */ - reg = snd_soc_read(codec, WM8900_REG_POWER1); - snd_soc_write(codec, WM8900_REG_POWER1, + reg = wm8900_read(codec, WM8900_REG_POWER1); + wm8900_write(codec, WM8900_REG_POWER1, reg & WM8900_REG_POWER1_STARTUP_BIAS_ENA); - snd_soc_write(codec, WM8900_REG_ADDCTL, + wm8900_write(codec, WM8900_REG_ADDCTL, WM8900_REG_ADDCTL_BIAS_SRC | WM8900_REG_ADDCTL_VMID_SOFTST); /* Discharge caps */ - snd_soc_write(codec, WM8900_REG_POWER1, + wm8900_write(codec, WM8900_REG_POWER1, WM8900_REG_POWER1_STARTUP_BIAS_ENA); schedule_timeout_interruptible(msecs_to_jiffies(500)); /* Remove clamp */ - snd_soc_write(codec, WM8900_REG_HPCTL1, 0); + wm8900_write(codec, WM8900_REG_HPCTL1, 0); /* Power down */ - snd_soc_write(codec, WM8900_REG_ADDCTL, 0); - snd_soc_write(codec, WM8900_REG_POWER1, 0); - snd_soc_write(codec, WM8900_REG_POWER2, 0); - snd_soc_write(codec, WM8900_REG_POWER3, 0); + wm8900_write(codec, WM8900_REG_ADDCTL, 0); + wm8900_write(codec, WM8900_REG_POWER1, 0); + wm8900_write(codec, WM8900_REG_POWER2, 0); + wm8900_write(codec, WM8900_REG_POWER3, 0); /* Need to let things settle before stopping the clock * to ensure that restart works, see "Stopping the * master clock" in the datasheet. */ schedule_timeout_interruptible(msecs_to_jiffies(1)); - snd_soc_write(codec, WM8900_REG_POWER2, + wm8900_write(codec, WM8900_REG_POWER2, WM8900_REG_POWER2_SYSCLK_ENA); break; } @@ -1184,7 +1264,7 @@ static int wm8900_resume(struct platform_device *pdev) if (cache) { for (i = 0; i < WM8900_MAXREG; i++) - snd_soc_write(codec, i, cache[i]); + wm8900_write(codec, i, cache[i]); kfree(cache); } else dev_err(&pdev->dev, "Unable to allocate register cache\n"); @@ -1217,20 +1297,16 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, codec->name = "WM8900"; codec->owner = THIS_MODULE; + codec->read = wm8900_read; + codec->write = wm8900_write; codec->dai = &wm8900_dai; codec->num_dai = 1; + codec->hw_write = (hw_write_t)i2c_master_send; codec->control_data = i2c; codec->set_bias_level = wm8900_set_bias_level; - codec->volatile_register = wm8900_volatile_register; codec->dev = &i2c->dev; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - reg = snd_soc_read(codec, WM8900_REG_ID); + reg = wm8900_read(codec, WM8900_REG_ID); if (reg != 0x8900) { dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); ret = -ENODEV; @@ -1238,7 +1314,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, } /* Read back from the chip */ - reg = snd_soc_read(codec, WM8900_REG_POWER1); + reg = wm8900_chip_read(codec, WM8900_REG_POWER1); reg = (reg >> 12) & 0xf; dev_info(&i2c->dev, "WM8900 revision %d\n", reg); @@ -1248,29 +1324,29 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the volume update bits */ - snd_soc_write(codec, WM8900_REG_LINVOL, - snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100); - snd_soc_write(codec, WM8900_REG_RINVOL, - snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100); - snd_soc_write(codec, WM8900_REG_LOUT1CTL, - snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100); - snd_soc_write(codec, WM8900_REG_ROUT1CTL, - snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100); - snd_soc_write(codec, WM8900_REG_LOUT2CTL, - snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100); - snd_soc_write(codec, WM8900_REG_ROUT2CTL, - snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100); - snd_soc_write(codec, WM8900_REG_LDAC_DV, - snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100); - snd_soc_write(codec, WM8900_REG_RDAC_DV, - snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100); - snd_soc_write(codec, WM8900_REG_LADC_DV, - snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100); - snd_soc_write(codec, WM8900_REG_RADC_DV, - snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100); + wm8900_write(codec, WM8900_REG_LINVOL, + wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); + wm8900_write(codec, WM8900_REG_RINVOL, + wm8900_read(codec, WM8900_REG_RINVOL) | 0x100); + wm8900_write(codec, WM8900_REG_LOUT1CTL, + wm8900_read(codec, WM8900_REG_LOUT1CTL) | 0x100); + wm8900_write(codec, WM8900_REG_ROUT1CTL, + wm8900_read(codec, WM8900_REG_ROUT1CTL) | 0x100); + wm8900_write(codec, WM8900_REG_LOUT2CTL, + wm8900_read(codec, WM8900_REG_LOUT2CTL) | 0x100); + wm8900_write(codec, WM8900_REG_ROUT2CTL, + wm8900_read(codec, WM8900_REG_ROUT2CTL) | 0x100); + wm8900_write(codec, WM8900_REG_LDAC_DV, + wm8900_read(codec, WM8900_REG_LDAC_DV) | 0x100); + wm8900_write(codec, WM8900_REG_RDAC_DV, + wm8900_read(codec, WM8900_REG_RDAC_DV) | 0x100); + wm8900_write(codec, WM8900_REG_LADC_DV, + wm8900_read(codec, WM8900_REG_LADC_DV) | 0x100); + wm8900_write(codec, WM8900_REG_RADC_DV, + wm8900_read(codec, WM8900_REG_RADC_DV) | 0x100); /* Set the DAC and mixer output bias */ - snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81); + wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); wm8900_dai.dev = &i2c->dev; @@ -1312,21 +1388,6 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8900_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8900_i2c_suspend NULL -#define wm8900_i2c_resume NULL -#endif - static const struct i2c_device_id wm8900_i2c_id[] = { { "wm8900", 0 }, { } @@ -1340,8 +1401,6 @@ static struct i2c_driver wm8900_i2c_driver = { }, .probe = wm8900_i2c_probe, .remove = __devexit_p(wm8900_i2c_remove), - .suspend = wm8900_i2c_suspend, - .resume = wm8900_i2c_resume, .id_table = wm8900_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm8903.c b/trunk/sound/soc/codecs/wm8903.c index fe1307b500cf..e8d2e3e14c45 100644 --- a/trunk/sound/soc/codecs/wm8903.c +++ b/trunk/sound/soc/codecs/wm8903.c @@ -225,20 +225,96 @@ struct wm8903_priv { struct snd_pcm_substream *slave_substream; }; -static int wm8903_volatile_register(unsigned int reg) + +static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults)); + + return cache[reg]; +} + +static unsigned int wm8903_hw_read(struct snd_soc_codec *codec, u8 reg) +{ + struct i2c_msg xfer[2]; + u16 data; + int ret; + struct i2c_client *client = codec->control_data; + + /* Write register */ + xfer[0].addr = client->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = ® + + /* Read data */ + xfer[1].addr = client->addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = 2; + xfer[1].buf = (u8 *)&data; + + ret = i2c_transfer(client->adapter, xfer, 2); + if (ret != 2) { + pr_err("i2c_transfer returned %d\n", ret); + return 0; + } + + return (data >> 8) | ((data & 0xff) << 8); +} + +static unsigned int wm8903_read(struct snd_soc_codec *codec, + unsigned int reg) { switch (reg) { case WM8903_SW_RESET_AND_ID: case WM8903_REVISION_NUMBER: case WM8903_INTERRUPT_STATUS_1: case WM8903_WRITE_SEQUENCER_4: - return 1; + return wm8903_hw_read(codec, reg); default: - return 0; + return wm8903_read_reg_cache(codec, reg); } } +static void wm8903_write_reg_cache(struct snd_soc_codec *codec, + u16 reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + + BUG_ON(reg >= ARRAY_SIZE(wm8903_reg_defaults)); + + switch (reg) { + case WM8903_SW_RESET_AND_ID: + case WM8903_REVISION_NUMBER: + break; + + default: + cache[reg] = value; + break; + } +} + +static int wm8903_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[3]; + + wm8903_write_reg_cache(codec, reg, value); + + /* Data format is 1 byte of address followed by 2 bytes of data */ + data[0] = reg; + data[1] = (value >> 8) & 0xff; + data[2] = value & 0xff; + + if (codec->hw_write(codec->control_data, data, 3) == 2) + return 0; + else + return -EIO; +} + static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) { u16 reg[5]; @@ -247,13 +323,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) BUG_ON(start > 48); /* Enable the sequencer */ - reg[0] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_0); + reg[0] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_0); reg[0] |= WM8903_WSEQ_ENA; - snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); + wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0]); dev_dbg(&i2c->dev, "Starting sequence at %d\n", start); - snd_soc_write(codec, WM8903_WRITE_SEQUENCER_3, + wm8903_write(codec, WM8903_WRITE_SEQUENCER_3, start | WM8903_WSEQ_START); /* Wait for it to complete. If we have the interrupt wired up then @@ -263,13 +339,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start) do { msleep(10); - reg[4] = snd_soc_read(codec, WM8903_WRITE_SEQUENCER_4); + reg[4] = wm8903_read(codec, WM8903_WRITE_SEQUENCER_4); } while (reg[4] & WM8903_WSEQ_BUSY); dev_dbg(&i2c->dev, "Sequence complete\n"); /* Disable the sequencer again */ - snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, + wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, reg[0] & ~WM8903_WSEQ_ENA); return 0; @@ -281,12 +357,12 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache) /* There really ought to be something better we can do here :/ */ for (i = 0; i < ARRAY_SIZE(wm8903_reg_defaults); i++) - cache[i] = codec->hw_read(codec, i); + cache[i] = wm8903_hw_read(codec, i); } static void wm8903_reset(struct snd_soc_codec *codec) { - snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0); + wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0); memcpy(codec->reg_cache, wm8903_reg_defaults, sizeof(wm8903_reg_defaults)); } @@ -347,52 +423,52 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w, } if (event & SND_SOC_DAPM_PRE_PMU) { - val = snd_soc_read(codec, reg); + val = wm8903_read(codec, reg); /* Short the output */ val &= ~(WM8903_OUTPUT_SHORT << shift); - snd_soc_write(codec, reg, val); + wm8903_write(codec, reg, val); } if (event & SND_SOC_DAPM_POST_PMU) { - val = snd_soc_read(codec, reg); + val = wm8903_read(codec, reg); val |= (WM8903_OUTPUT_IN << shift); - snd_soc_write(codec, reg, val); + wm8903_write(codec, reg, val); val |= (WM8903_OUTPUT_INT << shift); - snd_soc_write(codec, reg, val); + wm8903_write(codec, reg, val); /* Turn on the output ENA_OUTP */ val |= (WM8903_OUTPUT_OUT << shift); - snd_soc_write(codec, reg, val); + wm8903_write(codec, reg, val); /* Enable the DC servo */ - dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0); + dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0); dcs_reg |= dcs_bit; - snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg); + wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg); /* Remove the short */ val |= (WM8903_OUTPUT_SHORT << shift); - snd_soc_write(codec, reg, val); + wm8903_write(codec, reg, val); } if (event & SND_SOC_DAPM_PRE_PMD) { - val = snd_soc_read(codec, reg); + val = wm8903_read(codec, reg); /* Short the output */ val &= ~(WM8903_OUTPUT_SHORT << shift); - snd_soc_write(codec, reg, val); + wm8903_write(codec, reg, val); /* Disable the DC servo */ - dcs_reg = snd_soc_read(codec, WM8903_DC_SERVO_0); + dcs_reg = wm8903_read(codec, WM8903_DC_SERVO_0); dcs_reg &= ~dcs_bit; - snd_soc_write(codec, WM8903_DC_SERVO_0, dcs_reg); + wm8903_write(codec, WM8903_DC_SERVO_0, dcs_reg); /* Then disable the intermediate and output stages */ val &= ~((WM8903_OUTPUT_OUT | WM8903_OUTPUT_INT | WM8903_OUTPUT_IN) << shift); - snd_soc_write(codec, reg, val); + wm8903_write(codec, reg, val); } return 0; @@ -416,13 +492,13 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, u16 reg; int ret; - reg = snd_soc_read(codec, WM8903_CLASS_W_0); + reg = wm8903_read(codec, WM8903_CLASS_W_0); /* Turn it off if we're about to enable bypass */ if (ucontrol->value.integer.value[0]) { if (wm8903->class_w_users == 0) { dev_dbg(&i2c->dev, "Disabling Class W\n"); - snd_soc_write(codec, WM8903_CLASS_W_0, reg & + wm8903_write(codec, WM8903_CLASS_W_0, reg & ~(WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V)); } wm8903->class_w_users++; @@ -435,7 +511,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, if (!ucontrol->value.integer.value[0]) { if (wm8903->class_w_users == 1) { dev_dbg(&i2c->dev, "Enabling Class W\n"); - snd_soc_write(codec, WM8903_CLASS_W_0, reg | + wm8903_write(codec, WM8903_CLASS_W_0, reg | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); } wm8903->class_w_users--; @@ -639,6 +715,8 @@ SOC_ENUM("DAC Soft Mute Rate", soft_mute), SOC_ENUM("DAC Mute Mode", mute_mode), SOC_SINGLE("DAC Mono Switch", WM8903_DAC_DIGITAL_1, 12, 1, 0), SOC_ENUM("DAC De-emphasis", dac_deemphasis), +SOC_SINGLE("DAC Sloping Stopband Filter Switch", + WM8903_DAC_DIGITAL_1, 11, 1, 0), SOC_ENUM("DAC Companding Mode", dac_companding), SOC_SINGLE("DAC Companding Switch", WM8903_AUDIO_INTERFACE_0, 1, 1, 0), @@ -933,55 +1011,55 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, switch (level) { case SND_SOC_BIAS_ON: case SND_SOC_BIAS_PREPARE: - reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0); + reg = wm8903_read(codec, WM8903_VMID_CONTROL_0); reg &= ~(WM8903_VMID_RES_MASK); reg |= WM8903_VMID_RES_50K; - snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg); + wm8903_write(codec, WM8903_VMID_CONTROL_0, reg); break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { - snd_soc_write(codec, WM8903_CLOCK_RATES_2, + wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA); /* Change DC servo dither level in startup sequence */ - snd_soc_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11); - snd_soc_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257); - snd_soc_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2); + wm8903_write(codec, WM8903_WRITE_SEQUENCER_0, 0x11); + wm8903_write(codec, WM8903_WRITE_SEQUENCER_1, 0x1257); + wm8903_write(codec, WM8903_WRITE_SEQUENCER_2, 0x2); wm8903_run_sequence(codec, 0); wm8903_sync_reg_cache(codec, codec->reg_cache); /* Enable low impedence charge pump output */ - reg = snd_soc_read(codec, + reg = wm8903_read(codec, WM8903_CONTROL_INTERFACE_TEST_1); - snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, + wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, reg | WM8903_TEST_KEY); - reg2 = snd_soc_read(codec, WM8903_CHARGE_PUMP_TEST_1); - snd_soc_write(codec, WM8903_CHARGE_PUMP_TEST_1, + reg2 = wm8903_read(codec, WM8903_CHARGE_PUMP_TEST_1); + wm8903_write(codec, WM8903_CHARGE_PUMP_TEST_1, reg2 | WM8903_CP_SW_KELVIN_MODE_MASK); - snd_soc_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, + wm8903_write(codec, WM8903_CONTROL_INTERFACE_TEST_1, reg); /* By default no bypass paths are enabled so * enable Class W support. */ dev_dbg(&i2c->dev, "Enabling Class W\n"); - snd_soc_write(codec, WM8903_CLASS_W_0, reg | + wm8903_write(codec, WM8903_CLASS_W_0, reg | WM8903_CP_DYN_FREQ | WM8903_CP_DYN_V); } - reg = snd_soc_read(codec, WM8903_VMID_CONTROL_0); + reg = wm8903_read(codec, WM8903_VMID_CONTROL_0); reg &= ~(WM8903_VMID_RES_MASK); reg |= WM8903_VMID_RES_250K; - snd_soc_write(codec, WM8903_VMID_CONTROL_0, reg); + wm8903_write(codec, WM8903_VMID_CONTROL_0, reg); break; case SND_SOC_BIAS_OFF: wm8903_run_sequence(codec, 32); - reg = snd_soc_read(codec, WM8903_CLOCK_RATES_2); + reg = wm8903_read(codec, WM8903_CLOCK_RATES_2); reg &= ~WM8903_CLK_SYS_ENA; - snd_soc_write(codec, WM8903_CLOCK_RATES_2, reg); + wm8903_write(codec, WM8903_CLOCK_RATES_2, reg); break; } @@ -1005,7 +1083,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1); + u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1); aif1 &= ~(WM8903_LRCLK_DIR | WM8903_BCLK_DIR | WM8903_AIF_FMT_MASK | WM8903_AIF_LRCLK_INV | WM8903_AIF_BCLK_INV); @@ -1083,7 +1161,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); + wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); return 0; } @@ -1093,14 +1171,14 @@ static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute) struct snd_soc_codec *codec = codec_dai->codec; u16 reg; - reg = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); + reg = wm8903_read(codec, WM8903_DAC_DIGITAL_1); if (mute) reg |= WM8903_DAC_MUTE; else reg &= ~WM8903_DAC_MUTE; - snd_soc_write(codec, WM8903_DAC_DIGITAL_1, reg); + wm8903_write(codec, WM8903_DAC_DIGITAL_1, reg); return 0; } @@ -1290,24 +1368,17 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, int cur_val; int clk_sys; - u16 aif1 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_1); - u16 aif2 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_2); - u16 aif3 = snd_soc_read(codec, WM8903_AUDIO_INTERFACE_3); - u16 clock0 = snd_soc_read(codec, WM8903_CLOCK_RATES_0); - u16 clock1 = snd_soc_read(codec, WM8903_CLOCK_RATES_1); - u16 dac_digital1 = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); + u16 aif1 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_1); + u16 aif2 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_2); + u16 aif3 = wm8903_read(codec, WM8903_AUDIO_INTERFACE_3); + u16 clock0 = wm8903_read(codec, WM8903_CLOCK_RATES_0); + u16 clock1 = wm8903_read(codec, WM8903_CLOCK_RATES_1); if (substream == wm8903->slave_substream) { dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); return 0; } - /* Enable sloping stopband filter for low sample rates */ - if (fs <= 24000) - dac_digital1 |= WM8903_DAC_SB_FILT; - else - dac_digital1 &= ~WM8903_DAC_SB_FILT; - /* Configure sample rate logic for DSP - choose nearest rate */ dsp_config = 0; best_val = abs(sample_rates[dsp_config].rate - fs); @@ -1427,12 +1498,11 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, aif2 |= bclk_divs[bclk_div].div; aif3 |= bclk / fs; - snd_soc_write(codec, WM8903_CLOCK_RATES_0, clock0); - snd_soc_write(codec, WM8903_CLOCK_RATES_1, clock1); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); - snd_soc_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); - snd_soc_write(codec, WM8903_DAC_DIGITAL_1, dac_digital1); + wm8903_write(codec, WM8903_CLOCK_RATES_0, clock0); + wm8903_write(codec, WM8903_CLOCK_RATES_1, clock1); + wm8903_write(codec, WM8903_AUDIO_INTERFACE_1, aif1); + wm8903_write(codec, WM8903_AUDIO_INTERFACE_2, aif2); + wm8903_write(codec, WM8903_AUDIO_INTERFACE_3, aif3); return 0; } @@ -1517,7 +1587,7 @@ static int wm8903_resume(struct platform_device *pdev) if (tmp_cache) { for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++) if (tmp_cache[i] != reg_cache[i]) - snd_soc_write(codec, i, tmp_cache[i]); + wm8903_write(codec, i, tmp_cache[i]); } else { dev_err(&i2c->dev, "Failed to allocate temporary cache\n"); } @@ -1548,6 +1618,9 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, codec->dev = &i2c->dev; codec->name = "WM8903"; codec->owner = THIS_MODULE; + codec->read = wm8903_read; + codec->write = wm8903_write; + codec->hw_write = (hw_write_t)i2c_master_send; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8903_set_bias_level; codec->dai = &wm8903_dai; @@ -1555,25 +1628,18 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); codec->reg_cache = &wm8903->reg_cache[0]; codec->private_data = wm8903; - codec->volatile_register = wm8903_volatile_register; i2c_set_clientdata(i2c, codec); codec->control_data = i2c; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret != 0) { - dev_err(&i2c->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID); + val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { dev_err(&i2c->dev, "Device with ID register %x is not a WM8903\n", val); return -ENODEV; } - val = snd_soc_read(codec, WM8903_REVISION_NUMBER); + val = wm8903_read(codec, WM8903_REVISION_NUMBER); dev_info(&i2c->dev, "WM8903 revision %d\n", val & WM8903_CHIP_REV_MASK); @@ -1583,35 +1649,35 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c, wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch volume update bits */ - val = snd_soc_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); + val = wm8903_read(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT); val |= WM8903_ADCVU; - snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); - snd_soc_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); + wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_LEFT, val); + wm8903_write(codec, WM8903_ADC_DIGITAL_VOLUME_RIGHT, val); - val = snd_soc_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); + val = wm8903_read(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT); val |= WM8903_DACVU; - snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); - snd_soc_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); + wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_LEFT, val); + wm8903_write(codec, WM8903_DAC_DIGITAL_VOLUME_RIGHT, val); - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT1_LEFT); + val = wm8903_read(codec, WM8903_ANALOGUE_OUT1_LEFT); val |= WM8903_HPOUTVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); + wm8903_write(codec, WM8903_ANALOGUE_OUT1_LEFT, val); + wm8903_write(codec, WM8903_ANALOGUE_OUT1_RIGHT, val); - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT2_LEFT); + val = wm8903_read(codec, WM8903_ANALOGUE_OUT2_LEFT); val |= WM8903_LINEOUTVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); + wm8903_write(codec, WM8903_ANALOGUE_OUT2_LEFT, val); + wm8903_write(codec, WM8903_ANALOGUE_OUT2_RIGHT, val); - val = snd_soc_read(codec, WM8903_ANALOGUE_OUT3_LEFT); + val = wm8903_read(codec, WM8903_ANALOGUE_OUT3_LEFT); val |= WM8903_SPKVU; - snd_soc_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); - snd_soc_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); + wm8903_write(codec, WM8903_ANALOGUE_OUT3_LEFT, val); + wm8903_write(codec, WM8903_ANALOGUE_OUT3_RIGHT, val); /* Enable DAC soft mute by default */ - val = snd_soc_read(codec, WM8903_DAC_DIGITAL_1); + val = wm8903_read(codec, WM8903_DAC_DIGITAL_1); val |= WM8903_DAC_MUTEMODE; - snd_soc_write(codec, WM8903_DAC_DIGITAL_1, val); + wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); wm8903_dai.dev = &i2c->dev; wm8903_codec = codec; @@ -1655,21 +1721,6 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8903_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8903_i2c_suspend NULL -#define wm8903_i2c_resume NULL -#endif - /* i2c codec control layer */ static const struct i2c_device_id wm8903_i2c_id[] = { { "wm8903", 0 }, @@ -1684,8 +1735,6 @@ static struct i2c_driver wm8903_i2c_driver = { }, .probe = wm8903_i2c_probe, .remove = __devexit_p(wm8903_i2c_remove), - .suspend = wm8903_i2c_suspend, - .resume = wm8903_i2c_resume, .id_table = wm8903_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm8940.c b/trunk/sound/soc/codecs/wm8940.c index da97aae475a2..b8e17d6bc1f7 100644 --- a/trunk/sound/soc/codecs/wm8940.c +++ b/trunk/sound/soc/codecs/wm8940.c @@ -106,6 +106,50 @@ static u16 wm8940_reg_defaults[] = { 0x0000, /* Mono Mixer Control */ }; +static inline unsigned int wm8940_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + + if (reg >= ARRAY_SIZE(wm8940_reg_defaults)) + return -1; + + return cache[reg]; +} + +static inline int wm8940_write_reg_cache(struct snd_soc_codec *codec, + u16 reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + + if (reg >= ARRAY_SIZE(wm8940_reg_defaults)) + return -1; + + cache[reg] = value; + + return 0; +} + +static int wm8940_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + int ret; + u8 data[3] = { reg, + (value & 0xff00) >> 8, + (value & 0x00ff) + }; + + wm8940_write_reg_cache(codec, reg, value); + + ret = codec->hw_write(codec->control_data, data, 3); + + if (ret < 0) + return ret; + else if (ret != 3) + return -EIO; + return 0; +} + static const char *wm8940_companding[] = { "Off", "NC", "u-law", "A-law" }; static const struct soc_enum wm8940_adc_companding_enum = SOC_ENUM_SINGLE(WM8940_COMPANDINGCTL, 1, 4, wm8940_companding); @@ -304,14 +348,14 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec) return ret; } -#define wm8940_reset(c) snd_soc_write(c, WM8940_SOFTRESET, 0); +#define wm8940_reset(c) wm8940_write(c, WM8940_SOFTRESET, 0); static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFE67; - u16 clk = snd_soc_read(codec, WM8940_CLOCK) & 0x1fe; + u16 iface = wm8940_read_reg_cache(codec, WM8940_IFACE) & 0xFE67; + u16 clk = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0x1fe; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: @@ -322,7 +366,7 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, default: return -EINVAL; } - snd_soc_write(codec, WM8940_CLOCK, clk); + wm8940_write(codec, WM8940_CLOCK, clk); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: @@ -355,7 +399,7 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai, break; } - snd_soc_write(codec, WM8940_IFACE, iface); + wm8940_write(codec, WM8940_IFACE, iface); return 0; } @@ -367,9 +411,9 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 iface = snd_soc_read(codec, WM8940_IFACE) & 0xFD9F; - u16 addcntrl = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFF1; - u16 companding = snd_soc_read(codec, + u16 iface = wm8940_read_reg_cache(codec, WM8940_IFACE) & 0xFD9F; + u16 addcntrl = wm8940_read_reg_cache(codec, WM8940_ADDCNTRL) & 0xFFF1; + u16 companding = wm8940_read_reg_cache(codec, WM8940_COMPANDINGCTL) & 0xFFDF; int ret; @@ -398,7 +442,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, case SNDRV_PCM_RATE_48000: break; } - ret = snd_soc_write(codec, WM8940_ADDCNTRL, addcntrl); + ret = wm8940_write(codec, WM8940_ADDCNTRL, addcntrl); if (ret) goto error_ret; @@ -418,10 +462,10 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, iface |= (3 << 5); break; } - ret = snd_soc_write(codec, WM8940_COMPANDINGCTL, companding); + ret = wm8940_write(codec, WM8940_COMPANDINGCTL, companding); if (ret) goto error_ret; - ret = snd_soc_write(codec, WM8940_IFACE, iface); + ret = wm8940_write(codec, WM8940_IFACE, iface); error_ret: return ret; @@ -430,19 +474,19 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream, static int wm8940_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8940_DAC) & 0xffbf; + u16 mute_reg = wm8940_read_reg_cache(codec, WM8940_DAC) & 0xffbf; if (mute) mute_reg |= 0x40; - return snd_soc_write(codec, WM8940_DAC, mute_reg); + return wm8940_write(codec, WM8940_DAC, mute_reg); } static int wm8940_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { u16 val; - u16 pwr_reg = snd_soc_read(codec, WM8940_POWER1) & 0x1F0; + u16 pwr_reg = wm8940_read_reg_cache(codec, WM8940_POWER1) & 0x1F0; int ret = 0; switch (level) { @@ -450,26 +494,26 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec, /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* Enable thermal shutdown */ - val = snd_soc_read(codec, WM8940_OUTPUTCTL); - ret = snd_soc_write(codec, WM8940_OUTPUTCTL, val | 0x2); + val = wm8940_read_reg_cache(codec, WM8940_OUTPUTCTL); + ret = wm8940_write(codec, WM8940_OUTPUTCTL, val | 0x2); if (ret) break; /* set vmid to 75k */ - ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); + ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x1); break; case SND_SOC_BIAS_PREPARE: /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); - ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); + ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x1); break; case SND_SOC_BIAS_STANDBY: /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* set vmid to 300k for standby */ - ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x2); + ret = wm8940_write(codec, WM8940_POWER1, pwr_reg | 0x2); break; case SND_SOC_BIAS_OFF: - ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg); + ret = wm8940_write(codec, WM8940_POWER1, pwr_reg); break; } @@ -543,36 +587,36 @@ static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, u16 reg; /* Turn off PLL */ - reg = snd_soc_read(codec, WM8940_POWER1); - snd_soc_write(codec, WM8940_POWER1, reg & 0x1df); + reg = wm8940_read_reg_cache(codec, WM8940_POWER1); + wm8940_write(codec, WM8940_POWER1, reg & 0x1df); if (freq_in == 0 || freq_out == 0) { /* Clock CODEC directly from MCLK */ - reg = snd_soc_read(codec, WM8940_CLOCK); - snd_soc_write(codec, WM8940_CLOCK, reg & 0x0ff); + reg = wm8940_read_reg_cache(codec, WM8940_CLOCK); + wm8940_write(codec, WM8940_CLOCK, reg & 0x0ff); /* Pll power down */ - snd_soc_write(codec, WM8940_PLLN, (1 << 7)); + wm8940_write(codec, WM8940_PLLN, (1 << 7)); return 0; } /* Pll is followed by a frequency divide by 4 */ pll_factors(freq_out*4, freq_in); if (pll_div.k) - snd_soc_write(codec, WM8940_PLLN, + wm8940_write(codec, WM8940_PLLN, (pll_div.pre_scale << 4) | pll_div.n | (1 << 6)); else /* No factional component */ - snd_soc_write(codec, WM8940_PLLN, + wm8940_write(codec, WM8940_PLLN, (pll_div.pre_scale << 4) | pll_div.n); - snd_soc_write(codec, WM8940_PLLK1, pll_div.k >> 18); - snd_soc_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff); + wm8940_write(codec, WM8940_PLLK1, pll_div.k >> 18); + wm8940_write(codec, WM8940_PLLK2, (pll_div.k >> 9) & 0x1ff); + wm8940_write(codec, WM8940_PLLK3, pll_div.k & 0x1ff); /* Enable the PLL */ - reg = snd_soc_read(codec, WM8940_POWER1); - snd_soc_write(codec, WM8940_POWER1, reg | 0x020); + reg = wm8940_read_reg_cache(codec, WM8940_POWER1); + wm8940_write(codec, WM8940_POWER1, reg | 0x020); /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_read(codec, WM8940_CLOCK); - snd_soc_write(codec, WM8940_CLOCK, reg | 0x100); + reg = wm8940_read_reg_cache(codec, WM8940_CLOCK); + wm8940_write(codec, WM8940_CLOCK, reg | 0x100); return 0; } @@ -604,16 +648,16 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8940_BCLKDIV: - reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3; - ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2)); + reg = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0xFFEF3; + ret = wm8940_write(codec, WM8940_CLOCK, reg | (div << 2)); break; case WM8940_MCLKDIV: - reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFF1F; - ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5)); + reg = wm8940_read_reg_cache(codec, WM8940_CLOCK) & 0xFF1F; + ret = wm8940_write(codec, WM8940_CLOCK, reg | (div << 5)); break; case WM8940_OPCLKDIV: - reg = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFCF; - ret = snd_soc_write(codec, WM8940_ADDCNTRL, reg | (div << 4)); + reg = wm8940_read_reg_cache(codec, WM8940_ADDCNTRL) & 0xFFCF; + ret = wm8940_write(codec, WM8940_ADDCNTRL, reg | (div << 4)); break; } return ret; @@ -764,8 +808,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8940 = { }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8940); -static int wm8940_register(struct wm8940_priv *wm8940, - enum snd_soc_control_type control) +static int wm8940_register(struct wm8940_priv *wm8940) { struct wm8940_setup_data *pdata = wm8940->codec.dev->platform_data; struct snd_soc_codec *codec = &wm8940->codec; @@ -782,6 +825,8 @@ static int wm8940_register(struct wm8940_priv *wm8940, codec->private_data = wm8940; codec->name = "WM8940"; codec->owner = THIS_MODULE; + codec->read = wm8940_read_reg_cache; + codec->write = wm8940_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8940_set_bias_level; codec->dai = &wm8940_dai; @@ -789,12 +834,6 @@ static int wm8940_register(struct wm8940_priv *wm8940, codec->reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults); codec->reg_cache = &wm8940->reg_cache; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); - if (ret == 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - memcpy(codec->reg_cache, wm8940_reg_defaults, sizeof(wm8940_reg_defaults)); @@ -808,15 +847,15 @@ static int wm8940_register(struct wm8940_priv *wm8940, wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - ret = snd_soc_write(codec, WM8940_POWER1, 0x180); + ret = wm8940_write(codec, WM8940_POWER1, 0x180); if (ret < 0) return ret; if (!pdata) dev_warn(codec->dev, "No platform data supplied\n"); else { - reg = snd_soc_read(codec, WM8940_OUTPUTCTL); - ret = snd_soc_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi); + reg = wm8940_read_reg_cache(codec, WM8940_OUTPUTCTL); + ret = wm8940_write(codec, WM8940_OUTPUTCTL, reg | pdata->vroi); if (ret < 0) return ret; } @@ -865,7 +904,7 @@ static int wm8940_i2c_probe(struct i2c_client *i2c, codec->control_data = i2c; codec->dev = &i2c->dev; - return wm8940_register(wm8940, SND_SOC_I2C); + return wm8940_register(wm8940); } static int __devexit wm8940_i2c_remove(struct i2c_client *client) @@ -877,21 +916,6 @@ static int __devexit wm8940_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8940_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8940_i2c_suspend NULL -#define wm8940_i2c_resume NULL -#endif - static const struct i2c_device_id wm8940_i2c_id[] = { { "wm8940", 0 }, { } @@ -905,8 +929,6 @@ static struct i2c_driver wm8940_i2c_driver = { }, .probe = wm8940_i2c_probe, .remove = __devexit_p(wm8940_i2c_remove), - .suspend = wm8940_i2c_suspend, - .resume = wm8940_i2c_resume, .id_table = wm8940_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm8960.c b/trunk/sound/soc/codecs/wm8960.c index f59703be61c8..e224d8add170 100644 --- a/trunk/sound/soc/codecs/wm8960.c +++ b/trunk/sound/soc/codecs/wm8960.c @@ -69,7 +69,61 @@ struct wm8960_priv { struct snd_soc_codec codec; }; -#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) +/* + * read wm8960 register cache + */ +static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg == WM8960_RESET) + return 0; + if (reg >= WM8960_CACHEREGNUM) + return -1; + return cache[reg]; +} + +/* + * write wm8960 register cache + */ +static inline void wm8960_write_reg_cache(struct snd_soc_codec *codec, + u16 reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg >= WM8960_CACHEREGNUM) + return; + cache[reg] = value; +} + +static inline unsigned int wm8960_read(struct snd_soc_codec *codec, + unsigned int reg) +{ + return wm8960_read_reg_cache(codec, reg); +} + +/* + * write to the WM8960 register space + */ +static int wm8960_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + /* data is + * D15..D9 WM8960 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8960_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +#define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0) /* enumerated controls */ static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; @@ -366,7 +420,7 @@ static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai, } /* set iface */ - snd_soc_write(codec, WM8960_IFACE1, iface); + wm8960_write(codec, WM8960_IFACE1, iface); return 0; } @@ -377,7 +431,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; + u16 iface = wm8960_read(codec, WM8960_IFACE1) & 0xfff3; /* bit size */ switch (params_format(params)) { @@ -392,19 +446,19 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, } /* set iface */ - snd_soc_write(codec, WM8960_IFACE1, iface); + wm8960_write(codec, WM8960_IFACE1, iface); return 0; } static int wm8960_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7; + u16 mute_reg = wm8960_read(codec, WM8960_DACCTL1) & 0xfff7; if (mute) - snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8); + wm8960_write(codec, WM8960_DACCTL1, mute_reg | 0x8); else - snd_soc_write(codec, WM8960_DACCTL1, mute_reg); + wm8960_write(codec, WM8960_DACCTL1, mute_reg); return 0; } @@ -420,16 +474,16 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: /* Set VMID to 2x50k */ - reg = snd_soc_read(codec, WM8960_POWER1); + reg = wm8960_read(codec, WM8960_POWER1); reg &= ~0x180; reg |= 0x80; - snd_soc_write(codec, WM8960_POWER1, reg); + wm8960_write(codec, WM8960_POWER1, reg); break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Enable anti-pop features */ - snd_soc_write(codec, WM8960_APOP1, + wm8960_write(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | WM8960_BUFDCOPEN | WM8960_BUFIOEN); @@ -437,43 +491,43 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, reg = WM8960_DISOP; if (pdata) reg |= pdata->dres << 4; - snd_soc_write(codec, WM8960_APOP2, reg); + wm8960_write(codec, WM8960_APOP2, reg); msleep(400); - snd_soc_write(codec, WM8960_APOP2, 0); + wm8960_write(codec, WM8960_APOP2, 0); /* Enable & ramp VMID at 2x50k */ - reg = snd_soc_read(codec, WM8960_POWER1); + reg = wm8960_read(codec, WM8960_POWER1); reg |= 0x80; - snd_soc_write(codec, WM8960_POWER1, reg); + wm8960_write(codec, WM8960_POWER1, reg); msleep(100); /* Enable VREF */ - snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF); + wm8960_write(codec, WM8960_POWER1, reg | WM8960_VREF); /* Disable anti-pop features */ - snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN); + wm8960_write(codec, WM8960_APOP1, WM8960_BUFIOEN); } /* Set VMID to 2x250k */ - reg = snd_soc_read(codec, WM8960_POWER1); + reg = wm8960_read(codec, WM8960_POWER1); reg &= ~0x180; reg |= 0x100; - snd_soc_write(codec, WM8960_POWER1, reg); + wm8960_write(codec, WM8960_POWER1, reg); break; case SND_SOC_BIAS_OFF: /* Enable anti-pop features */ - snd_soc_write(codec, WM8960_APOP1, + wm8960_write(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | WM8960_BUFDCOPEN | WM8960_BUFIOEN); /* Disable VMID and VREF, let them discharge */ - snd_soc_write(codec, WM8960_POWER1, 0); + wm8960_write(codec, WM8960_POWER1, 0); msleep(600); - snd_soc_write(codec, WM8960_APOP1, 0); + wm8960_write(codec, WM8960_APOP1, 0); break; } @@ -556,33 +610,33 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, /* Disable the PLL: even if we are changing the frequency the * PLL needs to be disabled while we do so. */ - snd_soc_write(codec, WM8960_CLOCK1, - snd_soc_read(codec, WM8960_CLOCK1) & ~1); - snd_soc_write(codec, WM8960_POWER2, - snd_soc_read(codec, WM8960_POWER2) & ~1); + wm8960_write(codec, WM8960_CLOCK1, + wm8960_read(codec, WM8960_CLOCK1) & ~1); + wm8960_write(codec, WM8960_POWER2, + wm8960_read(codec, WM8960_POWER2) & ~1); if (!freq_in || !freq_out) return 0; - reg = snd_soc_read(codec, WM8960_PLL1) & ~0x3f; + reg = wm8960_read(codec, WM8960_PLL1) & ~0x3f; reg |= pll_div.pre_div << 4; reg |= pll_div.n; if (pll_div.k) { reg |= 0x20; - snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); - snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); + wm8960_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); + wm8960_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); + wm8960_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); } - snd_soc_write(codec, WM8960_PLL1, reg); + wm8960_write(codec, WM8960_PLL1, reg); /* Turn it on */ - snd_soc_write(codec, WM8960_POWER2, - snd_soc_read(codec, WM8960_POWER2) | 1); + wm8960_write(codec, WM8960_POWER2, + wm8960_read(codec, WM8960_POWER2) | 1); msleep(250); - snd_soc_write(codec, WM8960_CLOCK1, - snd_soc_read(codec, WM8960_CLOCK1) | 1); + wm8960_write(codec, WM8960_CLOCK1, + wm8960_read(codec, WM8960_CLOCK1) | 1); return 0; } @@ -595,28 +649,28 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8960_SYSCLKSEL: - reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1fe; - snd_soc_write(codec, WM8960_CLOCK1, reg | div); + reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1fe; + wm8960_write(codec, WM8960_CLOCK1, reg | div); break; case WM8960_SYSCLKDIV: - reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9; - snd_soc_write(codec, WM8960_CLOCK1, reg | div); + reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1f9; + wm8960_write(codec, WM8960_CLOCK1, reg | div); break; case WM8960_DACDIV: - reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1c7; - snd_soc_write(codec, WM8960_CLOCK1, reg | div); + reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1c7; + wm8960_write(codec, WM8960_CLOCK1, reg | div); break; case WM8960_OPCLKDIV: - reg = snd_soc_read(codec, WM8960_PLL1) & 0x03f; - snd_soc_write(codec, WM8960_PLL1, reg | div); + reg = wm8960_read(codec, WM8960_PLL1) & 0x03f; + wm8960_write(codec, WM8960_PLL1, reg | div); break; case WM8960_DCLKDIV: - reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f; - snd_soc_write(codec, WM8960_CLOCK2, reg | div); + reg = wm8960_read(codec, WM8960_CLOCK2) & 0x03f; + wm8960_write(codec, WM8960_CLOCK2, reg | div); break; case WM8960_TOCLKSEL: - reg = snd_soc_read(codec, WM8960_ADDCTL1) & 0x1fd; - snd_soc_write(codec, WM8960_ADDCTL1, reg | div); + reg = wm8960_read(codec, WM8960_ADDCTL1) & 0x1fd; + wm8960_write(codec, WM8960_ADDCTL1, reg | div); break; default: return -EINVAL; @@ -747,8 +801,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8960 = { }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8960); -static int wm8960_register(struct wm8960_priv *wm8960, - enum snd_soc_control_type control) +static int wm8960_register(struct wm8960_priv *wm8960) { struct wm8960_data *pdata = wm8960->codec.dev->platform_data; struct snd_soc_codec *codec = &wm8960->codec; @@ -757,8 +810,7 @@ static int wm8960_register(struct wm8960_priv *wm8960, if (wm8960_codec) { dev_err(codec->dev, "Another WM8960 is registered\n"); - ret = -EINVAL; - goto err; + return -EINVAL; } if (!pdata) { @@ -777,6 +829,8 @@ static int wm8960_register(struct wm8960_priv *wm8960, codec->private_data = wm8960; codec->name = "WM8960"; codec->owner = THIS_MODULE; + codec->read = wm8960_read_reg_cache; + codec->write = wm8960_write; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm8960_set_bias_level; codec->dai = &wm8960_dai; @@ -786,16 +840,10 @@ static int wm8960_register(struct wm8960_priv *wm8960, memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - ret = wm8960_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } wm8960_dai.dev = codec->dev; @@ -803,48 +851,43 @@ static int wm8960_register(struct wm8960_priv *wm8960, wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Latch the update bits */ - reg = snd_soc_read(codec, WM8960_LINVOL); - snd_soc_write(codec, WM8960_LINVOL, reg | 0x100); - reg = snd_soc_read(codec, WM8960_RINVOL); - snd_soc_write(codec, WM8960_RINVOL, reg | 0x100); - reg = snd_soc_read(codec, WM8960_LADC); - snd_soc_write(codec, WM8960_LADC, reg | 0x100); - reg = snd_soc_read(codec, WM8960_RADC); - snd_soc_write(codec, WM8960_RADC, reg | 0x100); - reg = snd_soc_read(codec, WM8960_LDAC); - snd_soc_write(codec, WM8960_LDAC, reg | 0x100); - reg = snd_soc_read(codec, WM8960_RDAC); - snd_soc_write(codec, WM8960_RDAC, reg | 0x100); - reg = snd_soc_read(codec, WM8960_LOUT1); - snd_soc_write(codec, WM8960_LOUT1, reg | 0x100); - reg = snd_soc_read(codec, WM8960_ROUT1); - snd_soc_write(codec, WM8960_ROUT1, reg | 0x100); - reg = snd_soc_read(codec, WM8960_LOUT2); - snd_soc_write(codec, WM8960_LOUT2, reg | 0x100); - reg = snd_soc_read(codec, WM8960_ROUT2); - snd_soc_write(codec, WM8960_ROUT2, reg | 0x100); + reg = wm8960_read(codec, WM8960_LINVOL); + wm8960_write(codec, WM8960_LINVOL, reg | 0x100); + reg = wm8960_read(codec, WM8960_RINVOL); + wm8960_write(codec, WM8960_RINVOL, reg | 0x100); + reg = wm8960_read(codec, WM8960_LADC); + wm8960_write(codec, WM8960_LADC, reg | 0x100); + reg = wm8960_read(codec, WM8960_RADC); + wm8960_write(codec, WM8960_RADC, reg | 0x100); + reg = wm8960_read(codec, WM8960_LDAC); + wm8960_write(codec, WM8960_LDAC, reg | 0x100); + reg = wm8960_read(codec, WM8960_RDAC); + wm8960_write(codec, WM8960_RDAC, reg | 0x100); + reg = wm8960_read(codec, WM8960_LOUT1); + wm8960_write(codec, WM8960_LOUT1, reg | 0x100); + reg = wm8960_read(codec, WM8960_ROUT1); + wm8960_write(codec, WM8960_ROUT1, reg | 0x100); + reg = wm8960_read(codec, WM8960_LOUT2); + wm8960_write(codec, WM8960_LOUT2, reg | 0x100); + reg = wm8960_read(codec, WM8960_ROUT2); + wm8960_write(codec, WM8960_ROUT2, reg | 0x100); wm8960_codec = codec; ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; + return ret; } ret = snd_soc_register_dai(&wm8960_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; + snd_soc_unregister_codec(codec); + return ret; } return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8960); - return ret; } static void wm8960_unregister(struct wm8960_priv *wm8960) @@ -867,13 +910,14 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, return -ENOMEM; codec = &wm8960->codec; + codec->hw_write = (hw_write_t)i2c_master_send; i2c_set_clientdata(i2c, wm8960); codec->control_data = i2c; codec->dev = &i2c->dev; - return wm8960_register(wm8960, SND_SOC_I2C); + return wm8960_register(wm8960); } static __devexit int wm8960_i2c_remove(struct i2c_client *client) @@ -883,21 +927,6 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8960_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8960_i2c_suspend NULL -#define wm8960_i2c_resume NULL -#endif - static const struct i2c_device_id wm8960_i2c_id[] = { { "wm8960", 0 }, { } @@ -911,8 +940,6 @@ static struct i2c_driver wm8960_i2c_driver = { }, .probe = wm8960_i2c_probe, .remove = __devexit_p(wm8960_i2c_remove), - .suspend = wm8960_i2c_suspend, - .resume = wm8960_i2c_resume, .id_table = wm8960_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm8961.c b/trunk/sound/soc/codecs/wm8961.c deleted file mode 100644 index 503032085899..000000000000 --- a/trunk/sound/soc/codecs/wm8961.c +++ /dev/null @@ -1,1265 +0,0 @@ -/* - * wm8961.c -- WM8961 ALSA SoC Audio driver - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Currently unimplemented features: - * - ALC - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8961.h" - -#define WM8961_MAX_REGISTER 0xFC - -static u16 wm8961_reg_defaults[] = { - 0x009F, /* R0 - Left Input volume */ - 0x009F, /* R1 - Right Input volume */ - 0x0000, /* R2 - LOUT1 volume */ - 0x0000, /* R3 - ROUT1 volume */ - 0x0020, /* R4 - Clocking1 */ - 0x0008, /* R5 - ADC & DAC Control 1 */ - 0x0000, /* R6 - ADC & DAC Control 2 */ - 0x000A, /* R7 - Audio Interface 0 */ - 0x01F4, /* R8 - Clocking2 */ - 0x0000, /* R9 - Audio Interface 1 */ - 0x00FF, /* R10 - Left DAC volume */ - 0x00FF, /* R11 - Right DAC volume */ - 0x0000, /* R12 */ - 0x0000, /* R13 */ - 0x0040, /* R14 - Audio Interface 2 */ - 0x0000, /* R15 - Software Reset */ - 0x0000, /* R16 */ - 0x007B, /* R17 - ALC1 */ - 0x0000, /* R18 - ALC2 */ - 0x0032, /* R19 - ALC3 */ - 0x0000, /* R20 - Noise Gate */ - 0x00C0, /* R21 - Left ADC volume */ - 0x00C0, /* R22 - Right ADC volume */ - 0x0120, /* R23 - Additional control(1) */ - 0x0000, /* R24 - Additional control(2) */ - 0x0000, /* R25 - Pwr Mgmt (1) */ - 0x0000, /* R26 - Pwr Mgmt (2) */ - 0x0000, /* R27 - Additional Control (3) */ - 0x0000, /* R28 - Anti-pop */ - 0x0000, /* R29 */ - 0x005F, /* R30 - Clocking 3 */ - 0x0000, /* R31 */ - 0x0000, /* R32 - ADCL signal path */ - 0x0000, /* R33 - ADCR signal path */ - 0x0000, /* R34 */ - 0x0000, /* R35 */ - 0x0000, /* R36 */ - 0x0000, /* R37 */ - 0x0000, /* R38 */ - 0x0000, /* R39 */ - 0x0000, /* R40 - LOUT2 volume */ - 0x0000, /* R41 - ROUT2 volume */ - 0x0000, /* R42 */ - 0x0000, /* R43 */ - 0x0000, /* R44 */ - 0x0000, /* R45 */ - 0x0000, /* R46 */ - 0x0000, /* R47 - Pwr Mgmt (3) */ - 0x0023, /* R48 - Additional Control (4) */ - 0x0000, /* R49 - Class D Control 1 */ - 0x0000, /* R50 */ - 0x0003, /* R51 - Class D Control 2 */ - 0x0000, /* R52 */ - 0x0000, /* R53 */ - 0x0000, /* R54 */ - 0x0000, /* R55 */ - 0x0106, /* R56 - Clocking 4 */ - 0x0000, /* R57 - DSP Sidetone 0 */ - 0x0000, /* R58 - DSP Sidetone 1 */ - 0x0000, /* R59 */ - 0x0000, /* R60 - DC Servo 0 */ - 0x0000, /* R61 - DC Servo 1 */ - 0x0000, /* R62 */ - 0x015E, /* R63 - DC Servo 3 */ - 0x0010, /* R64 */ - 0x0010, /* R65 - DC Servo 5 */ - 0x0000, /* R66 */ - 0x0001, /* R67 */ - 0x0003, /* R68 - Analogue PGA Bias */ - 0x0000, /* R69 - Analogue HP 0 */ - 0x0060, /* R70 */ - 0x01FB, /* R71 - Analogue HP 2 */ - 0x0000, /* R72 - Charge Pump 1 */ - 0x0065, /* R73 */ - 0x005F, /* R74 */ - 0x0059, /* R75 */ - 0x006B, /* R76 */ - 0x0038, /* R77 */ - 0x000C, /* R78 */ - 0x000A, /* R79 */ - 0x006B, /* R80 */ - 0x0000, /* R81 */ - 0x0000, /* R82 - Charge Pump B */ - 0x0087, /* R83 */ - 0x0000, /* R84 */ - 0x005C, /* R85 */ - 0x0000, /* R86 */ - 0x0000, /* R87 - Write Sequencer 1 */ - 0x0000, /* R88 - Write Sequencer 2 */ - 0x0000, /* R89 - Write Sequencer 3 */ - 0x0000, /* R90 - Write Sequencer 4 */ - 0x0000, /* R91 - Write Sequencer 5 */ - 0x0000, /* R92 - Write Sequencer 6 */ - 0x0000, /* R93 - Write Sequencer 7 */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0000, /* R96 */ - 0x0000, /* R97 */ - 0x0000, /* R98 */ - 0x0000, /* R99 */ - 0x0000, /* R100 */ - 0x0000, /* R101 */ - 0x0000, /* R102 */ - 0x0000, /* R103 */ - 0x0000, /* R104 */ - 0x0000, /* R105 */ - 0x0000, /* R106 */ - 0x0000, /* R107 */ - 0x0000, /* R108 */ - 0x0000, /* R109 */ - 0x0000, /* R110 */ - 0x0000, /* R111 */ - 0x0000, /* R112 */ - 0x0000, /* R113 */ - 0x0000, /* R114 */ - 0x0000, /* R115 */ - 0x0000, /* R116 */ - 0x0000, /* R117 */ - 0x0000, /* R118 */ - 0x0000, /* R119 */ - 0x0000, /* R120 */ - 0x0000, /* R121 */ - 0x0000, /* R122 */ - 0x0000, /* R123 */ - 0x0000, /* R124 */ - 0x0000, /* R125 */ - 0x0000, /* R126 */ - 0x0000, /* R127 */ - 0x0000, /* R128 */ - 0x0000, /* R129 */ - 0x0000, /* R130 */ - 0x0000, /* R131 */ - 0x0000, /* R132 */ - 0x0000, /* R133 */ - 0x0000, /* R134 */ - 0x0000, /* R135 */ - 0x0000, /* R136 */ - 0x0000, /* R137 */ - 0x0000, /* R138 */ - 0x0000, /* R139 */ - 0x0000, /* R140 */ - 0x0000, /* R141 */ - 0x0000, /* R142 */ - 0x0000, /* R143 */ - 0x0000, /* R144 */ - 0x0000, /* R145 */ - 0x0000, /* R146 */ - 0x0000, /* R147 */ - 0x0000, /* R148 */ - 0x0000, /* R149 */ - 0x0000, /* R150 */ - 0x0000, /* R151 */ - 0x0000, /* R152 */ - 0x0000, /* R153 */ - 0x0000, /* R154 */ - 0x0000, /* R155 */ - 0x0000, /* R156 */ - 0x0000, /* R157 */ - 0x0000, /* R158 */ - 0x0000, /* R159 */ - 0x0000, /* R160 */ - 0x0000, /* R161 */ - 0x0000, /* R162 */ - 0x0000, /* R163 */ - 0x0000, /* R164 */ - 0x0000, /* R165 */ - 0x0000, /* R166 */ - 0x0000, /* R167 */ - 0x0000, /* R168 */ - 0x0000, /* R169 */ - 0x0000, /* R170 */ - 0x0000, /* R171 */ - 0x0000, /* R172 */ - 0x0000, /* R173 */ - 0x0000, /* R174 */ - 0x0000, /* R175 */ - 0x0000, /* R176 */ - 0x0000, /* R177 */ - 0x0000, /* R178 */ - 0x0000, /* R179 */ - 0x0000, /* R180 */ - 0x0000, /* R181 */ - 0x0000, /* R182 */ - 0x0000, /* R183 */ - 0x0000, /* R184 */ - 0x0000, /* R185 */ - 0x0000, /* R186 */ - 0x0000, /* R187 */ - 0x0000, /* R188 */ - 0x0000, /* R189 */ - 0x0000, /* R190 */ - 0x0000, /* R191 */ - 0x0000, /* R192 */ - 0x0000, /* R193 */ - 0x0000, /* R194 */ - 0x0000, /* R195 */ - 0x0030, /* R196 */ - 0x0006, /* R197 */ - 0x0000, /* R198 */ - 0x0060, /* R199 */ - 0x0000, /* R200 */ - 0x003F, /* R201 */ - 0x0000, /* R202 */ - 0x0000, /* R203 */ - 0x0000, /* R204 */ - 0x0001, /* R205 */ - 0x0000, /* R206 */ - 0x0181, /* R207 */ - 0x0005, /* R208 */ - 0x0008, /* R209 */ - 0x0008, /* R210 */ - 0x0000, /* R211 */ - 0x013B, /* R212 */ - 0x0000, /* R213 */ - 0x0000, /* R214 */ - 0x0000, /* R215 */ - 0x0000, /* R216 */ - 0x0070, /* R217 */ - 0x0000, /* R218 */ - 0x0000, /* R219 */ - 0x0000, /* R220 */ - 0x0000, /* R221 */ - 0x0000, /* R222 */ - 0x0003, /* R223 */ - 0x0000, /* R224 */ - 0x0000, /* R225 */ - 0x0001, /* R226 */ - 0x0008, /* R227 */ - 0x0000, /* R228 */ - 0x0000, /* R229 */ - 0x0000, /* R230 */ - 0x0000, /* R231 */ - 0x0004, /* R232 */ - 0x0000, /* R233 */ - 0x0000, /* R234 */ - 0x0000, /* R235 */ - 0x0000, /* R236 */ - 0x0000, /* R237 */ - 0x0080, /* R238 */ - 0x0000, /* R239 */ - 0x0000, /* R240 */ - 0x0000, /* R241 */ - 0x0000, /* R242 */ - 0x0000, /* R243 */ - 0x0000, /* R244 */ - 0x0052, /* R245 */ - 0x0110, /* R246 */ - 0x0040, /* R247 */ - 0x0000, /* R248 */ - 0x0030, /* R249 */ - 0x0000, /* R250 */ - 0x0000, /* R251 */ - 0x0001, /* R252 - General test 1 */ -}; - -struct wm8961_priv { - struct snd_soc_codec codec; - int sysclk; - u16 reg_cache[WM8961_MAX_REGISTER]; -}; - -static int wm8961_volatile_register(unsigned int reg) -{ - switch (reg) { - case WM8961_SOFTWARE_RESET: - case WM8961_WRITE_SEQUENCER_7: - case WM8961_DC_SERVO_1: - return 1; - - default: - return 0; - } -} - -static int wm8961_reset(struct snd_soc_codec *codec) -{ - return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0); -} - -/* - * The headphone output supports special anti-pop sequences giving - * silent power up and power down. - */ -static int wm8961_hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 hp_reg = snd_soc_read(codec, WM8961_ANALOGUE_HP_0); - u16 cp_reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_1); - u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2); - u16 dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1); - int timeout = 500; - - if (event & SND_SOC_DAPM_POST_PMU) { - /* Make sure the output is shorted */ - hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT); - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Enable the charge pump */ - cp_reg |= WM8961_CP_ENA; - snd_soc_write(codec, WM8961_CHARGE_PUMP_1, cp_reg); - mdelay(5); - - /* Enable the PGA */ - pwr_reg |= WM8961_LOUT1_PGA | WM8961_ROUT1_PGA; - snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Enable the amplifier */ - hp_reg |= WM8961_HPR_ENA | WM8961_HPL_ENA; - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Second stage enable */ - hp_reg |= WM8961_HPR_ENA_DLY | WM8961_HPL_ENA_DLY; - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Enable the DC servo & trigger startup */ - dcs_reg |= - WM8961_DCS_ENA_CHAN_HPR | WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_ENA_CHAN_HPL | WM8961_DCS_TRIG_STARTUP_HPL; - dev_dbg(codec->dev, "Enabling DC servo\n"); - - snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg); - do { - msleep(1); - dcs_reg = snd_soc_read(codec, WM8961_DC_SERVO_1); - } while (--timeout && - dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_TRIG_STARTUP_HPL)); - if (dcs_reg & (WM8961_DCS_TRIG_STARTUP_HPR | - WM8961_DCS_TRIG_STARTUP_HPL)) - dev_err(codec->dev, "DC servo timed out\n"); - else - dev_dbg(codec->dev, "DC servo startup complete\n"); - - /* Enable the output stage */ - hp_reg |= WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP; - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Remove the short on the output stage */ - hp_reg |= WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT; - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - } - - if (event & SND_SOC_DAPM_PRE_PMD) { - /* Short the output */ - hp_reg &= ~(WM8961_HPR_RMV_SHORT | WM8961_HPL_RMV_SHORT); - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable the output stage */ - hp_reg &= ~(WM8961_HPR_ENA_OUTP | WM8961_HPL_ENA_OUTP); - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable DC offset cancellation */ - dcs_reg &= ~(WM8961_DCS_ENA_CHAN_HPR | - WM8961_DCS_ENA_CHAN_HPL); - snd_soc_write(codec, WM8961_DC_SERVO_1, dcs_reg); - - /* Finish up */ - hp_reg &= ~(WM8961_HPR_ENA_DLY | WM8961_HPR_ENA | - WM8961_HPL_ENA_DLY | WM8961_HPL_ENA); - snd_soc_write(codec, WM8961_ANALOGUE_HP_0, hp_reg); - - /* Disable the PGA */ - pwr_reg &= ~(WM8961_LOUT1_PGA | WM8961_ROUT1_PGA); - snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Disable the charge pump */ - dev_dbg(codec->dev, "Disabling charge pump\n"); - snd_soc_write(codec, WM8961_CHARGE_PUMP_1, - cp_reg & ~WM8961_CP_ENA); - } - - return 0; -} - -static int wm8961_spk_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 pwr_reg = snd_soc_read(codec, WM8961_PWR_MGMT_2); - u16 spk_reg = snd_soc_read(codec, WM8961_CLASS_D_CONTROL_1); - - if (event & SND_SOC_DAPM_POST_PMU) { - /* Enable the PGA */ - pwr_reg |= WM8961_SPKL_PGA | WM8961_SPKR_PGA; - snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - - /* Enable the amplifier */ - spk_reg |= WM8961_SPKL_ENA | WM8961_SPKR_ENA; - snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg); - } - - if (event & SND_SOC_DAPM_PRE_PMD) { - /* Enable the amplifier */ - spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA); - snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg); - - /* Enable the PGA */ - pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA); - snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg); - } - - return 0; -} - -static const char *adc_hpf_text[] = { - "Hi-fi", "Voice 1", "Voice 2", "Voice 3", -}; - -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_2, 7, 4, adc_hpf_text); - -static const char *dac_deemph_text[] = { - "None", "32kHz", "44.1kHz", "48kHz", -}; - -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8961_ADC_DAC_CONTROL_1, 1, 4, dac_deemph_text); - -static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); -static const DECLARE_TLV_DB_SCALE(hp_sec_tlv, -700, 100, 0); -static const DECLARE_TLV_DB_SCALE(adc_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); -static unsigned int boost_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), - 1, 1, TLV_DB_SCALE_ITEM(13, 0, 0), - 2, 2, TLV_DB_SCALE_ITEM(20, 0, 0), - 3, 3, TLV_DB_SCALE_ITEM(29, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(pga_tlv, -2325, 75, 0); - -static const struct snd_kcontrol_new wm8961_snd_controls[] = { -SOC_DOUBLE_R_TLV("Headphone Volume", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME, - 0, 127, 0, out_tlv), -SOC_DOUBLE_TLV("Headphone Secondary Volume", WM8961_ANALOGUE_HP_2, - 6, 3, 7, 0, hp_sec_tlv), -SOC_DOUBLE_R("Headphone ZC Switch", WM8961_LOUT1_VOLUME, WM8961_ROUT1_VOLUME, - 7, 1, 0), - -SOC_DOUBLE_R_TLV("Speaker Volume", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME, - 0, 127, 0, out_tlv), -SOC_DOUBLE_R("Speaker ZC Switch", WM8961_LOUT2_VOLUME, WM8961_ROUT2_VOLUME, - 7, 1, 0), -SOC_SINGLE("Speaker AC Gain", WM8961_CLASS_D_CONTROL_2, 0, 7, 0), - -SOC_SINGLE("DAC x128 OSR Switch", WM8961_ADC_DAC_CONTROL_2, 0, 1, 0), -SOC_ENUM("DAC Deemphasis", dac_deemph), -SOC_SINGLE("DAC Soft Mute Switch", WM8961_ADC_DAC_CONTROL_2, 3, 1, 0), - -SOC_DOUBLE_R_TLV("Sidetone Volume", WM8961_DSP_SIDETONE_0, - WM8961_DSP_SIDETONE_1, 4, 12, 0, sidetone_tlv), - -SOC_SINGLE("ADC High Pass Filter Switch", WM8961_ADC_DAC_CONTROL_1, 0, 1, 0), -SOC_ENUM("ADC High Pass Filter Mode", adc_hpf), - -SOC_DOUBLE_R_TLV("Capture Volume", - WM8961_LEFT_ADC_VOLUME, WM8961_RIGHT_ADC_VOLUME, - 1, 119, 0, adc_tlv), -SOC_DOUBLE_R_TLV("Capture Boost Volume", - WM8961_ADCL_SIGNAL_PATH, WM8961_ADCR_SIGNAL_PATH, - 4, 3, 0, boost_tlv), -SOC_DOUBLE_R_TLV("Capture PGA Volume", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 0, 62, 0, pga_tlv), -SOC_DOUBLE_R("Capture PGA ZC Switch", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 6, 1, 1), -SOC_DOUBLE_R("Capture PGA Switch", - WM8961_LEFT_INPUT_VOLUME, WM8961_RIGHT_INPUT_VOLUME, - 7, 1, 1), -}; - -static const char *sidetone_text[] = { - "None", "Left", "Right" -}; - -static const struct soc_enum dacl_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_0, 2, 3, sidetone_text); - -static const struct soc_enum dacr_sidetone = - SOC_ENUM_SINGLE(WM8961_DSP_SIDETONE_1, 2, 3, sidetone_text); - -static const struct snd_kcontrol_new dacl_mux = - SOC_DAPM_ENUM("DACL Sidetone", dacl_sidetone); - -static const struct snd_kcontrol_new dacr_mux = - SOC_DAPM_ENUM("DACR Sidetone", dacr_sidetone); - -static const struct snd_soc_dapm_widget wm8961_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("LINPUT"), -SND_SOC_DAPM_INPUT("RINPUT"), - -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8961_CLOCKING2, 4, 0, NULL, 0), - -SND_SOC_DAPM_PGA("Left Input", WM8961_PWR_MGMT_1, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0), - -SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0), -SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0), - -SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0), - -SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux), -SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux), - -SND_SOC_DAPM_DAC("DACL", "HiFi Playback", WM8961_PWR_MGMT_2, 8, 0), -SND_SOC_DAPM_DAC("DACR", "HiFi Playback", WM8961_PWR_MGMT_2, 7, 0), - -/* Handle as a mono path for DCS */ -SND_SOC_DAPM_PGA_E("Headphone Output", SND_SOC_NOPM, - 4, 0, NULL, 0, wm8961_hp_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), -SND_SOC_DAPM_PGA_E("Speaker Output", SND_SOC_NOPM, - 4, 0, NULL, 0, wm8961_spk_event, - SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_OUTPUT("HP_L"), -SND_SOC_DAPM_OUTPUT("HP_R"), -SND_SOC_DAPM_OUTPUT("SPK_LN"), -SND_SOC_DAPM_OUTPUT("SPK_LP"), -SND_SOC_DAPM_OUTPUT("SPK_RN"), -SND_SOC_DAPM_OUTPUT("SPK_RP"), -}; - - -static const struct snd_soc_dapm_route audio_paths[] = { - { "DACL", NULL, "CLK_DSP" }, - { "DACL", NULL, "DACL Sidetone" }, - { "DACR", NULL, "CLK_DSP" }, - { "DACR", NULL, "DACR Sidetone" }, - - { "DACL Sidetone", "Left", "ADCL" }, - { "DACL Sidetone", "Right", "ADCR" }, - - { "DACR Sidetone", "Left", "ADCL" }, - { "DACR Sidetone", "Right", "ADCR" }, - - { "HP_L", NULL, "Headphone Output" }, - { "HP_R", NULL, "Headphone Output" }, - { "Headphone Output", NULL, "DACL" }, - { "Headphone Output", NULL, "DACR" }, - - { "SPK_LN", NULL, "Speaker Output" }, - { "SPK_LP", NULL, "Speaker Output" }, - { "SPK_RN", NULL, "Speaker Output" }, - { "SPK_RP", NULL, "Speaker Output" }, - - { "Speaker Output", NULL, "DACL" }, - { "Speaker Output", NULL, "DACR" }, - - { "ADCL", NULL, "Left Input" }, - { "ADCL", NULL, "CLK_DSP" }, - { "ADCR", NULL, "Right Input" }, - { "ADCR", NULL, "CLK_DSP" }, - - { "Left Input", NULL, "LINPUT" }, - { "Right Input", NULL, "RINPUT" }, - -}; - -/* Values for CLK_SYS_RATE */ -static struct { - int ratio; - u16 val; -} wm8961_clk_sys_ratio[] = { - { 64, 0 }, - { 128, 1 }, - { 192, 2 }, - { 256, 3 }, - { 384, 4 }, - { 512, 5 }, - { 768, 6 }, - { 1024, 7 }, - { 1408, 8 }, - { 1536, 9 }, -}; - -/* Values for SAMPLE_RATE */ -static struct { - int rate; - u16 val; -} wm8961_srate[] = { - { 48000, 0 }, - { 44100, 0 }, - { 32000, 1 }, - { 22050, 2 }, - { 24000, 2 }, - { 16000, 3 }, - { 11250, 4 }, - { 12000, 4 }, - { 8000, 5 }, -}; - -static int wm8961_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8961_priv *wm8961 = codec->private_data; - int i, best, target, fs; - u16 reg; - - fs = params_rate(params); - - if (!wm8961->sysclk) { - dev_err(codec->dev, "MCLK has not been specified\n"); - return -EINVAL; - } - - /* Find the closest sample rate for the filters */ - best = 0; - for (i = 0; i < ARRAY_SIZE(wm8961_srate); i++) { - if (abs(wm8961_srate[i].rate - fs) < - abs(wm8961_srate[best].rate - fs)) - best = i; - } - reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_3); - reg &= ~WM8961_SAMPLE_RATE_MASK; - reg |= wm8961_srate[best].val; - snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_3, reg); - dev_dbg(codec->dev, "Selected SRATE %dHz for %dHz\n", - wm8961_srate[best].rate, fs); - - /* Select a CLK_SYS/fs ratio equal to or higher than required */ - target = wm8961->sysclk / fs; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && target < 64) { - dev_err(codec->dev, - "SYSCLK must be at least 64*fs for DAC\n"); - return -EINVAL; - } - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && target < 256) { - dev_err(codec->dev, - "SYSCLK must be at least 256*fs for ADC\n"); - return -EINVAL; - } - - for (i = 0; i < ARRAY_SIZE(wm8961_clk_sys_ratio); i++) { - if (wm8961_clk_sys_ratio[i].ratio >= target) - break; - } - if (i == ARRAY_SIZE(wm8961_clk_sys_ratio)) { - dev_err(codec->dev, "Unable to generate CLK_SYS_RATE\n"); - return -EINVAL; - } - dev_dbg(codec->dev, "Selected CLK_SYS_RATE of %d for %d/%d=%d\n", - wm8961_clk_sys_ratio[i].ratio, wm8961->sysclk, fs, - wm8961->sysclk / fs); - - reg = snd_soc_read(codec, WM8961_CLOCKING_4); - reg &= ~WM8961_CLK_SYS_RATE_MASK; - reg |= wm8961_clk_sys_ratio[i].val << WM8961_CLK_SYS_RATE_SHIFT; - snd_soc_write(codec, WM8961_CLOCKING_4, reg); - - reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0); - reg &= ~WM8961_WL_MASK; - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - reg |= 1 << WM8961_WL_SHIFT; - break; - case SNDRV_PCM_FORMAT_S24_LE: - reg |= 2 << WM8961_WL_SHIFT; - break; - case SNDRV_PCM_FORMAT_S32_LE: - reg |= 3 << WM8961_WL_SHIFT; - break; - default: - return -EINVAL; - } - snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, reg); - - /* Sloping stop-band filter is recommended for <= 24kHz */ - reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2); - if (fs <= 24000) - reg |= WM8961_DACSLOPE; - else - reg &= WM8961_DACSLOPE; - snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); - - return 0; -} - -static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id, - unsigned int freq, - int dir) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8961_priv *wm8961 = codec->private_data; - u16 reg = snd_soc_read(codec, WM8961_CLOCKING1); - - if (freq > 33000000) { - dev_err(codec->dev, "MCLK must be <33MHz\n"); - return -EINVAL; - } - - if (freq > 16500000) { - dev_dbg(codec->dev, "Using MCLK/2 for %dHz MCLK\n", freq); - reg |= WM8961_MCLKDIV; - freq /= 2; - } else { - dev_dbg(codec->dev, "Using MCLK/1 for %dHz MCLK\n", freq); - reg &= WM8961_MCLKDIV; - } - - snd_soc_write(codec, WM8961_CLOCKING1, reg); - - wm8961->sysclk = freq; - - return 0; -} - -static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - u16 aif = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_0); - - aif &= ~(WM8961_BCLKINV | WM8961_LRP | - WM8961_MS | WM8961_FORMAT_MASK); - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - aif |= WM8961_MS; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_RIGHT_J: - break; - - case SND_SOC_DAIFMT_LEFT_J: - aif |= 1; - break; - - case SND_SOC_DAIFMT_I2S: - aif |= 2; - break; - - case SND_SOC_DAIFMT_DSP_B: - aif |= WM8961_LRP; - case SND_SOC_DAIFMT_DSP_A: - aif |= 3; - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - case SND_SOC_DAIFMT_IB_NF: - break; - default: - return -EINVAL; - } - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_NB_IF: - aif |= WM8961_LRP; - break; - case SND_SOC_DAIFMT_IB_NF: - aif |= WM8961_BCLKINV; - break; - case SND_SOC_DAIFMT_IB_IF: - aif |= WM8961_BCLKINV | WM8961_LRP; - break; - default: - return -EINVAL; - } - - return snd_soc_write(codec, WM8961_AUDIO_INTERFACE_0, aif); -} - -static int wm8961_set_tristate(struct snd_soc_dai *dai, int tristate) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg = snd_soc_read(codec, WM8961_ADDITIONAL_CONTROL_2); - - if (tristate) - reg |= WM8961_TRIS; - else - reg &= ~WM8961_TRIS; - - return snd_soc_write(codec, WM8961_ADDITIONAL_CONTROL_2, reg); -} - -static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_1); - - if (mute) - reg |= WM8961_DACMU; - else - reg &= ~WM8961_DACMU; - - msleep(17); - - return snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_1, reg); -} - -static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) -{ - struct snd_soc_codec *codec = dai->codec; - u16 reg; - - switch (div_id) { - case WM8961_BCLK: - reg = snd_soc_read(codec, WM8961_CLOCKING2); - reg &= ~WM8961_BCLKDIV_MASK; - reg |= div; - snd_soc_write(codec, WM8961_CLOCKING2, reg); - break; - - case WM8961_LRCLK: - reg = snd_soc_read(codec, WM8961_AUDIO_INTERFACE_2); - reg &= ~WM8961_LRCLK_RATE_MASK; - reg |= div; - snd_soc_write(codec, WM8961_AUDIO_INTERFACE_2, reg); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm8961_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 reg; - - /* This is all slightly unusual since we have no bypass paths - * and the output amplifier structure means we can just slam - * the biases straight up rather than having to ramp them - * slowly. - */ - switch (level) { - case SND_SOC_BIAS_ON: - break; - - case SND_SOC_BIAS_PREPARE: - if (codec->bias_level == SND_SOC_BIAS_STANDBY) { - /* Enable bias generation */ - reg = snd_soc_read(codec, WM8961_ANTI_POP); - reg |= WM8961_BUFIOEN | WM8961_BUFDCOPEN; - snd_soc_write(codec, WM8961_ANTI_POP, reg); - - /* VMID=2*50k, VREF */ - reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VMIDSEL_MASK; - reg |= (1 << WM8961_VMIDSEL_SHIFT) | WM8961_VREF; - snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); - } - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_PREPARE) { - /* VREF off */ - reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VREF; - snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); - - /* Bias generation off */ - reg = snd_soc_read(codec, WM8961_ANTI_POP); - reg &= ~(WM8961_BUFIOEN | WM8961_BUFDCOPEN); - snd_soc_write(codec, WM8961_ANTI_POP, reg); - - /* VMID off */ - reg = snd_soc_read(codec, WM8961_PWR_MGMT_1); - reg &= ~WM8961_VMIDSEL_MASK; - snd_soc_write(codec, WM8961_PWR_MGMT_1, reg); - } - break; - - case SND_SOC_BIAS_OFF: - break; - } - - codec->bias_level = level; - - return 0; -} - - -#define WM8961_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM8961_FORMATS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -static struct snd_soc_dai_ops wm8961_dai_ops = { - .hw_params = wm8961_hw_params, - .set_sysclk = wm8961_set_sysclk, - .set_fmt = wm8961_set_fmt, - .digital_mute = wm8961_digital_mute, - .set_tristate = wm8961_set_tristate, - .set_clkdiv = wm8961_set_clkdiv, -}; - -struct snd_soc_dai wm8961_dai = { - .name = "WM8961", - .playback = { - .stream_name = "HiFi Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8961_RATES, - .formats = WM8961_FORMATS,}, - .capture = { - .stream_name = "HiFi Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8961_RATES, - .formats = WM8961_FORMATS,}, - .ops = &wm8961_dai_ops, -}; -EXPORT_SYMBOL_GPL(wm8961_dai); - - -static struct snd_soc_codec *wm8961_codec; - -static int wm8961_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8961_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8961_codec; - codec = wm8961_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8961_snd_controls, - ARRAY_SIZE(wm8961_snd_controls)); - snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, - ARRAY_SIZE(wm8961_dapm_widgets)); - snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); - snd_soc_dapm_new_widgets(codec); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -static int wm8961_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -#ifdef CONFIG_PM -static int wm8961_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF); - - return 0; -} - -static int wm8961_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - u16 *reg_cache = codec->reg_cache; - int i; - - for (i = 0; i < codec->reg_cache_size; i++) { - if (i == WM8961_SOFTWARE_RESET) - continue; - - snd_soc_write(codec, i, reg_cache[i]); - } - - wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - return 0; -} -#else -#define wm8961_suspend NULL -#define wm8961_resume NULL -#endif - -struct snd_soc_codec_device soc_codec_dev_wm8961 = { - .probe = wm8961_probe, - .remove = wm8961_remove, - .suspend = wm8961_suspend, - .resume = wm8961_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8961); - -static int wm8961_register(struct wm8961_priv *wm8961) -{ - struct snd_soc_codec *codec = &wm8961->codec; - int ret; - u16 reg; - - if (wm8961_codec) { - dev_err(codec->dev, "Another WM8961 is registered\n"); - ret = -EINVAL; - goto err; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->private_data = wm8961; - codec->name = "WM8961"; - codec->owner = THIS_MODULE; - codec->dai = &wm8961_dai; - codec->num_dai = 1; - codec->reg_cache_size = ARRAY_SIZE(wm8961->reg_cache); - codec->reg_cache = &wm8961->reg_cache; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8961_set_bias_level; - codec->volatile_register = wm8961_volatile_register; - - memcpy(codec->reg_cache, wm8961_reg_defaults, - sizeof(wm8961_reg_defaults)); - - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); - if (reg != 0x1801) { - dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); - ret = -EINVAL; - goto err; - } - - /* This isn't volatile - readback doesn't correspond to write */ - reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME); - dev_info(codec->dev, "WM8961 family %d revision %c\n", - (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, - ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) - + 'A'); - - ret = wm8961_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - return ret; - } - - /* Enable class W */ - reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); - reg |= WM8961_CP_DYN_PWR_MASK; - snd_soc_write(codec, WM8961_CHARGE_PUMP_B, reg); - - /* Latch volume update bits (right channel only, we always - * write both out) and default ZC on. */ - reg = snd_soc_read(codec, WM8961_ROUT1_VOLUME); - snd_soc_write(codec, WM8961_ROUT1_VOLUME, - reg | WM8961_LO1ZC | WM8961_OUT1VU); - snd_soc_write(codec, WM8961_LOUT1_VOLUME, reg | WM8961_LO1ZC); - reg = snd_soc_read(codec, WM8961_ROUT2_VOLUME); - snd_soc_write(codec, WM8961_ROUT2_VOLUME, - reg | WM8961_SPKRZC | WM8961_SPKVU); - snd_soc_write(codec, WM8961_LOUT2_VOLUME, reg | WM8961_SPKLZC); - - reg = snd_soc_read(codec, WM8961_RIGHT_ADC_VOLUME); - snd_soc_write(codec, WM8961_RIGHT_ADC_VOLUME, reg | WM8961_ADCVU); - reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); - snd_soc_write(codec, WM8961_RIGHT_INPUT_VOLUME, reg | WM8961_IPVU); - - /* Use soft mute by default */ - reg = snd_soc_read(codec, WM8961_ADC_DAC_CONTROL_2); - reg |= WM8961_DACSMM; - snd_soc_write(codec, WM8961_ADC_DAC_CONTROL_2, reg); - - /* Use automatic clocking mode by default; for now this is all - * we support. - */ - reg = snd_soc_read(codec, WM8961_CLOCKING_3); - reg &= ~WM8961_MANUAL_MODE; - snd_soc_write(codec, WM8961_CLOCKING_3, reg); - - wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - wm8961_dai.dev = codec->dev; - - wm8961_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - return ret; - } - - ret = snd_soc_register_dai(&wm8961_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - snd_soc_unregister_codec(codec); - return ret; - } - - return 0; - -err: - kfree(wm8961); - return ret; -} - -static void wm8961_unregister(struct wm8961_priv *wm8961) -{ - wm8961_set_bias_level(&wm8961->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8961_dai); - snd_soc_unregister_codec(&wm8961->codec); - kfree(wm8961); - wm8961_codec = NULL; -} - -static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8961_priv *wm8961; - struct snd_soc_codec *codec; - - wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL); - if (wm8961 == NULL) - return -ENOMEM; - - codec = &wm8961->codec; - - i2c_set_clientdata(i2c, wm8961); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - - return wm8961_register(wm8961); -} - -static __devexit int wm8961_i2c_remove(struct i2c_client *client) -{ - struct wm8961_priv *wm8961 = i2c_get_clientdata(client); - wm8961_unregister(wm8961); - return 0; -} - -#ifdef CONFIG_PM -static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8961_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8961_i2c_suspend NULL -#define wm8961_i2c_resume NULL -#endif - -static const struct i2c_device_id wm8961_i2c_id[] = { - { "wm8961", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); - -static struct i2c_driver wm8961_i2c_driver = { - .driver = { - .name = "wm8961", - .owner = THIS_MODULE, - }, - .probe = wm8961_i2c_probe, - .remove = __devexit_p(wm8961_i2c_remove), - .suspend = wm8961_i2c_suspend, - .resume = wm8961_i2c_resume, - .id_table = wm8961_i2c_id, -}; - -static int __init wm8961_modinit(void) -{ - int ret; - - ret = i2c_add_driver(&wm8961_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register WM8961 I2C driver: %d\n", - ret); - } - - return ret; -} -module_init(wm8961_modinit); - -static void __exit wm8961_exit(void) -{ - i2c_del_driver(&wm8961_i2c_driver); -} -module_exit(wm8961_exit); - - -MODULE_DESCRIPTION("ASoC WM8961 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8961.h b/trunk/sound/soc/codecs/wm8961.h deleted file mode 100644 index 5513bfd720d6..000000000000 --- a/trunk/sound/soc/codecs/wm8961.h +++ /dev/null @@ -1,866 +0,0 @@ -/* - * wm8961.h -- WM8961 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8961_H -#define _WM8961_H - -#include - -extern struct snd_soc_codec_device soc_codec_dev_wm8961; -extern struct snd_soc_dai wm8961_dai; - -#define WM8961_BCLK 1 -#define WM8961_LRCLK 2 - -#define WM8961_BCLK_DIV_1 0 -#define WM8961_BCLK_DIV_1_5 1 -#define WM8961_BCLK_DIV_2 2 -#define WM8961_BCLK_DIV_3 3 -#define WM8961_BCLK_DIV_4 4 -#define WM8961_BCLK_DIV_5_5 5 -#define WM8961_BCLK_DIV_6 6 -#define WM8961_BCLK_DIV_8 7 -#define WM8961_BCLK_DIV_11 8 -#define WM8961_BCLK_DIV_12 9 -#define WM8961_BCLK_DIV_16 10 -#define WM8961_BCLK_DIV_24 11 -#define WM8961_BCLK_DIV_32 13 - - -/* - * Register values. - */ -#define WM8961_LEFT_INPUT_VOLUME 0x00 -#define WM8961_RIGHT_INPUT_VOLUME 0x01 -#define WM8961_LOUT1_VOLUME 0x02 -#define WM8961_ROUT1_VOLUME 0x03 -#define WM8961_CLOCKING1 0x04 -#define WM8961_ADC_DAC_CONTROL_1 0x05 -#define WM8961_ADC_DAC_CONTROL_2 0x06 -#define WM8961_AUDIO_INTERFACE_0 0x07 -#define WM8961_CLOCKING2 0x08 -#define WM8961_AUDIO_INTERFACE_1 0x09 -#define WM8961_LEFT_DAC_VOLUME 0x0A -#define WM8961_RIGHT_DAC_VOLUME 0x0B -#define WM8961_AUDIO_INTERFACE_2 0x0E -#define WM8961_SOFTWARE_RESET 0x0F -#define WM8961_ALC1 0x11 -#define WM8961_ALC2 0x12 -#define WM8961_ALC3 0x13 -#define WM8961_NOISE_GATE 0x14 -#define WM8961_LEFT_ADC_VOLUME 0x15 -#define WM8961_RIGHT_ADC_VOLUME 0x16 -#define WM8961_ADDITIONAL_CONTROL_1 0x17 -#define WM8961_ADDITIONAL_CONTROL_2 0x18 -#define WM8961_PWR_MGMT_1 0x19 -#define WM8961_PWR_MGMT_2 0x1A -#define WM8961_ADDITIONAL_CONTROL_3 0x1B -#define WM8961_ANTI_POP 0x1C -#define WM8961_CLOCKING_3 0x1E -#define WM8961_ADCL_SIGNAL_PATH 0x20 -#define WM8961_ADCR_SIGNAL_PATH 0x21 -#define WM8961_LOUT2_VOLUME 0x28 -#define WM8961_ROUT2_VOLUME 0x29 -#define WM8961_PWR_MGMT_3 0x2F -#define WM8961_ADDITIONAL_CONTROL_4 0x30 -#define WM8961_CLASS_D_CONTROL_1 0x31 -#define WM8961_CLASS_D_CONTROL_2 0x33 -#define WM8961_CLOCKING_4 0x38 -#define WM8961_DSP_SIDETONE_0 0x39 -#define WM8961_DSP_SIDETONE_1 0x3A -#define WM8961_DC_SERVO_0 0x3C -#define WM8961_DC_SERVO_1 0x3D -#define WM8961_DC_SERVO_3 0x3F -#define WM8961_DC_SERVO_5 0x41 -#define WM8961_ANALOGUE_PGA_BIAS 0x44 -#define WM8961_ANALOGUE_HP_0 0x45 -#define WM8961_ANALOGUE_HP_2 0x47 -#define WM8961_CHARGE_PUMP_1 0x48 -#define WM8961_CHARGE_PUMP_B 0x52 -#define WM8961_WRITE_SEQUENCER_1 0x57 -#define WM8961_WRITE_SEQUENCER_2 0x58 -#define WM8961_WRITE_SEQUENCER_3 0x59 -#define WM8961_WRITE_SEQUENCER_4 0x5A -#define WM8961_WRITE_SEQUENCER_5 0x5B -#define WM8961_WRITE_SEQUENCER_6 0x5C -#define WM8961_WRITE_SEQUENCER_7 0x5D -#define WM8961_GENERAL_TEST_1 0xFC - - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Left Input volume - */ -#define WM8961_IPVU 0x0100 /* IPVU */ -#define WM8961_IPVU_MASK 0x0100 /* IPVU */ -#define WM8961_IPVU_SHIFT 8 /* IPVU */ -#define WM8961_IPVU_WIDTH 1 /* IPVU */ -#define WM8961_LINMUTE 0x0080 /* LINMUTE */ -#define WM8961_LINMUTE_MASK 0x0080 /* LINMUTE */ -#define WM8961_LINMUTE_SHIFT 7 /* LINMUTE */ -#define WM8961_LINMUTE_WIDTH 1 /* LINMUTE */ -#define WM8961_LIZC 0x0040 /* LIZC */ -#define WM8961_LIZC_MASK 0x0040 /* LIZC */ -#define WM8961_LIZC_SHIFT 6 /* LIZC */ -#define WM8961_LIZC_WIDTH 1 /* LIZC */ -#define WM8961_LINVOL_MASK 0x003F /* LINVOL - [5:0] */ -#define WM8961_LINVOL_SHIFT 0 /* LINVOL - [5:0] */ -#define WM8961_LINVOL_WIDTH 6 /* LINVOL - [5:0] */ - -/* - * R1 (0x01) - Right Input volume - */ -#define WM8961_DEVICE_ID_MASK 0xF000 /* DEVICE_ID - [15:12] */ -#define WM8961_DEVICE_ID_SHIFT 12 /* DEVICE_ID - [15:12] */ -#define WM8961_DEVICE_ID_WIDTH 4 /* DEVICE_ID - [15:12] */ -#define WM8961_CHIP_REV_MASK 0x0E00 /* CHIP_REV - [11:9] */ -#define WM8961_CHIP_REV_SHIFT 9 /* CHIP_REV - [11:9] */ -#define WM8961_CHIP_REV_WIDTH 3 /* CHIP_REV - [11:9] */ -#define WM8961_IPVU 0x0100 /* IPVU */ -#define WM8961_IPVU_MASK 0x0100 /* IPVU */ -#define WM8961_IPVU_SHIFT 8 /* IPVU */ -#define WM8961_IPVU_WIDTH 1 /* IPVU */ -#define WM8961_RINMUTE 0x0080 /* RINMUTE */ -#define WM8961_RINMUTE_MASK 0x0080 /* RINMUTE */ -#define WM8961_RINMUTE_SHIFT 7 /* RINMUTE */ -#define WM8961_RINMUTE_WIDTH 1 /* RINMUTE */ -#define WM8961_RIZC 0x0040 /* RIZC */ -#define WM8961_RIZC_MASK 0x0040 /* RIZC */ -#define WM8961_RIZC_SHIFT 6 /* RIZC */ -#define WM8961_RIZC_WIDTH 1 /* RIZC */ -#define WM8961_RINVOL_MASK 0x003F /* RINVOL - [5:0] */ -#define WM8961_RINVOL_SHIFT 0 /* RINVOL - [5:0] */ -#define WM8961_RINVOL_WIDTH 6 /* RINVOL - [5:0] */ - -/* - * R2 (0x02) - LOUT1 volume - */ -#define WM8961_OUT1VU 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8961_LO1ZC 0x0080 /* LO1ZC */ -#define WM8961_LO1ZC_MASK 0x0080 /* LO1ZC */ -#define WM8961_LO1ZC_SHIFT 7 /* LO1ZC */ -#define WM8961_LO1ZC_WIDTH 1 /* LO1ZC */ -#define WM8961_LOUT1VOL_MASK 0x007F /* LOUT1VOL - [6:0] */ -#define WM8961_LOUT1VOL_SHIFT 0 /* LOUT1VOL - [6:0] */ -#define WM8961_LOUT1VOL_WIDTH 7 /* LOUT1VOL - [6:0] */ - -/* - * R3 (0x03) - ROUT1 volume - */ -#define WM8961_OUT1VU 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_MASK 0x0100 /* OUT1VU */ -#define WM8961_OUT1VU_SHIFT 8 /* OUT1VU */ -#define WM8961_OUT1VU_WIDTH 1 /* OUT1VU */ -#define WM8961_RO1ZC 0x0080 /* RO1ZC */ -#define WM8961_RO1ZC_MASK 0x0080 /* RO1ZC */ -#define WM8961_RO1ZC_SHIFT 7 /* RO1ZC */ -#define WM8961_RO1ZC_WIDTH 1 /* RO1ZC */ -#define WM8961_ROUT1VOL_MASK 0x007F /* ROUT1VOL - [6:0] */ -#define WM8961_ROUT1VOL_SHIFT 0 /* ROUT1VOL - [6:0] */ -#define WM8961_ROUT1VOL_WIDTH 7 /* ROUT1VOL - [6:0] */ - -/* - * R4 (0x04) - Clocking1 - */ -#define WM8961_ADCDIV_MASK 0x01C0 /* ADCDIV - [8:6] */ -#define WM8961_ADCDIV_SHIFT 6 /* ADCDIV - [8:6] */ -#define WM8961_ADCDIV_WIDTH 3 /* ADCDIV - [8:6] */ -#define WM8961_DACDIV_MASK 0x0038 /* DACDIV - [5:3] */ -#define WM8961_DACDIV_SHIFT 3 /* DACDIV - [5:3] */ -#define WM8961_DACDIV_WIDTH 3 /* DACDIV - [5:3] */ -#define WM8961_MCLKDIV 0x0004 /* MCLKDIV */ -#define WM8961_MCLKDIV_MASK 0x0004 /* MCLKDIV */ -#define WM8961_MCLKDIV_SHIFT 2 /* MCLKDIV */ -#define WM8961_MCLKDIV_WIDTH 1 /* MCLKDIV */ - -/* - * R5 (0x05) - ADC & DAC Control 1 - */ -#define WM8961_ADCPOL_MASK 0x0060 /* ADCPOL - [6:5] */ -#define WM8961_ADCPOL_SHIFT 5 /* ADCPOL - [6:5] */ -#define WM8961_ADCPOL_WIDTH 2 /* ADCPOL - [6:5] */ -#define WM8961_DACMU 0x0008 /* DACMU */ -#define WM8961_DACMU_MASK 0x0008 /* DACMU */ -#define WM8961_DACMU_SHIFT 3 /* DACMU */ -#define WM8961_DACMU_WIDTH 1 /* DACMU */ -#define WM8961_DEEMPH_MASK 0x0006 /* DEEMPH - [2:1] */ -#define WM8961_DEEMPH_SHIFT 1 /* DEEMPH - [2:1] */ -#define WM8961_DEEMPH_WIDTH 2 /* DEEMPH - [2:1] */ -#define WM8961_ADCHPD 0x0001 /* ADCHPD */ -#define WM8961_ADCHPD_MASK 0x0001 /* ADCHPD */ -#define WM8961_ADCHPD_SHIFT 0 /* ADCHPD */ -#define WM8961_ADCHPD_WIDTH 1 /* ADCHPD */ - -/* - * R6 (0x06) - ADC & DAC Control 2 - */ -#define WM8961_ADC_HPF_CUT_MASK 0x0180 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_ADC_HPF_CUT_SHIFT 7 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [8:7] */ -#define WM8961_DACPOL_MASK 0x0060 /* DACPOL - [6:5] */ -#define WM8961_DACPOL_SHIFT 5 /* DACPOL - [6:5] */ -#define WM8961_DACPOL_WIDTH 2 /* DACPOL - [6:5] */ -#define WM8961_DACSMM 0x0008 /* DACSMM */ -#define WM8961_DACSMM_MASK 0x0008 /* DACSMM */ -#define WM8961_DACSMM_SHIFT 3 /* DACSMM */ -#define WM8961_DACSMM_WIDTH 1 /* DACSMM */ -#define WM8961_DACMR 0x0004 /* DACMR */ -#define WM8961_DACMR_MASK 0x0004 /* DACMR */ -#define WM8961_DACMR_SHIFT 2 /* DACMR */ -#define WM8961_DACMR_WIDTH 1 /* DACMR */ -#define WM8961_DACSLOPE 0x0002 /* DACSLOPE */ -#define WM8961_DACSLOPE_MASK 0x0002 /* DACSLOPE */ -#define WM8961_DACSLOPE_SHIFT 1 /* DACSLOPE */ -#define WM8961_DACSLOPE_WIDTH 1 /* DACSLOPE */ -#define WM8961_DAC_OSR128 0x0001 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */ -#define WM8961_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ - -/* - * R7 (0x07) - Audio Interface 0 - */ -#define WM8961_ALRSWAP 0x0100 /* ALRSWAP */ -#define WM8961_ALRSWAP_MASK 0x0100 /* ALRSWAP */ -#define WM8961_ALRSWAP_SHIFT 8 /* ALRSWAP */ -#define WM8961_ALRSWAP_WIDTH 1 /* ALRSWAP */ -#define WM8961_BCLKINV 0x0080 /* BCLKINV */ -#define WM8961_BCLKINV_MASK 0x0080 /* BCLKINV */ -#define WM8961_BCLKINV_SHIFT 7 /* BCLKINV */ -#define WM8961_BCLKINV_WIDTH 1 /* BCLKINV */ -#define WM8961_MS 0x0040 /* MS */ -#define WM8961_MS_MASK 0x0040 /* MS */ -#define WM8961_MS_SHIFT 6 /* MS */ -#define WM8961_MS_WIDTH 1 /* MS */ -#define WM8961_DLRSWAP 0x0020 /* DLRSWAP */ -#define WM8961_DLRSWAP_MASK 0x0020 /* DLRSWAP */ -#define WM8961_DLRSWAP_SHIFT 5 /* DLRSWAP */ -#define WM8961_DLRSWAP_WIDTH 1 /* DLRSWAP */ -#define WM8961_LRP 0x0010 /* LRP */ -#define WM8961_LRP_MASK 0x0010 /* LRP */ -#define WM8961_LRP_SHIFT 4 /* LRP */ -#define WM8961_LRP_WIDTH 1 /* LRP */ -#define WM8961_WL_MASK 0x000C /* WL - [3:2] */ -#define WM8961_WL_SHIFT 2 /* WL - [3:2] */ -#define WM8961_WL_WIDTH 2 /* WL - [3:2] */ -#define WM8961_FORMAT_MASK 0x0003 /* FORMAT - [1:0] */ -#define WM8961_FORMAT_SHIFT 0 /* FORMAT - [1:0] */ -#define WM8961_FORMAT_WIDTH 2 /* FORMAT - [1:0] */ - -/* - * R8 (0x08) - Clocking2 - */ -#define WM8961_DCLKDIV_MASK 0x01C0 /* DCLKDIV - [8:6] */ -#define WM8961_DCLKDIV_SHIFT 6 /* DCLKDIV - [8:6] */ -#define WM8961_DCLKDIV_WIDTH 3 /* DCLKDIV - [8:6] */ -#define WM8961_CLK_SYS_ENA 0x0020 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_MASK 0x0020 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_SHIFT 5 /* CLK_SYS_ENA */ -#define WM8961_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ -#define WM8961_CLK_DSP_ENA 0x0010 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_MASK 0x0010 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_SHIFT 4 /* CLK_DSP_ENA */ -#define WM8961_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ -#define WM8961_BCLKDIV_MASK 0x000F /* BCLKDIV - [3:0] */ -#define WM8961_BCLKDIV_SHIFT 0 /* BCLKDIV - [3:0] */ -#define WM8961_BCLKDIV_WIDTH 4 /* BCLKDIV - [3:0] */ - -/* - * R9 (0x09) - Audio Interface 1 - */ -#define WM8961_DACCOMP_MASK 0x0018 /* DACCOMP - [4:3] */ -#define WM8961_DACCOMP_SHIFT 3 /* DACCOMP - [4:3] */ -#define WM8961_DACCOMP_WIDTH 2 /* DACCOMP - [4:3] */ -#define WM8961_ADCCOMP_MASK 0x0006 /* ADCCOMP - [2:1] */ -#define WM8961_ADCCOMP_SHIFT 1 /* ADCCOMP - [2:1] */ -#define WM8961_ADCCOMP_WIDTH 2 /* ADCCOMP - [2:1] */ -#define WM8961_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8961_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8961_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8961_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R10 (0x0A) - Left DAC volume - */ -#define WM8961_DACVU 0x0100 /* DACVU */ -#define WM8961_DACVU_MASK 0x0100 /* DACVU */ -#define WM8961_DACVU_SHIFT 8 /* DACVU */ -#define WM8961_DACVU_WIDTH 1 /* DACVU */ -#define WM8961_LDACVOL_MASK 0x00FF /* LDACVOL - [7:0] */ -#define WM8961_LDACVOL_SHIFT 0 /* LDACVOL - [7:0] */ -#define WM8961_LDACVOL_WIDTH 8 /* LDACVOL - [7:0] */ - -/* - * R11 (0x0B) - Right DAC volume - */ -#define WM8961_DACVU 0x0100 /* DACVU */ -#define WM8961_DACVU_MASK 0x0100 /* DACVU */ -#define WM8961_DACVU_SHIFT 8 /* DACVU */ -#define WM8961_DACVU_WIDTH 1 /* DACVU */ -#define WM8961_RDACVOL_MASK 0x00FF /* RDACVOL - [7:0] */ -#define WM8961_RDACVOL_SHIFT 0 /* RDACVOL - [7:0] */ -#define WM8961_RDACVOL_WIDTH 8 /* RDACVOL - [7:0] */ - -/* - * R14 (0x0E) - Audio Interface 2 - */ -#define WM8961_LRCLK_RATE_MASK 0x01FF /* LRCLK_RATE - [8:0] */ -#define WM8961_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [8:0] */ -#define WM8961_LRCLK_RATE_WIDTH 9 /* LRCLK_RATE - [8:0] */ - -/* - * R15 (0x0F) - Software Reset - */ -#define WM8961_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */ -#define WM8961_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */ -#define WM8961_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */ - -/* - * R17 (0x11) - ALC1 - */ -#define WM8961_ALCSEL_MASK 0x0180 /* ALCSEL - [8:7] */ -#define WM8961_ALCSEL_SHIFT 7 /* ALCSEL - [8:7] */ -#define WM8961_ALCSEL_WIDTH 2 /* ALCSEL - [8:7] */ -#define WM8961_MAXGAIN_MASK 0x0070 /* MAXGAIN - [6:4] */ -#define WM8961_MAXGAIN_SHIFT 4 /* MAXGAIN - [6:4] */ -#define WM8961_MAXGAIN_WIDTH 3 /* MAXGAIN - [6:4] */ -#define WM8961_ALCL_MASK 0x000F /* ALCL - [3:0] */ -#define WM8961_ALCL_SHIFT 0 /* ALCL - [3:0] */ -#define WM8961_ALCL_WIDTH 4 /* ALCL - [3:0] */ - -/* - * R18 (0x12) - ALC2 - */ -#define WM8961_ALCZC 0x0080 /* ALCZC */ -#define WM8961_ALCZC_MASK 0x0080 /* ALCZC */ -#define WM8961_ALCZC_SHIFT 7 /* ALCZC */ -#define WM8961_ALCZC_WIDTH 1 /* ALCZC */ -#define WM8961_MINGAIN_MASK 0x0070 /* MINGAIN - [6:4] */ -#define WM8961_MINGAIN_SHIFT 4 /* MINGAIN - [6:4] */ -#define WM8961_MINGAIN_WIDTH 3 /* MINGAIN - [6:4] */ -#define WM8961_HLD_MASK 0x000F /* HLD - [3:0] */ -#define WM8961_HLD_SHIFT 0 /* HLD - [3:0] */ -#define WM8961_HLD_WIDTH 4 /* HLD - [3:0] */ - -/* - * R19 (0x13) - ALC3 - */ -#define WM8961_ALCMODE 0x0100 /* ALCMODE */ -#define WM8961_ALCMODE_MASK 0x0100 /* ALCMODE */ -#define WM8961_ALCMODE_SHIFT 8 /* ALCMODE */ -#define WM8961_ALCMODE_WIDTH 1 /* ALCMODE */ -#define WM8961_DCY_MASK 0x00F0 /* DCY - [7:4] */ -#define WM8961_DCY_SHIFT 4 /* DCY - [7:4] */ -#define WM8961_DCY_WIDTH 4 /* DCY - [7:4] */ -#define WM8961_ATK_MASK 0x000F /* ATK - [3:0] */ -#define WM8961_ATK_SHIFT 0 /* ATK - [3:0] */ -#define WM8961_ATK_WIDTH 4 /* ATK - [3:0] */ - -/* - * R20 (0x14) - Noise Gate - */ -#define WM8961_NGTH_MASK 0x00F8 /* NGTH - [7:3] */ -#define WM8961_NGTH_SHIFT 3 /* NGTH - [7:3] */ -#define WM8961_NGTH_WIDTH 5 /* NGTH - [7:3] */ -#define WM8961_NGG 0x0002 /* NGG */ -#define WM8961_NGG_MASK 0x0002 /* NGG */ -#define WM8961_NGG_SHIFT 1 /* NGG */ -#define WM8961_NGG_WIDTH 1 /* NGG */ -#define WM8961_NGAT 0x0001 /* NGAT */ -#define WM8961_NGAT_MASK 0x0001 /* NGAT */ -#define WM8961_NGAT_SHIFT 0 /* NGAT */ -#define WM8961_NGAT_WIDTH 1 /* NGAT */ - -/* - * R21 (0x15) - Left ADC volume - */ -#define WM8961_ADCVU 0x0100 /* ADCVU */ -#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8961_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8961_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8961_LADCVOL_MASK 0x00FF /* LADCVOL - [7:0] */ -#define WM8961_LADCVOL_SHIFT 0 /* LADCVOL - [7:0] */ -#define WM8961_LADCVOL_WIDTH 8 /* LADCVOL - [7:0] */ - -/* - * R22 (0x16) - Right ADC volume - */ -#define WM8961_ADCVU 0x0100 /* ADCVU */ -#define WM8961_ADCVU_MASK 0x0100 /* ADCVU */ -#define WM8961_ADCVU_SHIFT 8 /* ADCVU */ -#define WM8961_ADCVU_WIDTH 1 /* ADCVU */ -#define WM8961_RADCVOL_MASK 0x00FF /* RADCVOL - [7:0] */ -#define WM8961_RADCVOL_SHIFT 0 /* RADCVOL - [7:0] */ -#define WM8961_RADCVOL_WIDTH 8 /* RADCVOL - [7:0] */ - -/* - * R23 (0x17) - Additional control(1) - */ -#define WM8961_TSDEN 0x0100 /* TSDEN */ -#define WM8961_TSDEN_MASK 0x0100 /* TSDEN */ -#define WM8961_TSDEN_SHIFT 8 /* TSDEN */ -#define WM8961_TSDEN_WIDTH 1 /* TSDEN */ -#define WM8961_DMONOMIX 0x0010 /* DMONOMIX */ -#define WM8961_DMONOMIX_MASK 0x0010 /* DMONOMIX */ -#define WM8961_DMONOMIX_SHIFT 4 /* DMONOMIX */ -#define WM8961_DMONOMIX_WIDTH 1 /* DMONOMIX */ -#define WM8961_TOEN 0x0001 /* TOEN */ -#define WM8961_TOEN_MASK 0x0001 /* TOEN */ -#define WM8961_TOEN_SHIFT 0 /* TOEN */ -#define WM8961_TOEN_WIDTH 1 /* TOEN */ - -/* - * R24 (0x18) - Additional control(2) - */ -#define WM8961_TRIS 0x0008 /* TRIS */ -#define WM8961_TRIS_MASK 0x0008 /* TRIS */ -#define WM8961_TRIS_SHIFT 3 /* TRIS */ -#define WM8961_TRIS_WIDTH 1 /* TRIS */ - -/* - * R25 (0x19) - Pwr Mgmt (1) - */ -#define WM8961_VMIDSEL_MASK 0x0180 /* VMIDSEL - [8:7] */ -#define WM8961_VMIDSEL_SHIFT 7 /* VMIDSEL - [8:7] */ -#define WM8961_VMIDSEL_WIDTH 2 /* VMIDSEL - [8:7] */ -#define WM8961_VREF 0x0040 /* VREF */ -#define WM8961_VREF_MASK 0x0040 /* VREF */ -#define WM8961_VREF_SHIFT 6 /* VREF */ -#define WM8961_VREF_WIDTH 1 /* VREF */ -#define WM8961_AINL 0x0020 /* AINL */ -#define WM8961_AINL_MASK 0x0020 /* AINL */ -#define WM8961_AINL_SHIFT 5 /* AINL */ -#define WM8961_AINL_WIDTH 1 /* AINL */ -#define WM8961_AINR 0x0010 /* AINR */ -#define WM8961_AINR_MASK 0x0010 /* AINR */ -#define WM8961_AINR_SHIFT 4 /* AINR */ -#define WM8961_AINR_WIDTH 1 /* AINR */ -#define WM8961_ADCL 0x0008 /* ADCL */ -#define WM8961_ADCL_MASK 0x0008 /* ADCL */ -#define WM8961_ADCL_SHIFT 3 /* ADCL */ -#define WM8961_ADCL_WIDTH 1 /* ADCL */ -#define WM8961_ADCR 0x0004 /* ADCR */ -#define WM8961_ADCR_MASK 0x0004 /* ADCR */ -#define WM8961_ADCR_SHIFT 2 /* ADCR */ -#define WM8961_ADCR_WIDTH 1 /* ADCR */ -#define WM8961_MICB 0x0002 /* MICB */ -#define WM8961_MICB_MASK 0x0002 /* MICB */ -#define WM8961_MICB_SHIFT 1 /* MICB */ -#define WM8961_MICB_WIDTH 1 /* MICB */ - -/* - * R26 (0x1A) - Pwr Mgmt (2) - */ -#define WM8961_DACL 0x0100 /* DACL */ -#define WM8961_DACL_MASK 0x0100 /* DACL */ -#define WM8961_DACL_SHIFT 8 /* DACL */ -#define WM8961_DACL_WIDTH 1 /* DACL */ -#define WM8961_DACR 0x0080 /* DACR */ -#define WM8961_DACR_MASK 0x0080 /* DACR */ -#define WM8961_DACR_SHIFT 7 /* DACR */ -#define WM8961_DACR_WIDTH 1 /* DACR */ -#define WM8961_LOUT1_PGA 0x0040 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_MASK 0x0040 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_SHIFT 6 /* LOUT1_PGA */ -#define WM8961_LOUT1_PGA_WIDTH 1 /* LOUT1_PGA */ -#define WM8961_ROUT1_PGA 0x0020 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_MASK 0x0020 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_SHIFT 5 /* ROUT1_PGA */ -#define WM8961_ROUT1_PGA_WIDTH 1 /* ROUT1_PGA */ -#define WM8961_SPKL_PGA 0x0010 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_MASK 0x0010 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_SHIFT 4 /* SPKL_PGA */ -#define WM8961_SPKL_PGA_WIDTH 1 /* SPKL_PGA */ -#define WM8961_SPKR_PGA 0x0008 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_MASK 0x0008 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_SHIFT 3 /* SPKR_PGA */ -#define WM8961_SPKR_PGA_WIDTH 1 /* SPKR_PGA */ - -/* - * R27 (0x1B) - Additional Control (3) - */ -#define WM8961_SAMPLE_RATE_MASK 0x0007 /* SAMPLE_RATE - [2:0] */ -#define WM8961_SAMPLE_RATE_SHIFT 0 /* SAMPLE_RATE - [2:0] */ -#define WM8961_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [2:0] */ - -/* - * R28 (0x1C) - Anti-pop - */ -#define WM8961_BUFDCOPEN 0x0010 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_MASK 0x0010 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_SHIFT 4 /* BUFDCOPEN */ -#define WM8961_BUFDCOPEN_WIDTH 1 /* BUFDCOPEN */ -#define WM8961_BUFIOEN 0x0008 /* BUFIOEN */ -#define WM8961_BUFIOEN_MASK 0x0008 /* BUFIOEN */ -#define WM8961_BUFIOEN_SHIFT 3 /* BUFIOEN */ -#define WM8961_BUFIOEN_WIDTH 1 /* BUFIOEN */ -#define WM8961_SOFT_ST 0x0004 /* SOFT_ST */ -#define WM8961_SOFT_ST_MASK 0x0004 /* SOFT_ST */ -#define WM8961_SOFT_ST_SHIFT 2 /* SOFT_ST */ -#define WM8961_SOFT_ST_WIDTH 1 /* SOFT_ST */ - -/* - * R30 (0x1E) - Clocking 3 - */ -#define WM8961_CLK_TO_DIV_MASK 0x0180 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_TO_DIV_SHIFT 7 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_TO_DIV_WIDTH 2 /* CLK_TO_DIV - [8:7] */ -#define WM8961_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */ -#define WM8961_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */ -#define WM8961_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */ -#define WM8961_MANUAL_MODE 0x0001 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_MASK 0x0001 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_SHIFT 0 /* MANUAL_MODE */ -#define WM8961_MANUAL_MODE_WIDTH 1 /* MANUAL_MODE */ - -/* - * R32 (0x20) - ADCL signal path - */ -#define WM8961_LMICBOOST_MASK 0x0030 /* LMICBOOST - [5:4] */ -#define WM8961_LMICBOOST_SHIFT 4 /* LMICBOOST - [5:4] */ -#define WM8961_LMICBOOST_WIDTH 2 /* LMICBOOST - [5:4] */ - -/* - * R33 (0x21) - ADCR signal path - */ -#define WM8961_RMICBOOST_MASK 0x0030 /* RMICBOOST - [5:4] */ -#define WM8961_RMICBOOST_SHIFT 4 /* RMICBOOST - [5:4] */ -#define WM8961_RMICBOOST_WIDTH 2 /* RMICBOOST - [5:4] */ - -/* - * R40 (0x28) - LOUT2 volume - */ -#define WM8961_SPKVU 0x0100 /* SPKVU */ -#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */ -#define WM8961_SPKVU_SHIFT 8 /* SPKVU */ -#define WM8961_SPKVU_WIDTH 1 /* SPKVU */ -#define WM8961_SPKLZC 0x0080 /* SPKLZC */ -#define WM8961_SPKLZC_MASK 0x0080 /* SPKLZC */ -#define WM8961_SPKLZC_SHIFT 7 /* SPKLZC */ -#define WM8961_SPKLZC_WIDTH 1 /* SPKLZC */ -#define WM8961_SPKLVOL_MASK 0x007F /* SPKLVOL - [6:0] */ -#define WM8961_SPKLVOL_SHIFT 0 /* SPKLVOL - [6:0] */ -#define WM8961_SPKLVOL_WIDTH 7 /* SPKLVOL - [6:0] */ - -/* - * R41 (0x29) - ROUT2 volume - */ -#define WM8961_SPKVU 0x0100 /* SPKVU */ -#define WM8961_SPKVU_MASK 0x0100 /* SPKVU */ -#define WM8961_SPKVU_SHIFT 8 /* SPKVU */ -#define WM8961_SPKVU_WIDTH 1 /* SPKVU */ -#define WM8961_SPKRZC 0x0080 /* SPKRZC */ -#define WM8961_SPKRZC_MASK 0x0080 /* SPKRZC */ -#define WM8961_SPKRZC_SHIFT 7 /* SPKRZC */ -#define WM8961_SPKRZC_WIDTH 1 /* SPKRZC */ -#define WM8961_SPKRVOL_MASK 0x007F /* SPKRVOL - [6:0] */ -#define WM8961_SPKRVOL_SHIFT 0 /* SPKRVOL - [6:0] */ -#define WM8961_SPKRVOL_WIDTH 7 /* SPKRVOL - [6:0] */ - -/* - * R47 (0x2F) - Pwr Mgmt (3) - */ -#define WM8961_TEMP_SHUT 0x0002 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_MASK 0x0002 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_SHIFT 1 /* TEMP_SHUT */ -#define WM8961_TEMP_SHUT_WIDTH 1 /* TEMP_SHUT */ -#define WM8961_TEMP_WARN 0x0001 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_MASK 0x0001 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_SHIFT 0 /* TEMP_WARN */ -#define WM8961_TEMP_WARN_WIDTH 1 /* TEMP_WARN */ - -/* - * R48 (0x30) - Additional Control (4) - */ -#define WM8961_TSENSEN 0x0002 /* TSENSEN */ -#define WM8961_TSENSEN_MASK 0x0002 /* TSENSEN */ -#define WM8961_TSENSEN_SHIFT 1 /* TSENSEN */ -#define WM8961_TSENSEN_WIDTH 1 /* TSENSEN */ -#define WM8961_MBSEL 0x0001 /* MBSEL */ -#define WM8961_MBSEL_MASK 0x0001 /* MBSEL */ -#define WM8961_MBSEL_SHIFT 0 /* MBSEL */ -#define WM8961_MBSEL_WIDTH 1 /* MBSEL */ - -/* - * R49 (0x31) - Class D Control 1 - */ -#define WM8961_SPKR_ENA 0x0080 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_MASK 0x0080 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_SHIFT 7 /* SPKR_ENA */ -#define WM8961_SPKR_ENA_WIDTH 1 /* SPKR_ENA */ -#define WM8961_SPKL_ENA 0x0040 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_MASK 0x0040 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_SHIFT 6 /* SPKL_ENA */ -#define WM8961_SPKL_ENA_WIDTH 1 /* SPKL_ENA */ - -/* - * R51 (0x33) - Class D Control 2 - */ -#define WM8961_CLASSD_ACGAIN_MASK 0x0007 /* CLASSD_ACGAIN - [2:0] */ -#define WM8961_CLASSD_ACGAIN_SHIFT 0 /* CLASSD_ACGAIN - [2:0] */ -#define WM8961_CLASSD_ACGAIN_WIDTH 3 /* CLASSD_ACGAIN - [2:0] */ - -/* - * R56 (0x38) - Clocking 4 - */ -#define WM8961_CLK_DCS_DIV_MASK 0x01E0 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_DCS_DIV_SHIFT 5 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [8:5] */ -#define WM8961_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */ -#define WM8961_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */ -#define WM8961_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */ - -/* - * R57 (0x39) - DSP Sidetone 0 - */ -#define WM8961_ADCR_DAC_SVOL_MASK 0x00F0 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADCR_DAC_SVOL_SHIFT 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [7:4] */ -#define WM8961_ADC_TO_DACR_MASK 0x000C /* ADC_TO_DACR - [3:2] */ -#define WM8961_ADC_TO_DACR_SHIFT 2 /* ADC_TO_DACR - [3:2] */ -#define WM8961_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [3:2] */ - -/* - * R58 (0x3A) - DSP Sidetone 1 - */ -#define WM8961_ADCL_DAC_SVOL_MASK 0x00F0 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADCL_DAC_SVOL_SHIFT 4 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [7:4] */ -#define WM8961_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8961_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8961_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ - -/* - * R60 (0x3C) - DC Servo 0 - */ -#define WM8961_DCS_ENA_CHAN_INL 0x0080 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_MASK 0x0080 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_SHIFT 7 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_ENA_CHAN_INL_WIDTH 1 /* DCS_ENA_CHAN_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL 0x0040 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_MASK 0x0040 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_SHIFT 6 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_STARTUP_INL_WIDTH 1 /* DCS_TRIG_STARTUP_INL */ -#define WM8961_DCS_TRIG_SERIES_INL 0x0010 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_MASK 0x0010 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_SHIFT 4 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_TRIG_SERIES_INL_WIDTH 1 /* DCS_TRIG_SERIES_INL */ -#define WM8961_DCS_ENA_CHAN_INR 0x0008 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_MASK 0x0008 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_SHIFT 3 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_ENA_CHAN_INR_WIDTH 1 /* DCS_ENA_CHAN_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR 0x0004 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_MASK 0x0004 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_SHIFT 2 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_STARTUP_INR_WIDTH 1 /* DCS_TRIG_STARTUP_INR */ -#define WM8961_DCS_TRIG_SERIES_INR 0x0001 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_MASK 0x0001 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_SHIFT 0 /* DCS_TRIG_SERIES_INR */ -#define WM8961_DCS_TRIG_SERIES_INR_WIDTH 1 /* DCS_TRIG_SERIES_INR */ - -/* - * R61 (0x3D) - DC Servo 1 - */ -#define WM8961_DCS_ENA_CHAN_HPL 0x0080 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_MASK 0x0080 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_SHIFT 7 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_ENA_CHAN_HPL_WIDTH 1 /* DCS_ENA_CHAN_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL 0x0040 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_MASK 0x0040 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_SHIFT 6 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_STARTUP_HPL_WIDTH 1 /* DCS_TRIG_STARTUP_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL 0x0010 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_MASK 0x0010 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_SHIFT 4 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_TRIG_SERIES_HPL_WIDTH 1 /* DCS_TRIG_SERIES_HPL */ -#define WM8961_DCS_ENA_CHAN_HPR 0x0008 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_MASK 0x0008 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_SHIFT 3 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_ENA_CHAN_HPR_WIDTH 1 /* DCS_ENA_CHAN_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR 0x0004 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_MASK 0x0004 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_SHIFT 2 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_STARTUP_HPR_WIDTH 1 /* DCS_TRIG_STARTUP_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR 0x0001 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_MASK 0x0001 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_SHIFT 0 /* DCS_TRIG_SERIES_HPR */ -#define WM8961_DCS_TRIG_SERIES_HPR_WIDTH 1 /* DCS_TRIG_SERIES_HPR */ - -/* - * R63 (0x3F) - DC Servo 3 - */ -#define WM8961_DCS_FILT_BW_SERIES_MASK 0x0030 /* DCS_FILT_BW_SERIES - [5:4] */ -#define WM8961_DCS_FILT_BW_SERIES_SHIFT 4 /* DCS_FILT_BW_SERIES - [5:4] */ -#define WM8961_DCS_FILT_BW_SERIES_WIDTH 2 /* DCS_FILT_BW_SERIES - [5:4] */ - -/* - * R65 (0x41) - DC Servo 5 - */ -#define WM8961_DCS_SERIES_NO_HP_MASK 0x007F /* DCS_SERIES_NO_HP - [6:0] */ -#define WM8961_DCS_SERIES_NO_HP_SHIFT 0 /* DCS_SERIES_NO_HP - [6:0] */ -#define WM8961_DCS_SERIES_NO_HP_WIDTH 7 /* DCS_SERIES_NO_HP - [6:0] */ - -/* - * R68 (0x44) - Analogue PGA Bias - */ -#define WM8961_HP_PGAS_BIAS_MASK 0x0007 /* HP_PGAS_BIAS - [2:0] */ -#define WM8961_HP_PGAS_BIAS_SHIFT 0 /* HP_PGAS_BIAS - [2:0] */ -#define WM8961_HP_PGAS_BIAS_WIDTH 3 /* HP_PGAS_BIAS - [2:0] */ - -/* - * R69 (0x45) - Analogue HP 0 - */ -#define WM8961_HPL_RMV_SHORT 0x0080 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_MASK 0x0080 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_SHIFT 7 /* HPL_RMV_SHORT */ -#define WM8961_HPL_RMV_SHORT_WIDTH 1 /* HPL_RMV_SHORT */ -#define WM8961_HPL_ENA_OUTP 0x0040 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_MASK 0x0040 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_SHIFT 6 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_OUTP_WIDTH 1 /* HPL_ENA_OUTP */ -#define WM8961_HPL_ENA_DLY 0x0020 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_MASK 0x0020 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_SHIFT 5 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA_DLY_WIDTH 1 /* HPL_ENA_DLY */ -#define WM8961_HPL_ENA 0x0010 /* HPL_ENA */ -#define WM8961_HPL_ENA_MASK 0x0010 /* HPL_ENA */ -#define WM8961_HPL_ENA_SHIFT 4 /* HPL_ENA */ -#define WM8961_HPL_ENA_WIDTH 1 /* HPL_ENA */ -#define WM8961_HPR_RMV_SHORT 0x0008 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_MASK 0x0008 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_SHIFT 3 /* HPR_RMV_SHORT */ -#define WM8961_HPR_RMV_SHORT_WIDTH 1 /* HPR_RMV_SHORT */ -#define WM8961_HPR_ENA_OUTP 0x0004 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_MASK 0x0004 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_SHIFT 2 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_OUTP_WIDTH 1 /* HPR_ENA_OUTP */ -#define WM8961_HPR_ENA_DLY 0x0002 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_MASK 0x0002 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_SHIFT 1 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA_DLY_WIDTH 1 /* HPR_ENA_DLY */ -#define WM8961_HPR_ENA 0x0001 /* HPR_ENA */ -#define WM8961_HPR_ENA_MASK 0x0001 /* HPR_ENA */ -#define WM8961_HPR_ENA_SHIFT 0 /* HPR_ENA */ -#define WM8961_HPR_ENA_WIDTH 1 /* HPR_ENA */ - -/* - * R71 (0x47) - Analogue HP 2 - */ -#define WM8961_HPL_VOL_MASK 0x01C0 /* HPL_VOL - [8:6] */ -#define WM8961_HPL_VOL_SHIFT 6 /* HPL_VOL - [8:6] */ -#define WM8961_HPL_VOL_WIDTH 3 /* HPL_VOL - [8:6] */ -#define WM8961_HPR_VOL_MASK 0x0038 /* HPR_VOL - [5:3] */ -#define WM8961_HPR_VOL_SHIFT 3 /* HPR_VOL - [5:3] */ -#define WM8961_HPR_VOL_WIDTH 3 /* HPR_VOL - [5:3] */ -#define WM8961_HP_BIAS_BOOST_MASK 0x0007 /* HP_BIAS_BOOST - [2:0] */ -#define WM8961_HP_BIAS_BOOST_SHIFT 0 /* HP_BIAS_BOOST - [2:0] */ -#define WM8961_HP_BIAS_BOOST_WIDTH 3 /* HP_BIAS_BOOST - [2:0] */ - -/* - * R72 (0x48) - Charge Pump 1 - */ -#define WM8961_CP_ENA 0x0001 /* CP_ENA */ -#define WM8961_CP_ENA_MASK 0x0001 /* CP_ENA */ -#define WM8961_CP_ENA_SHIFT 0 /* CP_ENA */ -#define WM8961_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R82 (0x52) - Charge Pump B - */ -#define WM8961_CP_DYN_PWR_MASK 0x0003 /* CP_DYN_PWR - [1:0] */ -#define WM8961_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR - [1:0] */ -#define WM8961_CP_DYN_PWR_WIDTH 2 /* CP_DYN_PWR - [1:0] */ - -/* - * R87 (0x57) - Write Sequencer 1 - */ -#define WM8961_WSEQ_ENA 0x0020 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_MASK 0x0020 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_SHIFT 5 /* WSEQ_ENA */ -#define WM8961_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8961_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8961_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8961_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ - -/* - * R88 (0x58) - Write Sequencer 2 - */ -#define WM8961_WSEQ_EOS 0x0100 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_MASK 0x0100 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_SHIFT 8 /* WSEQ_EOS */ -#define WM8961_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM8961_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM8961_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM8961_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R89 (0x59) - Write Sequencer 3 - */ -#define WM8961_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM8961_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM8961_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R90 (0x5A) - Write Sequencer 4 - */ -#define WM8961_WSEQ_ABORT 0x0100 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_MASK 0x0100 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_SHIFT 8 /* WSEQ_ABORT */ -#define WM8961_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8961_WSEQ_START 0x0080 /* WSEQ_START */ -#define WM8961_WSEQ_START_MASK 0x0080 /* WSEQ_START */ -#define WM8961_WSEQ_START_SHIFT 7 /* WSEQ_START */ -#define WM8961_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8961_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM8961_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM8961_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R91 (0x5B) - Write Sequencer 5 - */ -#define WM8961_WSEQ_DATA_WIDTH_MASK 0x0070 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_WIDTH_SHIFT 4 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [6:4] */ -#define WM8961_WSEQ_DATA_START_MASK 0x000F /* WSEQ_DATA_START - [3:0] */ -#define WM8961_WSEQ_DATA_START_SHIFT 0 /* WSEQ_DATA_START - [3:0] */ -#define WM8961_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [3:0] */ - -/* - * R92 (0x5C) - Write Sequencer 6 - */ -#define WM8961_WSEQ_DELAY_MASK 0x000F /* WSEQ_DELAY - [3:0] */ -#define WM8961_WSEQ_DELAY_SHIFT 0 /* WSEQ_DELAY - [3:0] */ -#define WM8961_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [3:0] */ - -/* - * R93 (0x5D) - Write Sequencer 7 - */ -#define WM8961_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8961_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R252 (0xFC) - General test 1 - */ -#define WM8961_ARA_ENA 0x0002 /* ARA_ENA */ -#define WM8961_ARA_ENA_MASK 0x0002 /* ARA_ENA */ -#define WM8961_ARA_ENA_SHIFT 1 /* ARA_ENA */ -#define WM8961_ARA_ENA_WIDTH 1 /* ARA_ENA */ -#define WM8961_AUTO_INC 0x0001 /* AUTO_INC */ -#define WM8961_AUTO_INC_MASK 0x0001 /* AUTO_INC */ -#define WM8961_AUTO_INC_SHIFT 0 /* AUTO_INC */ -#define WM8961_AUTO_INC_WIDTH 1 /* AUTO_INC */ - -#endif diff --git a/trunk/sound/soc/codecs/wm8971.c b/trunk/sound/soc/codecs/wm8971.c index d66efb0546ea..032dca22dbd3 100644 --- a/trunk/sound/soc/codecs/wm8971.c +++ b/trunk/sound/soc/codecs/wm8971.c @@ -59,7 +59,44 @@ static const u16 wm8971_reg[] = { 0x0079, 0x0079, 0x0079, /* 40 */ }; -#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0) +static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg < WM8971_REG_COUNT) + return cache[reg]; + + return -1; +} + +static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg < WM8971_REG_COUNT) + cache[reg] = value; +} + +static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + /* data is + * D15..D9 WM8753 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8971_write_reg_cache (codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0) /* WM8971 Controls */ static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; @@ -484,7 +521,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8971_IFACE, iface); + wm8971_write(codec, WM8971_IFACE, iface); return 0; } @@ -496,8 +533,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct wm8971_priv *wm8971 = codec->private_data; - u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3; - u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0; + u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; + u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; int coeff = get_coeff(wm8971->sysclk, params_rate(params)); /* bit size */ @@ -516,9 +553,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, } /* set iface & srate */ - snd_soc_write(codec, WM8971_IFACE, iface); + wm8971_write(codec, WM8971_IFACE, iface); if (coeff >= 0) - snd_soc_write(codec, WM8971_SRATE, srate | + wm8971_write(codec, WM8971_SRATE, srate | (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); return 0; @@ -527,33 +564,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, static int wm8971_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7; + u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7; if (mute) - snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8); + wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8); else - snd_soc_write(codec, WM8971_ADCDAC, mute_reg); + wm8971_write(codec, WM8971_ADCDAC, mute_reg); return 0; } static int wm8971_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; + u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; switch (level) { case SND_SOC_BIAS_ON: /* set vmid to 50k and unmute dac */ - snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); + wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* mute dac and set vmid to 500k, enable VREF */ - snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); + wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140); break; case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8971_PWR1, 0x0001); + wm8971_write(codec, WM8971_PWR1, 0x0001); break; } codec->bias_level = level; @@ -630,8 +667,8 @@ static int wm8971_resume(struct platform_device *pdev) /* charge wm8971 caps */ if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { - reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; - snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); + reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; + wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); codec->bias_level = SND_SOC_BIAS_ON; queue_delayed_work(wm8971_workq, &codec->delayed_work, msecs_to_jiffies(1000)); @@ -640,14 +677,15 @@ static int wm8971_resume(struct platform_device *pdev) return 0; } -static int wm8971_init(struct snd_soc_device *socdev, - enum snd_soc_control_type control) +static int wm8971_init(struct snd_soc_device *socdev) { struct snd_soc_codec *codec = socdev->card->codec; int reg, ret = 0; codec->name = "WM8971"; codec->owner = THIS_MODULE; + codec->read = wm8971_read_reg_cache; + codec->write = wm8971_write; codec->set_bias_level = wm8971_set_bias_level; codec->dai = &wm8971_dai; codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); @@ -657,48 +695,42 @@ static int wm8971_init(struct snd_soc_device *socdev, if (codec->reg_cache == NULL) return -ENOMEM; - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); - goto err; - } - wm8971_reset(codec); /* register pcms */ ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { printk(KERN_ERR "wm8971: failed to create pcms\n"); - goto err; + goto pcm_err; } /* charge output caps - set vmid to 5k for quick power up */ - reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; - snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); + reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; + wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); codec->bias_level = SND_SOC_BIAS_STANDBY; queue_delayed_work(wm8971_workq, &codec->delayed_work, msecs_to_jiffies(1000)); /* set the update bits */ - reg = snd_soc_read(codec, WM8971_LDAC); - snd_soc_write(codec, WM8971_LDAC, reg | 0x0100); - reg = snd_soc_read(codec, WM8971_RDAC); - snd_soc_write(codec, WM8971_RDAC, reg | 0x0100); - - reg = snd_soc_read(codec, WM8971_LOUT1V); - snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8971_ROUT1V); - snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100); - - reg = snd_soc_read(codec, WM8971_LOUT2V); - snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100); - reg = snd_soc_read(codec, WM8971_ROUT2V); - snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100); - - reg = snd_soc_read(codec, WM8971_LINVOL); - snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100); - reg = snd_soc_read(codec, WM8971_RINVOL); - snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100); + reg = wm8971_read_reg_cache(codec, WM8971_LDAC); + wm8971_write(codec, WM8971_LDAC, reg | 0x0100); + reg = wm8971_read_reg_cache(codec, WM8971_RDAC); + wm8971_write(codec, WM8971_RDAC, reg | 0x0100); + + reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V); + wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100); + reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V); + wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100); + + reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V); + wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100); + reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V); + wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100); + + reg = wm8971_read_reg_cache(codec, WM8971_LINVOL); + wm8971_write(codec, WM8971_LINVOL, reg | 0x0100); + reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); + wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); snd_soc_add_controls(codec, wm8971_snd_controls, ARRAY_SIZE(wm8971_snd_controls)); @@ -713,7 +745,7 @@ static int wm8971_init(struct snd_soc_device *socdev, card_err: snd_soc_free_pcms(socdev); snd_soc_dapm_free(socdev); -err: +pcm_err: kfree(codec->reg_cache); return ret; } @@ -735,7 +767,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, codec->control_data = i2c; - ret = wm8971_init(socdev, SND_SOC_I2C); + ret = wm8971_init(socdev); if (ret < 0) pr_err("failed to initialise WM8971\n"); @@ -845,6 +877,7 @@ static int wm8971_probe(struct platform_device *pdev) #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) if (setup->i2c_address) { + codec->hw_write = (hw_write_t)i2c_master_send; ret = wm8971_add_i2c_device(pdev, setup); } #endif diff --git a/trunk/sound/soc/codecs/wm8974.c b/trunk/sound/soc/codecs/wm8974.c deleted file mode 100644 index d8a013ab3177..000000000000 --- a/trunk/sound/soc/codecs/wm8974.c +++ /dev/null @@ -1,808 +0,0 @@ -/* - * wm8974.c -- WM8974 ALSA Soc Audio driver - * - * Copyright 2006-2009 Wolfson Microelectronics PLC. - * - * Author: Liam Girdwood - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8974.h" - -static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0050, 0x0000, 0x0140, 0x0000, - 0x0000, 0x0000, 0x0000, 0x00ff, - 0x0000, 0x0000, 0x0100, 0x00ff, - 0x0000, 0x0000, 0x012c, 0x002c, - 0x002c, 0x002c, 0x002c, 0x0000, - 0x0032, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0038, 0x000b, 0x0032, 0x0000, - 0x0008, 0x000c, 0x0093, 0x00e9, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0003, 0x0010, 0x0000, 0x0000, - 0x0000, 0x0002, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0039, 0x0000, - 0x0000, -}; - -#define WM8974_POWER1_BIASEN 0x08 -#define WM8974_POWER1_BUFIOEN 0x10 - -struct wm8974_priv { - struct snd_soc_codec codec; - u16 reg_cache[WM8974_CACHEREGNUM]; -}; - -static struct snd_soc_codec *wm8974_codec; - -#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0) - -static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" }; -static const char *wm8974_deemp[] = {"None", "32kHz", "44.1kHz", "48kHz" }; -static const char *wm8974_eqmode[] = {"Capture", "Playback" }; -static const char *wm8974_bw[] = {"Narrow", "Wide" }; -static const char *wm8974_eq1[] = {"80Hz", "105Hz", "135Hz", "175Hz" }; -static const char *wm8974_eq2[] = {"230Hz", "300Hz", "385Hz", "500Hz" }; -static const char *wm8974_eq3[] = {"650Hz", "850Hz", "1.1kHz", "1.4kHz" }; -static const char *wm8974_eq4[] = {"1.8kHz", "2.4kHz", "3.2kHz", "4.1kHz" }; -static const char *wm8974_eq5[] = {"5.3kHz", "6.9kHz", "9kHz", "11.7kHz" }; -static const char *wm8974_alc[] = {"ALC", "Limiter" }; - -static const struct soc_enum wm8974_enum[] = { - SOC_ENUM_SINGLE(WM8974_COMP, 1, 4, wm8974_companding), /* adc */ - SOC_ENUM_SINGLE(WM8974_COMP, 3, 4, wm8974_companding), /* dac */ - SOC_ENUM_SINGLE(WM8974_DAC, 4, 4, wm8974_deemp), - SOC_ENUM_SINGLE(WM8974_EQ1, 8, 2, wm8974_eqmode), - - SOC_ENUM_SINGLE(WM8974_EQ1, 5, 4, wm8974_eq1), - SOC_ENUM_SINGLE(WM8974_EQ2, 8, 2, wm8974_bw), - SOC_ENUM_SINGLE(WM8974_EQ2, 5, 4, wm8974_eq2), - SOC_ENUM_SINGLE(WM8974_EQ3, 8, 2, wm8974_bw), - - SOC_ENUM_SINGLE(WM8974_EQ3, 5, 4, wm8974_eq3), - SOC_ENUM_SINGLE(WM8974_EQ4, 8, 2, wm8974_bw), - SOC_ENUM_SINGLE(WM8974_EQ4, 5, 4, wm8974_eq4), - SOC_ENUM_SINGLE(WM8974_EQ5, 8, 2, wm8974_bw), - - SOC_ENUM_SINGLE(WM8974_EQ5, 5, 4, wm8974_eq5), - SOC_ENUM_SINGLE(WM8974_ALC3, 8, 2, wm8974_alc), -}; - -static const char *wm8974_auxmode_text[] = { "Buffer", "Mixer" }; - -static const struct soc_enum wm8974_auxmode = - SOC_ENUM_SINGLE(WM8974_INPUT, 3, 2, wm8974_auxmode_text); - -static const DECLARE_TLV_DB_SCALE(digital_tlv, -12750, 50, 1); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1200, 75, 0); -static const DECLARE_TLV_DB_SCALE(spk_tlv, -5700, 100, 0); - -static const struct snd_kcontrol_new wm8974_snd_controls[] = { - -SOC_SINGLE("Digital Loopback Switch", WM8974_COMP, 0, 1, 0), - -SOC_ENUM("DAC Companding", wm8974_enum[1]), -SOC_ENUM("ADC Companding", wm8974_enum[0]), - -SOC_ENUM("Playback De-emphasis", wm8974_enum[2]), -SOC_SINGLE("DAC Inversion Switch", WM8974_DAC, 0, 1, 0), - -SOC_SINGLE_TLV("PCM Volume", WM8974_DACVOL, 0, 255, 0, digital_tlv), - -SOC_SINGLE("High Pass Filter Switch", WM8974_ADC, 8, 1, 0), -SOC_SINGLE("High Pass Cut Off", WM8974_ADC, 4, 7, 0), -SOC_SINGLE("ADC Inversion Switch", WM8974_ADC, 0, 1, 0), - -SOC_SINGLE_TLV("Capture Volume", WM8974_ADCVOL, 0, 255, 0, digital_tlv), - -SOC_ENUM("Equaliser Function", wm8974_enum[3]), -SOC_ENUM("EQ1 Cut Off", wm8974_enum[4]), -SOC_SINGLE_TLV("EQ1 Volume", WM8974_EQ1, 0, 24, 1, eq_tlv), - -SOC_ENUM("Equaliser EQ2 Bandwith", wm8974_enum[5]), -SOC_ENUM("EQ2 Cut Off", wm8974_enum[6]), -SOC_SINGLE_TLV("EQ2 Volume", WM8974_EQ2, 0, 24, 1, eq_tlv), - -SOC_ENUM("Equaliser EQ3 Bandwith", wm8974_enum[7]), -SOC_ENUM("EQ3 Cut Off", wm8974_enum[8]), -SOC_SINGLE_TLV("EQ3 Volume", WM8974_EQ3, 0, 24, 1, eq_tlv), - -SOC_ENUM("Equaliser EQ4 Bandwith", wm8974_enum[9]), -SOC_ENUM("EQ4 Cut Off", wm8974_enum[10]), -SOC_SINGLE_TLV("EQ4 Volume", WM8974_EQ4, 0, 24, 1, eq_tlv), - -SOC_ENUM("Equaliser EQ5 Bandwith", wm8974_enum[11]), -SOC_ENUM("EQ5 Cut Off", wm8974_enum[12]), -SOC_SINGLE_TLV("EQ5 Volume", WM8974_EQ5, 0, 24, 1, eq_tlv), - -SOC_SINGLE("DAC Playback Limiter Switch", WM8974_DACLIM1, 8, 1, 0), -SOC_SINGLE("DAC Playback Limiter Decay", WM8974_DACLIM1, 4, 15, 0), -SOC_SINGLE("DAC Playback Limiter Attack", WM8974_DACLIM1, 0, 15, 0), - -SOC_SINGLE("DAC Playback Limiter Threshold", WM8974_DACLIM2, 4, 7, 0), -SOC_SINGLE("DAC Playback Limiter Boost", WM8974_DACLIM2, 0, 15, 0), - -SOC_SINGLE("ALC Enable Switch", WM8974_ALC1, 8, 1, 0), -SOC_SINGLE("ALC Capture Max Gain", WM8974_ALC1, 3, 7, 0), -SOC_SINGLE("ALC Capture Min Gain", WM8974_ALC1, 0, 7, 0), - -SOC_SINGLE("ALC Capture ZC Switch", WM8974_ALC2, 8, 1, 0), -SOC_SINGLE("ALC Capture Hold", WM8974_ALC2, 4, 7, 0), -SOC_SINGLE("ALC Capture Target", WM8974_ALC2, 0, 15, 0), - -SOC_ENUM("ALC Capture Mode", wm8974_enum[13]), -SOC_SINGLE("ALC Capture Decay", WM8974_ALC3, 4, 15, 0), -SOC_SINGLE("ALC Capture Attack", WM8974_ALC3, 0, 15, 0), - -SOC_SINGLE("ALC Capture Noise Gate Switch", WM8974_NGATE, 3, 1, 0), -SOC_SINGLE("ALC Capture Noise Gate Threshold", WM8974_NGATE, 0, 7, 0), - -SOC_SINGLE("Capture PGA ZC Switch", WM8974_INPPGA, 7, 1, 0), -SOC_SINGLE_TLV("Capture PGA Volume", WM8974_INPPGA, 0, 63, 0, inpga_tlv), - -SOC_SINGLE("Speaker Playback ZC Switch", WM8974_SPKVOL, 7, 1, 0), -SOC_SINGLE("Speaker Playback Switch", WM8974_SPKVOL, 6, 1, 1), -SOC_SINGLE_TLV("Speaker Playback Volume", WM8974_SPKVOL, 0, 63, 0, spk_tlv), - -SOC_ENUM("Aux Mode", wm8974_auxmode), - -SOC_SINGLE("Capture Boost(+20dB)", WM8974_ADCBOOST, 8, 1, 0), -SOC_SINGLE("Mono Playback Switch", WM8974_MONOMIX, 6, 1, 1), -}; - -/* Speaker Output Mixer */ -static const struct snd_kcontrol_new wm8974_speaker_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_SPKMIX, 1, 1, 0), -SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_SPKMIX, 5, 1, 0), -SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_SPKMIX, 0, 1, 1), -}; - -/* Mono Output Mixer */ -static const struct snd_kcontrol_new wm8974_mono_mixer_controls[] = { -SOC_DAPM_SINGLE("Line Bypass Switch", WM8974_MONOMIX, 1, 1, 0), -SOC_DAPM_SINGLE("Aux Playback Switch", WM8974_MONOMIX, 2, 1, 0), -SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_MONOMIX, 0, 1, 0), -}; - -/* Boost mixer */ -static const struct snd_kcontrol_new wm8974_boost_mixer[] = { -SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 0), -}; - -/* Input PGA */ -static const struct snd_kcontrol_new wm8974_inpga[] = { -SOC_DAPM_SINGLE("Aux Switch", WM8974_INPUT, 2, 1, 0), -SOC_DAPM_SINGLE("MicN Switch", WM8974_INPUT, 1, 1, 0), -SOC_DAPM_SINGLE("MicP Switch", WM8974_INPUT, 0, 1, 0), -}; - -/* AUX Input boost vol */ -static const struct snd_kcontrol_new wm8974_aux_boost_controls = -SOC_DAPM_SINGLE("Aux Volume", WM8974_ADCBOOST, 0, 7, 0); - -/* Mic Input boost vol */ -static const struct snd_kcontrol_new wm8974_mic_boost_controls = -SOC_DAPM_SINGLE("Mic Volume", WM8974_ADCBOOST, 4, 7, 0); - -static const struct snd_soc_dapm_widget wm8974_dapm_widgets[] = { -SND_SOC_DAPM_MIXER("Speaker Mixer", WM8974_POWER3, 2, 0, - &wm8974_speaker_mixer_controls[0], - ARRAY_SIZE(wm8974_speaker_mixer_controls)), -SND_SOC_DAPM_MIXER("Mono Mixer", WM8974_POWER3, 3, 0, - &wm8974_mono_mixer_controls[0], - ARRAY_SIZE(wm8974_mono_mixer_controls)), -SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8974_POWER3, 0, 0), -SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8974_POWER2, 0, 0), -SND_SOC_DAPM_PGA("Aux Input", WM8974_POWER1, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("SpkN Out", WM8974_POWER3, 5, 0, NULL, 0), -SND_SOC_DAPM_PGA("SpkP Out", WM8974_POWER3, 6, 0, NULL, 0), -SND_SOC_DAPM_PGA("Mono Out", WM8974_POWER3, 7, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("Input PGA", WM8974_POWER2, 2, 0, wm8974_inpga, - ARRAY_SIZE(wm8974_inpga)), -SND_SOC_DAPM_MIXER("Boost Mixer", WM8974_POWER2, 4, 0, - wm8974_boost_mixer, ARRAY_SIZE(wm8974_boost_mixer)), - -SND_SOC_DAPM_MICBIAS("Mic Bias", WM8974_POWER1, 4, 0), - -SND_SOC_DAPM_INPUT("MICN"), -SND_SOC_DAPM_INPUT("MICP"), -SND_SOC_DAPM_INPUT("AUX"), -SND_SOC_DAPM_OUTPUT("MONOOUT"), -SND_SOC_DAPM_OUTPUT("SPKOUTP"), -SND_SOC_DAPM_OUTPUT("SPKOUTN"), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* Mono output mixer */ - {"Mono Mixer", "PCM Playback Switch", "DAC"}, - {"Mono Mixer", "Aux Playback Switch", "Aux Input"}, - {"Mono Mixer", "Line Bypass Switch", "Boost Mixer"}, - - /* Speaker output mixer */ - {"Speaker Mixer", "PCM Playback Switch", "DAC"}, - {"Speaker Mixer", "Aux Playback Switch", "Aux Input"}, - {"Speaker Mixer", "Line Bypass Switch", "Boost Mixer"}, - - /* Outputs */ - {"Mono Out", NULL, "Mono Mixer"}, - {"MONOOUT", NULL, "Mono Out"}, - {"SpkN Out", NULL, "Speaker Mixer"}, - {"SpkP Out", NULL, "Speaker Mixer"}, - {"SPKOUTN", NULL, "SpkN Out"}, - {"SPKOUTP", NULL, "SpkP Out"}, - - /* Boost Mixer */ - {"ADC", NULL, "Boost Mixer"}, - {"Boost Mixer", "Aux Switch", "Aux Input"}, - {"Boost Mixer", NULL, "Input PGA"}, - {"Boost Mixer", NULL, "MICP"}, - - /* Input PGA */ - {"Input PGA", "Aux Switch", "Aux Input"}, - {"Input PGA", "MicN Switch", "MICN"}, - {"Input PGA", "MicP Switch", "MICP"}, - - /* Inputs */ - {"Aux Input", NULL, "AUX"}, -}; - -static int wm8974_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, wm8974_dapm_widgets, - ARRAY_SIZE(wm8974_dapm_widgets)); - - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - - snd_soc_dapm_new_widgets(codec); - return 0; -} - -struct pll_ { - unsigned int pre_div:4; /* prescale - 1 */ - unsigned int n:4; - unsigned int k; -}; - -static struct pll_ pll_div; - -/* The size in bits of the pll divide multiplied by 10 - * to allow rounding later */ -#define FIXED_PLL_SIZE ((1 << 24) * 10) - -static void pll_factors(unsigned int target, unsigned int source) -{ - unsigned long long Kpart; - unsigned int K, Ndiv, Nmod; - - Ndiv = target / source; - if (Ndiv < 6) { - source >>= 1; - pll_div.pre_div = 1; - Ndiv = target / source; - } else - pll_div.pre_div = 0; - - if ((Ndiv < 6) || (Ndiv > 12)) - printk(KERN_WARNING - "WM8974 N value %u outwith recommended range!\n", - Ndiv); - - pll_div.n = Ndiv; - Nmod = target % source; - Kpart = FIXED_PLL_SIZE * (long long)Nmod; - - do_div(Kpart, source); - - K = Kpart & 0xFFFFFFFF; - - /* Check if we need to round */ - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - K /= 10; - - pll_div.k = K; -} - -static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, - int pll_id, unsigned int freq_in, unsigned int freq_out) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - if (freq_in == 0 || freq_out == 0) { - /* Clock CODEC directly from MCLK */ - reg = snd_soc_read(codec, WM8974_CLOCK); - snd_soc_write(codec, WM8974_CLOCK, reg & 0x0ff); - - /* Turn off PLL */ - reg = snd_soc_read(codec, WM8974_POWER1); - snd_soc_write(codec, WM8974_POWER1, reg & 0x1df); - return 0; - } - - pll_factors(freq_out*4, freq_in); - - snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); - snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18); - snd_soc_write(codec, WM8974_PLLK2, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8974_PLLK3, pll_div.k & 0x1ff); - reg = snd_soc_read(codec, WM8974_POWER1); - snd_soc_write(codec, WM8974_POWER1, reg | 0x020); - - /* Run CODEC from PLL instead of MCLK */ - reg = snd_soc_read(codec, WM8974_CLOCK); - snd_soc_write(codec, WM8974_CLOCK, reg | 0x100); - - return 0; -} - -/* - * Configure WM8974 clock dividers. - */ -static int wm8974_set_dai_clkdiv(struct snd_soc_dai *codec_dai, - int div_id, int div) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 reg; - - switch (div_id) { - case WM8974_OPCLKDIV: - reg = snd_soc_read(codec, WM8974_GPIO) & 0x1cf; - snd_soc_write(codec, WM8974_GPIO, reg | div); - break; - case WM8974_MCLKDIV: - reg = snd_soc_read(codec, WM8974_CLOCK) & 0x11f; - snd_soc_write(codec, WM8974_CLOCK, reg | div); - break; - case WM8974_ADCCLK: - reg = snd_soc_read(codec, WM8974_ADC) & 0x1f7; - snd_soc_write(codec, WM8974_ADC, reg | div); - break; - case WM8974_DACCLK: - reg = snd_soc_read(codec, WM8974_DAC) & 0x1f7; - snd_soc_write(codec, WM8974_DAC, reg | div); - break; - case WM8974_BCLKDIV: - reg = snd_soc_read(codec, WM8974_CLOCK) & 0x1e3; - snd_soc_write(codec, WM8974_CLOCK, reg | div); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = codec_dai->codec; - u16 iface = 0; - u16 clk = snd_soc_read(codec, WM8974_CLOCK) & 0x1fe; - - /* set master/slave audio interface */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBM_CFM: - clk |= 0x0001; - break; - case SND_SOC_DAIFMT_CBS_CFS: - break; - default: - return -EINVAL; - } - - /* interface format */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - iface |= 0x0010; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - iface |= 0x0008; - break; - case SND_SOC_DAIFMT_DSP_A: - iface |= 0x00018; - break; - default: - return -EINVAL; - } - - /* clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - iface |= 0x0180; - break; - case SND_SOC_DAIFMT_IB_NF: - iface |= 0x0100; - break; - case SND_SOC_DAIFMT_NB_IF: - iface |= 0x0080; - break; - default: - return -EINVAL; - } - - snd_soc_write(codec, WM8974_IFACE, iface); - snd_soc_write(codec, WM8974_CLOCK, clk); - return 0; -} - -static int wm8974_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - u16 iface = snd_soc_read(codec, WM8974_IFACE) & 0x19f; - u16 adn = snd_soc_read(codec, WM8974_ADD) & 0x1f1; - - /* bit size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - break; - case SNDRV_PCM_FORMAT_S20_3LE: - iface |= 0x0020; - break; - case SNDRV_PCM_FORMAT_S24_LE: - iface |= 0x0040; - break; - case SNDRV_PCM_FORMAT_S32_LE: - iface |= 0x0060; - break; - } - - /* filter coefficient */ - switch (params_rate(params)) { - case SNDRV_PCM_RATE_8000: - adn |= 0x5 << 1; - break; - case SNDRV_PCM_RATE_11025: - adn |= 0x4 << 1; - break; - case SNDRV_PCM_RATE_16000: - adn |= 0x3 << 1; - break; - case SNDRV_PCM_RATE_22050: - adn |= 0x2 << 1; - break; - case SNDRV_PCM_RATE_32000: - adn |= 0x1 << 1; - break; - case SNDRV_PCM_RATE_44100: - case SNDRV_PCM_RATE_48000: - break; - } - - snd_soc_write(codec, WM8974_IFACE, iface); - snd_soc_write(codec, WM8974_ADD, adn); - return 0; -} - -static int wm8974_mute(struct snd_soc_dai *dai, int mute) -{ - struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8974_DAC) & 0xffbf; - - if (mute) - snd_soc_write(codec, WM8974_DAC, mute_reg | 0x40); - else - snd_soc_write(codec, WM8974_DAC, mute_reg); - return 0; -} - -/* liam need to make this lower power with dapm */ -static int wm8974_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - u16 power1 = snd_soc_read(codec, WM8974_POWER1) & ~0x3; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - power1 |= 0x1; /* VMID 50k */ - snd_soc_write(codec, WM8974_POWER1, power1); - break; - - case SND_SOC_BIAS_STANDBY: - power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN; - - if (codec->bias_level == SND_SOC_BIAS_OFF) { - /* Initial cap charge at VMID 5k */ - snd_soc_write(codec, WM8974_POWER1, power1 | 0x3); - mdelay(100); - } - - power1 |= 0x2; /* VMID 500k */ - snd_soc_write(codec, WM8974_POWER1, power1); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8974_POWER1, 0); - snd_soc_write(codec, WM8974_POWER2, 0); - snd_soc_write(codec, WM8974_POWER3, 0); - break; - } - - codec->bias_level = level; - return 0; -} - -#define WM8974_RATES (SNDRV_PCM_RATE_8000_48000) - -#define WM8974_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE) - -static struct snd_soc_dai_ops wm8974_ops = { - .hw_params = wm8974_pcm_hw_params, - .digital_mute = wm8974_mute, - .set_fmt = wm8974_set_dai_fmt, - .set_clkdiv = wm8974_set_dai_clkdiv, - .set_pll = wm8974_set_dai_pll, -}; - -struct snd_soc_dai wm8974_dai = { - .name = "WM8974 HiFi", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, /* Only 1 channel of data */ - .rates = WM8974_RATES, - .formats = WM8974_FORMATS,}, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, /* Only 1 channel of data */ - .rates = WM8974_RATES, - .formats = WM8974_FORMATS,}, - .ops = &wm8974_ops, - .symmetric_rates = 1, -}; -EXPORT_SYMBOL_GPL(wm8974_dai); - -static int wm8974_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - - wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF); - return 0; -} - -static int wm8974_resume(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec = socdev->card->codec; - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - wm8974_set_bias_level(codec, codec->suspend_bias_level); - return 0; -} - -static int wm8974_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - int ret = 0; - - if (wm8974_codec == NULL) { - dev_err(&pdev->dev, "Codec device not registered\n"); - return -ENODEV; - } - - socdev->card->codec = wm8974_codec; - codec = wm8974_codec; - - /* register pcms */ - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms: %d\n", ret); - goto pcm_err; - } - - snd_soc_add_controls(codec, wm8974_snd_controls, - ARRAY_SIZE(wm8974_snd_controls)); - wm8974_add_widgets(codec); - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card: %d\n", ret); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -pcm_err: - return ret; -} - -/* power down chip */ -static int wm8974_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8974 = { - .probe = wm8974_probe, - .remove = wm8974_remove, - .suspend = wm8974_suspend, - .resume = wm8974_resume, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8974); - -static __devinit int wm8974_register(struct wm8974_priv *wm8974) -{ - int ret; - struct snd_soc_codec *codec = &wm8974->codec; - - if (wm8974_codec) { - dev_err(codec->dev, "Another WM8974 is registered\n"); - return -EINVAL; - } - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->private_data = wm8974; - codec->name = "WM8974"; - codec->owner = THIS_MODULE; - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8974_set_bias_level; - codec->dai = &wm8974_dai; - codec->num_dai = 1; - codec->reg_cache_size = WM8974_CACHEREGNUM; - codec->reg_cache = &wm8974->reg_cache; - - ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - - memcpy(codec->reg_cache, wm8974_reg, sizeof(wm8974_reg)); - - ret = wm8974_reset(codec); - if (ret < 0) { - dev_err(codec->dev, "Failed to issue reset\n"); - goto err; - } - - wm8974_dai.dev = codec->dev; - - wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - - wm8974_codec = codec; - - ret = snd_soc_register_codec(codec); - if (ret != 0) { - dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; - } - - ret = snd_soc_register_dai(&wm8974_dai); - if (ret != 0) { - dev_err(codec->dev, "Failed to register DAI: %d\n", ret); - goto err_codec; - } - - return 0; - -err_codec: - snd_soc_unregister_codec(codec); -err: - kfree(wm8974); - return ret; -} - -static __devexit void wm8974_unregister(struct wm8974_priv *wm8974) -{ - wm8974_set_bias_level(&wm8974->codec, SND_SOC_BIAS_OFF); - snd_soc_unregister_dai(&wm8974_dai); - snd_soc_unregister_codec(&wm8974->codec); - kfree(wm8974); - wm8974_codec = NULL; -} - -static __devinit int wm8974_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8974_priv *wm8974; - struct snd_soc_codec *codec; - - wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL); - if (wm8974 == NULL) - return -ENOMEM; - - codec = &wm8974->codec; - codec->hw_write = (hw_write_t)i2c_master_send; - - i2c_set_clientdata(i2c, wm8974); - codec->control_data = i2c; - - codec->dev = &i2c->dev; - - return wm8974_register(wm8974); -} - -static __devexit int wm8974_i2c_remove(struct i2c_client *client) -{ - struct wm8974_priv *wm8974 = i2c_get_clientdata(client); - wm8974_unregister(wm8974); - return 0; -} - -static const struct i2c_device_id wm8974_i2c_id[] = { - { "wm8974", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id); - -static struct i2c_driver wm8974_i2c_driver = { - .driver = { - .name = "WM8974", - .owner = THIS_MODULE, - }, - .probe = wm8974_i2c_probe, - .remove = __devexit_p(wm8974_i2c_remove), - .id_table = wm8974_i2c_id, -}; - -static int __init wm8974_modinit(void) -{ - return i2c_add_driver(&wm8974_i2c_driver); -} -module_init(wm8974_modinit); - -static void __exit wm8974_exit(void) -{ - i2c_del_driver(&wm8974_i2c_driver); -} -module_exit(wm8974_exit); - -MODULE_DESCRIPTION("ASoC WM8974 driver"); -MODULE_AUTHOR("Liam Girdwood"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8974.h b/trunk/sound/soc/codecs/wm8974.h deleted file mode 100644 index 98de9562d4d2..000000000000 --- a/trunk/sound/soc/codecs/wm8974.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * wm8974.h -- WM8974 Soc Audio driver - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM8974_H -#define _WM8974_H - -/* WM8974 register space */ - -#define WM8974_RESET 0x0 -#define WM8974_POWER1 0x1 -#define WM8974_POWER2 0x2 -#define WM8974_POWER3 0x3 -#define WM8974_IFACE 0x4 -#define WM8974_COMP 0x5 -#define WM8974_CLOCK 0x6 -#define WM8974_ADD 0x7 -#define WM8974_GPIO 0x8 -#define WM8974_DAC 0xa -#define WM8974_DACVOL 0xb -#define WM8974_ADC 0xe -#define WM8974_ADCVOL 0xf -#define WM8974_EQ1 0x12 -#define WM8974_EQ2 0x13 -#define WM8974_EQ3 0x14 -#define WM8974_EQ4 0x15 -#define WM8974_EQ5 0x16 -#define WM8974_DACLIM1 0x18 -#define WM8974_DACLIM2 0x19 -#define WM8974_NOTCH1 0x1b -#define WM8974_NOTCH2 0x1c -#define WM8974_NOTCH3 0x1d -#define WM8974_NOTCH4 0x1e -#define WM8974_ALC1 0x20 -#define WM8974_ALC2 0x21 -#define WM8974_ALC3 0x22 -#define WM8974_NGATE 0x23 -#define WM8974_PLLN 0x24 -#define WM8974_PLLK1 0x25 -#define WM8974_PLLK2 0x26 -#define WM8974_PLLK3 0x27 -#define WM8974_ATTEN 0x28 -#define WM8974_INPUT 0x2c -#define WM8974_INPPGA 0x2d -#define WM8974_ADCBOOST 0x2f -#define WM8974_OUTPUT 0x31 -#define WM8974_SPKMIX 0x32 -#define WM8974_SPKVOL 0x36 -#define WM8974_MONOMIX 0x38 - -#define WM8974_CACHEREGNUM 57 - -/* Clock divider Id's */ -#define WM8974_OPCLKDIV 0 -#define WM8974_MCLKDIV 1 -#define WM8974_ADCCLK 2 -#define WM8974_DACCLK 3 -#define WM8974_BCLKDIV 4 - -/* DAC clock dividers */ -#define WM8974_DACCLK_F2 (1 << 3) -#define WM8974_DACCLK_F4 (0 << 3) - -/* ADC clock dividers */ -#define WM8974_ADCCLK_F2 (1 << 3) -#define WM8974_ADCCLK_F4 (0 << 3) - -/* PLL Out dividers */ -#define WM8974_OPCLKDIV_1 (0 << 4) -#define WM8974_OPCLKDIV_2 (1 << 4) -#define WM8974_OPCLKDIV_3 (2 << 4) -#define WM8974_OPCLKDIV_4 (3 << 4) - -/* BCLK clock dividers */ -#define WM8974_BCLKDIV_1 (0 << 2) -#define WM8974_BCLKDIV_2 (1 << 2) -#define WM8974_BCLKDIV_4 (2 << 2) -#define WM8974_BCLKDIV_8 (3 << 2) -#define WM8974_BCLKDIV_16 (4 << 2) -#define WM8974_BCLKDIV_32 (5 << 2) - -/* MCLK clock dividers */ -#define WM8974_MCLKDIV_1 (0 << 5) -#define WM8974_MCLKDIV_1_5 (1 << 5) -#define WM8974_MCLKDIV_2 (2 << 5) -#define WM8974_MCLKDIV_3 (3 << 5) -#define WM8974_MCLKDIV_4 (4 << 5) -#define WM8974_MCLKDIV_6 (5 << 5) -#define WM8974_MCLKDIV_8 (6 << 5) -#define WM8974_MCLKDIV_12 (7 << 5) - -extern struct snd_soc_dai wm8974_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8974; - -#endif diff --git a/trunk/sound/soc/codecs/wm8988.c b/trunk/sound/soc/codecs/wm8988.c index 3f530f8a972a..8c0fdf84aac3 100644 --- a/trunk/sound/soc/codecs/wm8988.c +++ b/trunk/sound/soc/codecs/wm8988.c @@ -57,7 +57,50 @@ struct wm8988_priv { }; -#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0) +/* + * read wm8988 register cache + */ +static inline unsigned int wm8988_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + if (reg > WM8988_NUM_REG) + return -1; + return cache[reg]; +} + +/* + * write wm8988 register cache + */ +static inline void wm8988_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + if (reg > WM8988_NUM_REG) + return; + cache[reg] = value; +} + +static int wm8988_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[2]; + + /* data is + * D15..D9 WM8753 register offset + * D8...D0 register data + */ + data[0] = (reg << 1) | ((value >> 8) & 0x0001); + data[1] = value & 0x00ff; + + wm8988_write_reg_cache(codec, reg, value); + if (codec->hw_write(codec->control_data, data, 2) == 2) + return 0; + else + return -EIO; +} + +#define wm8988_reset(c) wm8988_write(c, WM8988_RESET, 0) /* * WM8988 Controls @@ -183,15 +226,15 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2); + u16 adctl2 = wm8988_read_reg_cache(codec, WM8988_ADCTL2); /* Use the DAC to gate LRC if active, otherwise use ADC */ - if (snd_soc_read(codec, WM8988_PWR2) & 0x180) + if (wm8988_read_reg_cache(codec, WM8988_PWR2) & 0x180) adctl2 &= ~0x4; else adctl2 |= 0x4; - return snd_soc_write(codec, WM8988_ADCTL2, adctl2); + return wm8988_write(codec, WM8988_ADCTL2, adctl2); } static const char *wm8988_line_texts[] = { @@ -576,7 +619,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8988_IFACE, iface); + wm8988_write(codec, WM8988_IFACE, iface); return 0; } @@ -610,8 +653,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; struct wm8988_priv *wm8988 = codec->private_data; - u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3; - u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180; + u16 iface = wm8988_read_reg_cache(codec, WM8988_IFACE) & 0x1f3; + u16 srate = wm8988_read_reg_cache(codec, WM8988_SRATE) & 0x180; int coeff; coeff = get_coeff(wm8988->sysclk, params_rate(params)); @@ -642,9 +685,9 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, } /* set iface & srate */ - snd_soc_write(codec, WM8988_IFACE, iface); + wm8988_write(codec, WM8988_IFACE, iface); if (coeff >= 0) - snd_soc_write(codec, WM8988_SRATE, srate | + wm8988_write(codec, WM8988_SRATE, srate | (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); return 0; @@ -653,19 +696,19 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream, static int wm8988_mute(struct snd_soc_dai *dai, int mute) { struct snd_soc_codec *codec = dai->codec; - u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7; + u16 mute_reg = wm8988_read_reg_cache(codec, WM8988_ADCDAC) & 0xfff7; if (mute) - snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8); + wm8988_write(codec, WM8988_ADCDAC, mute_reg | 0x8); else - snd_soc_write(codec, WM8988_ADCDAC, mute_reg); + wm8988_write(codec, WM8988_ADCDAC, mute_reg); return 0; } static int wm8988_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1; + u16 pwr_reg = wm8988_read_reg_cache(codec, WM8988_PWR1) & ~0x1c1; switch (level) { case SND_SOC_BIAS_ON: @@ -673,24 +716,24 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: /* VREF, VMID=2x50k, digital enabled */ - snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); + wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* VREF, VMID=2x5k */ - snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); + wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); /* Charge caps */ msleep(100); } /* VREF, VMID=2*500k, digital stopped */ - snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141); + wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x0141); break; case SND_SOC_BIAS_OFF: - snd_soc_write(codec, WM8988_PWR1, 0x0000); + wm8988_write(codec, WM8988_PWR1, 0x0000); break; } codec->bias_level = level; @@ -825,8 +868,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8988 = { }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm8988); -static int wm8988_register(struct wm8988_priv *wm8988, - enum snd_soc_control_type control) +static int wm8988_register(struct wm8988_priv *wm8988) { struct snd_soc_codec *codec = &wm8988->codec; int ret; @@ -845,6 +887,8 @@ static int wm8988_register(struct wm8988_priv *wm8988, codec->private_data = wm8988; codec->name = "WM8988"; codec->owner = THIS_MODULE; + codec->read = wm8988_read_reg_cache; + codec->write = wm8988_write; codec->dai = &wm8988_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); @@ -855,29 +899,23 @@ static int wm8988_register(struct wm8988_priv *wm8988, memcpy(codec->reg_cache, wm8988_reg, sizeof(wm8988_reg)); - ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); - if (ret < 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - goto err; - } - ret = wm8988_reset(codec); if (ret < 0) { dev_err(codec->dev, "Failed to issue reset\n"); - goto err; + return ret; } /* set the update bits (we always update left then right) */ - reg = snd_soc_read(codec, WM8988_RADC); - snd_soc_write(codec, WM8988_RADC, reg | 0x100); - reg = snd_soc_read(codec, WM8988_RDAC); - snd_soc_write(codec, WM8988_RDAC, reg | 0x0100); - reg = snd_soc_read(codec, WM8988_ROUT1V); - snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100); - reg = snd_soc_read(codec, WM8988_ROUT2V); - snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100); - reg = snd_soc_read(codec, WM8988_RINVOL); - snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100); + reg = wm8988_read_reg_cache(codec, WM8988_RADC); + wm8988_write(codec, WM8988_RADC, reg | 0x100); + reg = wm8988_read_reg_cache(codec, WM8988_RDAC); + wm8988_write(codec, WM8988_RDAC, reg | 0x0100); + reg = wm8988_read_reg_cache(codec, WM8988_ROUT1V); + wm8988_write(codec, WM8988_ROUT1V, reg | 0x0100); + reg = wm8988_read_reg_cache(codec, WM8988_ROUT2V); + wm8988_write(codec, WM8988_ROUT2V, reg | 0x0100); + reg = wm8988_read_reg_cache(codec, WM8988_RINVOL); + wm8988_write(codec, WM8988_RINVOL, reg | 0x0100); wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); @@ -888,20 +926,18 @@ static int wm8988_register(struct wm8988_priv *wm8988, ret = snd_soc_register_codec(codec); if (ret != 0) { dev_err(codec->dev, "Failed to register codec: %d\n", ret); - goto err; + return ret; } ret = snd_soc_register_dai(&wm8988_dai); if (ret != 0) { dev_err(codec->dev, "Failed to register DAI: %d\n", ret); snd_soc_unregister_codec(codec); - goto err_codec; + return ret; } return 0; -err_codec: - snd_soc_unregister_codec(codec); err: kfree(wm8988); return ret; @@ -928,13 +964,14 @@ static int wm8988_i2c_probe(struct i2c_client *i2c, return -ENOMEM; codec = &wm8988->codec; + codec->hw_write = (hw_write_t)i2c_master_send; i2c_set_clientdata(i2c, wm8988); codec->control_data = i2c; codec->dev = &i2c->dev; - return wm8988_register(wm8988, SND_SOC_I2C); + return wm8988_register(wm8988); } static int wm8988_i2c_remove(struct i2c_client *client) @@ -944,21 +981,6 @@ static int wm8988_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm8988_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm8988_i2c_suspend NULL -#define wm8988_i2c_resume NULL -#endif - static const struct i2c_device_id wm8988_i2c_id[] = { { "wm8988", 0 }, { } @@ -972,13 +994,35 @@ static struct i2c_driver wm8988_i2c_driver = { }, .probe = wm8988_i2c_probe, .remove = wm8988_i2c_remove, - .suspend = wm8988_i2c_suspend, - .resume = wm8988_i2c_resume, .id_table = wm8988_i2c_id, }; #endif #if defined(CONFIG_SPI_MASTER) +static int wm8988_spi_write(struct spi_device *spi, const char *data, int len) +{ + struct spi_transfer t; + struct spi_message m; + u8 msg[2]; + + if (len <= 0) + return 0; + + msg[0] = data[0]; + msg[1] = data[1]; + + spi_message_init(&m); + memset(&t, 0, (sizeof t)); + + t.tx_buf = &msg[0]; + t.len = len; + + spi_message_add_tail(&t, &m); + spi_sync(spi, &m); + + return len; +} + static int __devinit wm8988_spi_probe(struct spi_device *spi) { struct wm8988_priv *wm8988; @@ -989,12 +1033,13 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi) return -ENOMEM; codec = &wm8988->codec; + codec->hw_write = (hw_write_t)wm8988_spi_write; codec->control_data = spi; codec->dev = &spi->dev; dev_set_drvdata(&spi->dev, wm8988); - return wm8988_register(wm8988, SND_SOC_SPI); + return wm8988_register(wm8988); } static int __devexit wm8988_spi_remove(struct spi_device *spi) @@ -1006,21 +1051,6 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi) return 0; } -#ifdef CONFIG_PM -static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg) -{ - return snd_soc_suspend_device(&spi->dev); -} - -static int wm8988_spi_resume(struct spi_device *spi) -{ - return snd_soc_resume_device(&spi->dev); -} -#else -#define wm8988_spi_suspend NULL -#define wm8988_spi_resume NULL -#endif - static struct spi_driver wm8988_spi_driver = { .driver = { .name = "wm8988", @@ -1029,8 +1059,6 @@ static struct spi_driver wm8988_spi_driver = { }, .probe = wm8988_spi_probe, .remove = __devexit_p(wm8988_spi_remove), - .suspend = wm8988_spi_suspend, - .resume = wm8988_spi_resume, }; #endif diff --git a/trunk/sound/soc/codecs/wm8990.c b/trunk/sound/soc/codecs/wm8990.c index 2d702db4131d..d029818350e9 100644 --- a/trunk/sound/soc/codecs/wm8990.c +++ b/trunk/sound/soc/codecs/wm8990.c @@ -108,7 +108,53 @@ static const u16 wm8990_reg[] = { 0x0000, /* R63 - Driver internal */ }; -#define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0) +/* + * read wm8990 register cache + */ +static inline unsigned int wm8990_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + BUG_ON(reg >= ARRAY_SIZE(wm8990_reg)); + return cache[reg]; +} + +/* + * write wm8990 register cache + */ +static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec, + unsigned int reg, unsigned int value) +{ + u16 *cache = codec->reg_cache; + + /* Reset register and reserved registers are uncached */ + if (reg == 0 || reg >= ARRAY_SIZE(wm8990_reg)) + return; + + cache[reg] = value; +} + +/* + * write to the wm8990 register space + */ +static int wm8990_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u8 data[3]; + + data[0] = reg & 0xFF; + data[1] = (value >> 8) & 0xFF; + data[2] = value & 0xFF; + + wm8990_write_reg_cache(codec, reg, value); + + if (codec->hw_write(codec->control_data, data, 3) == 2) + return 0; + else + return -EIO; +} + +#define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0) static const DECLARE_TLV_DB_LINEAR(rec_mix_tlv, -1500, 600); @@ -141,8 +187,8 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, return ret; /* now hit the volume update bits (always bit 8) */ - val = snd_soc_read(codec, reg); - return snd_soc_write(codec, reg, val | 0x0100); + val = wm8990_read_reg_cache(codec, reg); + return wm8990_write(codec, reg, val | 0x0100); } #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ @@ -381,8 +427,8 @@ static int inmixer_event(struct snd_soc_dapm_widget *w, { u16 reg, fakepower; - reg = snd_soc_read(w->codec, WM8990_POWER_MANAGEMENT_2); - fakepower = snd_soc_read(w->codec, WM8990_INTDRIVBITS); + reg = wm8990_read_reg_cache(w->codec, WM8990_POWER_MANAGEMENT_2); + fakepower = wm8990_read_reg_cache(w->codec, WM8990_INTDRIVBITS); if (fakepower & ((1 << WM8990_INMIXL_PWR_BIT) | (1 << WM8990_AINLMUX_PWR_BIT))) { @@ -397,7 +443,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w, } else { reg &= ~WM8990_AINL_ENA; } - snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg); + wm8990_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg); return 0; } @@ -411,7 +457,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, switch (reg_shift) { case WM8990_SPEAKER_MIXER | (WM8990_LDSPK_BIT << 8) : - reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER1); + reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER1); if (reg & WM8990_LDLO) { printk(KERN_WARNING "Cannot set as Output Mixer 1 LDLO Set\n"); @@ -419,7 +465,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_SPEAKER_MIXER | (WM8990_RDSPK_BIT << 8): - reg = snd_soc_read(w->codec, WM8990_OUTPUT_MIXER2); + reg = wm8990_read_reg_cache(w->codec, WM8990_OUTPUT_MIXER2); if (reg & WM8990_RDRO) { printk(KERN_WARNING "Cannot set as Output Mixer 2 RDRO Set\n"); @@ -427,7 +473,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_OUTPUT_MIXER1 | (WM8990_LDLO_BIT << 8): - reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER); + reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER); if (reg & WM8990_LDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer LDSPK Set\n"); @@ -435,7 +481,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w, } break; case WM8990_OUTPUT_MIXER2 | (WM8990_RDRO_BIT << 8): - reg = snd_soc_read(w->codec, WM8990_SPEAKER_MIXER); + reg = wm8990_read_reg_cache(w->codec, WM8990_SPEAKER_MIXER); if (reg & WM8990_RDSPK) { printk(KERN_WARNING "Cannot set as Speaker Mixer RDSPK Set\n"); @@ -983,24 +1029,24 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, pll_factors(&pll_div, freq_out * 4, freq_in); /* Turn on PLL */ - reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2); + reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); reg |= WM8990_PLL_ENA; - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg); /* sysclk comes from PLL */ - reg = snd_soc_read(codec, WM8990_CLOCKING_2); - snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); + reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2); + wm8990_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC); /* set up N , fractional mode and pre-divisor if neccessary */ - snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | + wm8990_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM | (pll_div.div2?WM8990_PRESCALE:0)); - snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); - snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF)); + wm8990_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8)); + wm8990_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF)); } else { /* Turn on PLL */ - reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2); + reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); reg &= ~WM8990_PLL_ENA; - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg); } return 0; } @@ -1027,8 +1073,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; u16 audio1, audio3; - audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); - audio3 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_3); + audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); + audio3 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_3); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -1069,8 +1115,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai, return -EINVAL; } - snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); - snd_soc_write(codec, WM8990_AUDIO_INTERFACE_3, audio3); + wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); + wm8990_write(codec, WM8990_AUDIO_INTERFACE_3, audio3); return 0; } @@ -1082,24 +1128,24 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai, switch (div_id) { case WM8990_MCLK_DIV: - reg = snd_soc_read(codec, WM8990_CLOCKING_2) & + reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & ~WM8990_MCLK_DIV_MASK; - snd_soc_write(codec, WM8990_CLOCKING_2, reg | div); + wm8990_write(codec, WM8990_CLOCKING_2, reg | div); break; case WM8990_DACCLK_DIV: - reg = snd_soc_read(codec, WM8990_CLOCKING_2) & + reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & ~WM8990_DAC_CLKDIV_MASK; - snd_soc_write(codec, WM8990_CLOCKING_2, reg | div); + wm8990_write(codec, WM8990_CLOCKING_2, reg | div); break; case WM8990_ADCCLK_DIV: - reg = snd_soc_read(codec, WM8990_CLOCKING_2) & + reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_2) & ~WM8990_ADC_CLKDIV_MASK; - snd_soc_write(codec, WM8990_CLOCKING_2, reg | div); + wm8990_write(codec, WM8990_CLOCKING_2, reg | div); break; case WM8990_BCLK_DIV: - reg = snd_soc_read(codec, WM8990_CLOCKING_1) & + reg = wm8990_read_reg_cache(codec, WM8990_CLOCKING_1) & ~WM8990_BCLK_DIV_MASK; - snd_soc_write(codec, WM8990_CLOCKING_1, reg | div); + wm8990_write(codec, WM8990_CLOCKING_1, reg | div); break; default: return -EINVAL; @@ -1118,7 +1164,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_codec *codec = socdev->card->codec; - u16 audio1 = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_1); + u16 audio1 = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_1); audio1 &= ~WM8990_AIF_WL_MASK; /* bit size */ @@ -1136,7 +1182,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream, break; } - snd_soc_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); + wm8990_write(codec, WM8990_AUDIO_INTERFACE_1, audio1); return 0; } @@ -1145,12 +1191,12 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute) struct snd_soc_codec *codec = dai->codec; u16 val; - val = snd_soc_read(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; + val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL) & ~WM8990_DAC_MUTE; if (mute) - snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); + wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); else - snd_soc_write(codec, WM8990_DAC_CTRL, val); + wm8990_write(codec, WM8990_DAC_CTRL, val); return 0; } @@ -1166,21 +1212,21 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: /* VMID=2*50k */ - val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) & + val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) & ~WM8990_VMID_MODE_MASK; - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2); break; case SND_SOC_BIAS_STANDBY: if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Enable all output discharge bits */ - snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | + wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | WM8990_DIS_RLINE | WM8990_DIS_OUT3 | WM8990_DIS_OUT4 | WM8990_DIS_LOUT | WM8990_DIS_ROUT); /* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | + wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | WM8990_BUFDCOPEN | WM8990_POBCTRL | WM8990_VMIDTOG); @@ -1188,83 +1234,83 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, msleep(msecs_to_jiffies(300)); /* Disable VMIDTOG */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | + wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | WM8990_BUFDCOPEN | WM8990_POBCTRL); /* disable all output discharge bits */ - snd_soc_write(codec, WM8990_ANTIPOP1, 0); + wm8990_write(codec, WM8990_ANTIPOP1, 0); /* Enable outputs */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1b00); msleep(msecs_to_jiffies(50)); /* Enable VMID at 2x50k */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f02); msleep(msecs_to_jiffies(100)); /* Enable VREF */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); msleep(msecs_to_jiffies(600)); /* Enable BUFIOEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | + wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | WM8990_BUFDCOPEN | WM8990_POBCTRL | WM8990_BUFIOEN); /* Disable outputs */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x3); /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); + wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); /* Enable workaround for ADC clocking issue. */ - snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0x2); - snd_soc_write(codec, WM8990_EXT_CTL1, 0xa003); - snd_soc_write(codec, WM8990_EXT_ACCESS_ENA, 0); + wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2); + wm8990_write(codec, WM8990_EXT_CTL1, 0xa003); + wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0); } /* VMID=2*250k */ - val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) & + val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) & ~WM8990_VMID_MODE_MASK; - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4); break; case SND_SOC_BIAS_OFF: /* Enable POBCTRL and SOFT_ST */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | + wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | WM8990_POBCTRL | WM8990_BUFIOEN); /* Enable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | + wm8990_write(codec, WM8990_ANTIPOP2, WM8990_SOFTST | WM8990_BUFDCOPEN | WM8990_POBCTRL | WM8990_BUFIOEN); /* mute DAC */ - val = snd_soc_read(codec, WM8990_DAC_CTRL); - snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); + val = wm8990_read_reg_cache(codec, WM8990_DAC_CTRL); + wm8990_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE); /* Enable any disabled outputs */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03); /* Disable VMID */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f01); msleep(msecs_to_jiffies(300)); /* Enable all output discharge bits */ - snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | + wm8990_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | WM8990_DIS_RLINE | WM8990_DIS_OUT3 | WM8990_DIS_OUT4 | WM8990_DIS_LOUT | WM8990_DIS_ROUT); /* Disable VREF */ - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, 0x0); /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ - snd_soc_write(codec, WM8990_ANTIPOP2, 0x0); + wm8990_write(codec, WM8990_ANTIPOP2, 0x0); break; } @@ -1365,6 +1411,8 @@ static int wm8990_init(struct snd_soc_device *socdev) codec->name = "WM8990"; codec->owner = THIS_MODULE; + codec->read = wm8990_read_reg_cache; + codec->write = wm8990_write; codec->set_bias_level = wm8990_set_bias_level; codec->dai = &wm8990_dai; codec->num_dai = 2; @@ -1374,12 +1422,6 @@ static int wm8990_init(struct snd_soc_device *socdev) if (codec->reg_cache == NULL) return -ENOMEM; - ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); - if (ret < 0) { - printk(KERN_ERR "wm8990: failed to set cache I/O: %d\n", ret); - goto pcm_err; - } - wm8990_reset(codec); /* register pcms */ @@ -1393,18 +1435,18 @@ static int wm8990_init(struct snd_soc_device *socdev) codec->bias_level = SND_SOC_BIAS_OFF; wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4); - snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1); + reg = wm8990_read_reg_cache(codec, WM8990_AUDIO_INTERFACE_4); + wm8990_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1); - reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) & + reg = wm8990_read_reg_cache(codec, WM8990_GPIO1_GPIO2) & ~WM8990_GPIO1_SEL_MASK; - snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1); + wm8990_write(codec, WM8990_GPIO1_GPIO2, reg | 1); - reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2); - snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA); + reg = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_2); + wm8990_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA); - snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); - snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); + wm8990_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); + wm8990_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); snd_soc_add_controls(codec, wm8990_snd_controls, ARRAY_SIZE(wm8990_snd_controls)); diff --git a/trunk/sound/soc/codecs/wm8993.c b/trunk/sound/soc/codecs/wm8993.c deleted file mode 100644 index d9987999e92c..000000000000 --- a/trunk/sound/soc/codecs/wm8993.c +++ /dev/null @@ -1,1675 +0,0 @@ -/* - * wm8993.c -- WM8993 ALSA SoC audio driver - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8993.h" -#include "wm_hubs.h" - -static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = { - 0x8993, /* R0 - Software Reset */ - 0x0000, /* R1 - Power Management (1) */ - 0x6000, /* R2 - Power Management (2) */ - 0x0000, /* R3 - Power Management (3) */ - 0x4050, /* R4 - Audio Interface (1) */ - 0x4000, /* R5 - Audio Interface (2) */ - 0x01C8, /* R6 - Clocking 1 */ - 0x0000, /* R7 - Clocking 2 */ - 0x0000, /* R8 - Audio Interface (3) */ - 0x0040, /* R9 - Audio Interface (4) */ - 0x0004, /* R10 - DAC CTRL */ - 0x00C0, /* R11 - Left DAC Digital Volume */ - 0x00C0, /* R12 - Right DAC Digital Volume */ - 0x0000, /* R13 - Digital Side Tone */ - 0x0300, /* R14 - ADC CTRL */ - 0x00C0, /* R15 - Left ADC Digital Volume */ - 0x00C0, /* R16 - Right ADC Digital Volume */ - 0x0000, /* R17 */ - 0x0000, /* R18 - GPIO CTRL 1 */ - 0x0010, /* R19 - GPIO1 */ - 0x0000, /* R20 - IRQ_DEBOUNCE */ - 0x0000, /* R21 */ - 0x8000, /* R22 - GPIOCTRL 2 */ - 0x0800, /* R23 - GPIO_POL */ - 0x008B, /* R24 - Left Line Input 1&2 Volume */ - 0x008B, /* R25 - Left Line Input 3&4 Volume */ - 0x008B, /* R26 - Right Line Input 1&2 Volume */ - 0x008B, /* R27 - Right Line Input 3&4 Volume */ - 0x006D, /* R28 - Left Output Volume */ - 0x006D, /* R29 - Right Output Volume */ - 0x0066, /* R30 - Line Outputs Volume */ - 0x0020, /* R31 - HPOUT2 Volume */ - 0x0079, /* R32 - Left OPGA Volume */ - 0x0079, /* R33 - Right OPGA Volume */ - 0x0003, /* R34 - SPKMIXL Attenuation */ - 0x0003, /* R35 - SPKMIXR Attenuation */ - 0x0011, /* R36 - SPKOUT Mixers */ - 0x0100, /* R37 - SPKOUT Boost */ - 0x0079, /* R38 - Speaker Volume Left */ - 0x0079, /* R39 - Speaker Volume Right */ - 0x0000, /* R40 - Input Mixer2 */ - 0x0000, /* R41 - Input Mixer3 */ - 0x0000, /* R42 - Input Mixer4 */ - 0x0000, /* R43 - Input Mixer5 */ - 0x0000, /* R44 - Input Mixer6 */ - 0x0000, /* R45 - Output Mixer1 */ - 0x0000, /* R46 - Output Mixer2 */ - 0x0000, /* R47 - Output Mixer3 */ - 0x0000, /* R48 - Output Mixer4 */ - 0x0000, /* R49 - Output Mixer5 */ - 0x0000, /* R50 - Output Mixer6 */ - 0x0000, /* R51 - HPOUT2 Mixer */ - 0x0000, /* R52 - Line Mixer1 */ - 0x0000, /* R53 - Line Mixer2 */ - 0x0000, /* R54 - Speaker Mixer */ - 0x0000, /* R55 - Additional Control */ - 0x0000, /* R56 - AntiPOP1 */ - 0x0000, /* R57 - AntiPOP2 */ - 0x0000, /* R58 - MICBIAS */ - 0x0000, /* R59 */ - 0x0000, /* R60 - FLL Control 1 */ - 0x0000, /* R61 - FLL Control 2 */ - 0x0000, /* R62 - FLL Control 3 */ - 0x2EE0, /* R63 - FLL Control 4 */ - 0x0002, /* R64 - FLL Control 5 */ - 0x2287, /* R65 - Clocking 3 */ - 0x025F, /* R66 - Clocking 4 */ - 0x0000, /* R67 - MW Slave Control */ - 0x0000, /* R68 */ - 0x0002, /* R69 - Bus Control 1 */ - 0x0000, /* R70 - Write Sequencer 0 */ - 0x0000, /* R71 - Write Sequencer 1 */ - 0x0000, /* R72 - Write Sequencer 2 */ - 0x0000, /* R73 - Write Sequencer 3 */ - 0x0000, /* R74 - Write Sequencer 4 */ - 0x0000, /* R75 - Write Sequencer 5 */ - 0x1F25, /* R76 - Charge Pump 1 */ - 0x0000, /* R77 */ - 0x0000, /* R78 */ - 0x0000, /* R79 */ - 0x0000, /* R80 */ - 0x0000, /* R81 - Class W 0 */ - 0x0000, /* R82 */ - 0x0000, /* R83 */ - 0x0000, /* R84 - DC Servo 0 */ - 0x054A, /* R85 - DC Servo 1 */ - 0x0000, /* R86 */ - 0x0000, /* R87 - DC Servo 3 */ - 0x0000, /* R88 - DC Servo Readback 0 */ - 0x0000, /* R89 - DC Servo Readback 1 */ - 0x0000, /* R90 - DC Servo Readback 2 */ - 0x0000, /* R91 */ - 0x0000, /* R92 */ - 0x0000, /* R93 */ - 0x0000, /* R94 */ - 0x0000, /* R95 */ - 0x0100, /* R96 - Analogue HP 0 */ - 0x0000, /* R97 */ - 0x0000, /* R98 - EQ1 */ - 0x000C, /* R99 - EQ2 */ - 0x000C, /* R100 - EQ3 */ - 0x000C, /* R101 - EQ4 */ - 0x000C, /* R102 - EQ5 */ - 0x000C, /* R103 - EQ6 */ - 0x0FCA, /* R104 - EQ7 */ - 0x0400, /* R105 - EQ8 */ - 0x00D8, /* R106 - EQ9 */ - 0x1EB5, /* R107 - EQ10 */ - 0xF145, /* R108 - EQ11 */ - 0x0B75, /* R109 - EQ12 */ - 0x01C5, /* R110 - EQ13 */ - 0x1C58, /* R111 - EQ14 */ - 0xF373, /* R112 - EQ15 */ - 0x0A54, /* R113 - EQ16 */ - 0x0558, /* R114 - EQ17 */ - 0x168E, /* R115 - EQ18 */ - 0xF829, /* R116 - EQ19 */ - 0x07AD, /* R117 - EQ20 */ - 0x1103, /* R118 - EQ21 */ - 0x0564, /* R119 - EQ22 */ - 0x0559, /* R120 - EQ23 */ - 0x4000, /* R121 - EQ24 */ - 0x0000, /* R122 - Digital Pulls */ - 0x0F08, /* R123 - DRC Control 1 */ - 0x0000, /* R124 - DRC Control 2 */ - 0x0080, /* R125 - DRC Control 3 */ - 0x0000, /* R126 - DRC Control 4 */ -}; - -static struct { - int ratio; - int clk_sys_rate; -} clk_sys_rates[] = { - { 64, 0 }, - { 128, 1 }, - { 192, 2 }, - { 256, 3 }, - { 384, 4 }, - { 512, 5 }, - { 768, 6 }, - { 1024, 7 }, - { 1408, 8 }, - { 1536, 9 }, -}; - -static struct { - int rate; - int sample_rate; -} sample_rates[] = { - { 8000, 0 }, - { 11025, 1 }, - { 12000, 1 }, - { 16000, 2 }, - { 22050, 3 }, - { 24000, 3 }, - { 32000, 4 }, - { 44100, 5 }, - { 48000, 5 }, -}; - -static struct { - int div; /* *10 due to .5s */ - int bclk_div; -} bclk_divs[] = { - { 10, 0 }, - { 15, 1 }, - { 20, 2 }, - { 30, 3 }, - { 40, 4 }, - { 55, 5 }, - { 60, 6 }, - { 80, 7 }, - { 110, 8 }, - { 120, 9 }, - { 160, 10 }, - { 220, 11 }, - { 240, 12 }, - { 320, 13 }, - { 440, 14 }, - { 480, 15 }, -}; - -struct wm8993_priv { - u16 reg_cache[WM8993_REGISTER_COUNT]; - struct wm8993_platform_data pdata; - struct snd_soc_codec codec; - int master; - int sysclk_source; - int tdm_slots; - int tdm_width; - unsigned int mclk_rate; - unsigned int sysclk_rate; - unsigned int fs; - unsigned int bclk; - int class_w_users; - unsigned int fll_fref; - unsigned int fll_fout; -}; - -static unsigned int wm8993_read_hw(struct snd_soc_codec *codec, u8 reg) -{ - struct i2c_msg xfer[2]; - u16 data; - int ret; - struct i2c_client *i2c = codec->control_data; - - /* Write register */ - xfer[0].addr = i2c->addr; - xfer[0].flags = 0; - xfer[0].len = 1; - xfer[0].buf = ® - - /* Read data */ - xfer[1].addr = i2c->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = 2; - xfer[1].buf = (u8 *)&data; - - ret = i2c_transfer(i2c->adapter, xfer, 2); - if (ret != 2) { - dev_err(codec->dev, "Failed to read 0x%x: %d\n", reg, ret); - return 0; - } - - return (data >> 8) | ((data & 0xff) << 8); -} - -static int wm8993_volatile(unsigned int reg) -{ - switch (reg) { - case WM8993_SOFTWARE_RESET: - case WM8993_DC_SERVO_0: - case WM8993_DC_SERVO_READBACK_0: - case WM8993_DC_SERVO_READBACK_1: - case WM8993_DC_SERVO_READBACK_2: - return 1; - default: - return 0; - } -} - -static unsigned int wm8993_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *reg_cache = codec->reg_cache; - - BUG_ON(reg > WM8993_MAX_REGISTER); - - if (wm8993_volatile(reg)) - return wm8993_read_hw(codec, reg); - else - return reg_cache[reg]; -} - -static int wm8993_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u16 *reg_cache = codec->reg_cache; - u8 data[3]; - int ret; - - BUG_ON(reg > WM8993_MAX_REGISTER); - - /* data is - * D15..D9 WM8993 register offset - * D8...D0 register data - */ - data[0] = reg; - data[1] = value >> 8; - data[2] = value & 0x00ff; - - if (!wm8993_volatile(reg)) - reg_cache[reg] = value; - - ret = codec->hw_write(codec->control_data, data, 3); - - if (ret == 3) - return 0; - if (ret < 0) - return ret; - return -EIO; -} - -struct _fll_div { - u16 fll_fratio; - u16 fll_outdiv; - u16 fll_clk_ref_div; - u16 n; - u16 k; -}; - -/* The size in bits of the FLL divide multiplied by 10 - * to allow rounding later */ -#define FIXED_FLL_SIZE ((1 << 16) * 10) - -static struct { - unsigned int min; - unsigned int max; - u16 fll_fratio; - int ratio; -} fll_fratios[] = { - { 0, 64000, 4, 16 }, - { 64000, 128000, 3, 8 }, - { 128000, 256000, 2, 4 }, - { 256000, 1000000, 1, 2 }, - { 1000000, 13500000, 0, 1 }, -}; - -static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, - unsigned int Fout) -{ - u64 Kpart; - unsigned int K, Ndiv, Nmod, target; - unsigned int div; - int i; - - /* Fref must be <=13.5MHz */ - div = 1; - fll_div->fll_clk_ref_div = 0; - while ((Fref / div) > 13500000) { - div *= 2; - fll_div->fll_clk_ref_div++; - - if (div > 8) { - pr_err("Can't scale %dMHz input down to <=13.5MHz\n", - Fref); - return -EINVAL; - } - } - - pr_debug("Fref=%u Fout=%u\n", Fref, Fout); - - /* Apply the division for our remaining calculations */ - Fref /= div; - - /* Fvco should be 90-100MHz; don't check the upper bound */ - div = 0; - target = Fout * 2; - while (target < 90000000) { - div++; - target *= 2; - if (div > 7) { - pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n", - Fout); - return -EINVAL; - } - } - fll_div->fll_outdiv = div; - - pr_debug("Fvco=%dHz\n", target); - - /* Find an appropraite FLL_FRATIO and factor it out of the target */ - for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { - if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { - fll_div->fll_fratio = fll_fratios[i].fll_fratio; - target /= fll_fratios[i].ratio; - break; - } - } - if (i == ARRAY_SIZE(fll_fratios)) { - pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); - return -EINVAL; - } - - /* Now, calculate N.K */ - Ndiv = target / Fref; - - fll_div->n = Ndiv; - Nmod = target % Fref; - pr_debug("Nmod=%d\n", Nmod); - - /* Calculate fractional part - scale up so we can round. */ - Kpart = FIXED_FLL_SIZE * (long long)Nmod; - - do_div(Kpart, Fref); - - K = Kpart & 0xFFFFFFFF; - - if ((K % 10) >= 5) - K += 5; - - /* Move down to proper range now rounding is done */ - fll_div->k = K / 10; - - pr_debug("N=%x K=%x FLL_FRATIO=%x FLL_OUTDIV=%x FLL_CLK_REF_DIV=%x\n", - fll_div->n, fll_div->k, - fll_div->fll_fratio, fll_div->fll_outdiv, - fll_div->fll_clk_ref_div); - - return 0; -} - -static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, - unsigned int Fref, unsigned int Fout) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = codec->private_data; - u16 reg1, reg4, reg5; - struct _fll_div fll_div; - int ret; - - /* Any change? */ - if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout) - return 0; - - /* Disable the FLL */ - if (Fout == 0) { - dev_dbg(codec->dev, "FLL disabled\n"); - wm8993->fll_fref = 0; - wm8993->fll_fout = 0; - - reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1); - reg1 &= ~WM8993_FLL_ENA; - wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); - - return 0; - } - - ret = fll_factors(&fll_div, Fref, Fout); - if (ret != 0) - return ret; - - reg5 = wm8993_read(codec, WM8993_FLL_CONTROL_5); - reg5 &= ~WM8993_FLL_CLK_SRC_MASK; - - switch (fll_id) { - case WM8993_FLL_MCLK: - break; - - case WM8993_FLL_LRCLK: - reg5 |= 1; - break; - - case WM8993_FLL_BCLK: - reg5 |= 2; - break; - - default: - dev_err(codec->dev, "Unknown FLL ID %d\n", fll_id); - return -EINVAL; - } - - /* Any FLL configuration change requires that the FLL be - * disabled first. */ - reg1 = wm8993_read(codec, WM8993_FLL_CONTROL_1); - reg1 &= ~WM8993_FLL_ENA; - wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); - - /* Apply the configuration */ - if (fll_div.k) - reg1 |= WM8993_FLL_FRAC_MASK; - else - reg1 &= ~WM8993_FLL_FRAC_MASK; - wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1); - - wm8993_write(codec, WM8993_FLL_CONTROL_2, - (fll_div.fll_outdiv << WM8993_FLL_OUTDIV_SHIFT) | - (fll_div.fll_fratio << WM8993_FLL_FRATIO_SHIFT)); - wm8993_write(codec, WM8993_FLL_CONTROL_3, fll_div.k); - - reg4 = wm8993_read(codec, WM8993_FLL_CONTROL_4); - reg4 &= ~WM8993_FLL_N_MASK; - reg4 |= fll_div.n << WM8993_FLL_N_SHIFT; - wm8993_write(codec, WM8993_FLL_CONTROL_4, reg4); - - reg5 &= ~WM8993_FLL_CLK_REF_DIV_MASK; - reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT; - wm8993_write(codec, WM8993_FLL_CONTROL_5, reg5); - - /* Enable the FLL */ - wm8993_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA); - - dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); - - wm8993->fll_fref = Fref; - wm8993->fll_fout = Fout; - - return 0; -} - -static int configure_clock(struct snd_soc_codec *codec) -{ - struct wm8993_priv *wm8993 = codec->private_data; - unsigned int reg; - - /* This should be done on init() for bypass paths */ - switch (wm8993->sysclk_source) { - case WM8993_SYSCLK_MCLK: - dev_dbg(codec->dev, "Using %dHz MCLK\n", wm8993->mclk_rate); - - reg = wm8993_read(codec, WM8993_CLOCKING_2); - reg &= ~(WM8993_MCLK_DIV | WM8993_SYSCLK_SRC); - if (wm8993->mclk_rate > 13500000) { - reg |= WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->mclk_rate / 2; - } else { - reg &= ~WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->mclk_rate; - } - wm8993_write(codec, WM8993_CLOCKING_2, reg); - break; - - case WM8993_SYSCLK_FLL: - dev_dbg(codec->dev, "Using %dHz FLL clock\n", - wm8993->fll_fout); - - reg = wm8993_read(codec, WM8993_CLOCKING_2); - reg |= WM8993_SYSCLK_SRC; - if (wm8993->fll_fout > 13500000) { - reg |= WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->fll_fout / 2; - } else { - reg &= ~WM8993_MCLK_DIV; - wm8993->sysclk_rate = wm8993->fll_fout; - } - wm8993_write(codec, WM8993_CLOCKING_2, reg); - break; - - default: - dev_err(codec->dev, "System clock not configured\n"); - return -EINVAL; - } - - dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm8993->sysclk_rate); - - return 0; -} - -static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0); -static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0); -static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0); -static const unsigned int drc_max_tlv[] = { - TLV_DB_RANGE_HEAD(4), - 0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0), - 3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(drc_qr_tlv, 1200, 600, 0); -static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0); -static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); -static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); -static const DECLARE_TLV_DB_SCALE(dac_boost_tlv, 0, 600, 0); - -static const char *dac_deemph_text[] = { - "None", - "32kHz", - "44.1kHz", - "48kHz", -}; - -static const struct soc_enum dac_deemph = - SOC_ENUM_SINGLE(WM8993_DAC_CTRL, 4, 4, dac_deemph_text); - -static const char *adc_hpf_text[] = { - "Hi-Fi", - "Voice 1", - "Voice 2", - "Voice 3", -}; - -static const struct soc_enum adc_hpf = - SOC_ENUM_SINGLE(WM8993_ADC_CTRL, 5, 4, adc_hpf_text); - -static const char *drc_path_text[] = { - "ADC", - "DAC" -}; - -static const struct soc_enum drc_path = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 14, 2, drc_path_text); - -static const char *drc_r0_text[] = { - "1", - "1/2", - "1/4", - "1/8", - "1/16", - "0", -}; - -static const struct soc_enum drc_r0 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 8, 6, drc_r0_text); - -static const char *drc_r1_text[] = { - "1", - "1/2", - "1/4", - "1/8", - "0", -}; - -static const struct soc_enum drc_r1 = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_4, 13, 5, drc_r1_text); - -static const char *drc_attack_text[] = { - "Reserved", - "181us", - "363us", - "726us", - "1.45ms", - "2.9ms", - "5.8ms", - "11.6ms", - "23.2ms", - "46.4ms", - "92.8ms", - "185.6ms", -}; - -static const struct soc_enum drc_attack = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 12, 12, drc_attack_text); - -static const char *drc_decay_text[] = { - "186ms", - "372ms", - "743ms", - "1.49s", - "2.97ms", - "5.94ms", - "11.89ms", - "23.78ms", - "47.56ms", -}; - -static const struct soc_enum drc_decay = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_2, 8, 9, drc_decay_text); - -static const char *drc_ff_text[] = { - "5 samples", - "9 samples", -}; - -static const struct soc_enum drc_ff = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 7, 2, drc_ff_text); - -static const char *drc_qr_rate_text[] = { - "0.725ms", - "1.45ms", - "5.8ms", -}; - -static const struct soc_enum drc_qr_rate = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_3, 0, 3, drc_qr_rate_text); - -static const char *drc_smooth_text[] = { - "Low", - "Medium", - "High", -}; - -static const struct soc_enum drc_smooth = - SOC_ENUM_SINGLE(WM8993_DRC_CONTROL_1, 4, 3, drc_smooth_text); - -static const struct snd_kcontrol_new wm8993_snd_controls[] = { -SOC_DOUBLE_TLV("Digital Sidetone Volume", WM8993_DIGITAL_SIDE_TONE, - 5, 9, 12, 0, sidetone_tlv), - -SOC_SINGLE("DRC Switch", WM8993_DRC_CONTROL_1, 15, 1, 0), -SOC_ENUM("DRC Path", drc_path), -SOC_SINGLE_TLV("DRC Compressor Threashold Volume", WM8993_DRC_CONTROL_2, - 2, 60, 1, drc_comp_threash), -SOC_SINGLE_TLV("DRC Compressor Amplitude Volume", WM8993_DRC_CONTROL_3, - 11, 30, 1, drc_comp_amp), -SOC_ENUM("DRC R0", drc_r0), -SOC_ENUM("DRC R1", drc_r1), -SOC_SINGLE_TLV("DRC Minimum Volume", WM8993_DRC_CONTROL_1, 2, 3, 1, - drc_min_tlv), -SOC_SINGLE_TLV("DRC Maximum Volume", WM8993_DRC_CONTROL_1, 0, 3, 0, - drc_max_tlv), -SOC_ENUM("DRC Attack Rate", drc_attack), -SOC_ENUM("DRC Decay Rate", drc_decay), -SOC_ENUM("DRC FF Delay", drc_ff), -SOC_SINGLE("DRC Anti-clip Switch", WM8993_DRC_CONTROL_1, 9, 1, 0), -SOC_SINGLE("DRC Quick Release Switch", WM8993_DRC_CONTROL_1, 10, 1, 0), -SOC_SINGLE_TLV("DRC Quick Release Volume", WM8993_DRC_CONTROL_3, 2, 3, 0, - drc_qr_tlv), -SOC_ENUM("DRC Quick Release Rate", drc_qr_rate), -SOC_SINGLE("DRC Smoothing Switch", WM8993_DRC_CONTROL_1, 11, 1, 0), -SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8993_DRC_CONTROL_1, 8, 1, 0), -SOC_ENUM("DRC Smoothing Hysteresis Threashold", drc_smooth), -SOC_SINGLE_TLV("DRC Startup Volume", WM8993_DRC_CONTROL_4, 8, 18, 0, - drc_startup_tlv), - -SOC_SINGLE("EQ Switch", WM8993_EQ1, 0, 1, 0), - -SOC_DOUBLE_R_TLV("Capture Volume", WM8993_LEFT_ADC_DIGITAL_VOLUME, - WM8993_RIGHT_ADC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv), -SOC_SINGLE("ADC High Pass Filter Switch", WM8993_ADC_CTRL, 8, 1, 0), -SOC_ENUM("ADC High Pass Filter Mode", adc_hpf), - -SOC_DOUBLE_R_TLV("Playback Volume", WM8993_LEFT_DAC_DIGITAL_VOLUME, - WM8993_RIGHT_DAC_DIGITAL_VOLUME, 1, 96, 0, digital_tlv), -SOC_SINGLE_TLV("Playback Boost Volume", WM8993_AUDIO_INTERFACE_2, 10, 3, 0, - dac_boost_tlv), -SOC_ENUM("DAC Deemphasis", dac_deemph), - -SOC_SINGLE_TLV("SPKL DAC Volume", WM8993_SPKMIXL_ATTENUATION, - 2, 1, 1, wm_hubs_spkmix_tlv), - -SOC_SINGLE_TLV("SPKR DAC Volume", WM8993_SPKMIXR_ATTENUATION, - 2, 1, 1, wm_hubs_spkmix_tlv), -}; - -static const struct snd_kcontrol_new wm8993_eq_controls[] = { -SOC_SINGLE_TLV("EQ1 Volume", WM8993_EQ2, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ2 Volume", WM8993_EQ3, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ3 Volume", WM8993_EQ4, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ4 Volume", WM8993_EQ5, 0, 24, 0, eq_tlv), -SOC_SINGLE_TLV("EQ5 Volume", WM8993_EQ6, 0, 24, 0, eq_tlv), -}; - -static int clk_sys_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - return configure_clock(codec); - - case SND_SOC_DAPM_POST_PMD: - break; - } - - return 0; -} - -/* - * When used with DAC outputs only the WM8993 charge pump supports - * operation in class W mode, providing very low power consumption - * when used with digital sources. Enable and disable this mode - * automatically depending on the mixer configuration. - * - * Currently the only supported paths are the direct DAC->headphone - * paths (which provide minimum power consumption anyway). - */ -static int class_w_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); - struct snd_soc_codec *codec = widget->codec; - struct wm8993_priv *wm8993 = codec->private_data; - int ret; - - /* Turn it off if we're using the main output mixer */ - if (ucontrol->value.integer.value[0] == 0) { - if (wm8993->class_w_users == 0) { - dev_dbg(codec->dev, "Disabling Class W\n"); - snd_soc_update_bits(codec, WM8993_CLASS_W_0, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V, - 0); - } - wm8993->class_w_users++; - } - - /* Implement the change */ - ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); - - /* Enable it if we're using the direct DAC path */ - if (ucontrol->value.integer.value[0] == 1) { - if (wm8993->class_w_users == 1) { - dev_dbg(codec->dev, "Enabling Class W\n"); - snd_soc_update_bits(codec, WM8993_CLASS_W_0, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V, - WM8993_CP_DYN_FREQ | - WM8993_CP_DYN_V); - } - wm8993->class_w_users--; - } - - dev_dbg(codec->dev, "Indirect DAC use count now %d\n", - wm8993->class_w_users); - - return ret; -} - -#define SOC_DAPM_ENUM_W(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_double, \ - .put = class_w_put, \ - .private_value = (unsigned long)&xenum } - -static const char *hp_mux_text[] = { - "Mixer", - "DAC", -}; - -static const struct soc_enum hpl_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER1, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpl_mux = - SOC_DAPM_ENUM_W("Left Headphone Mux", hpl_enum); - -static const struct soc_enum hpr_enum = - SOC_ENUM_SINGLE(WM8993_OUTPUT_MIXER2, 8, 2, hp_mux_text); - -static const struct snd_kcontrol_new hpr_mux = - SOC_DAPM_ENUM_W("Right Headphone Mux", hpr_enum); - -static const struct snd_kcontrol_new left_speaker_mixer[] = { -SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 7, 1, 0), -SOC_DAPM_SINGLE("IN1LP Switch", WM8993_SPEAKER_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 3, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 6, 1, 0), -}; - -static const struct snd_kcontrol_new right_speaker_mixer[] = { -SOC_DAPM_SINGLE("Input Switch", WM8993_SPEAKER_MIXER, 6, 1, 0), -SOC_DAPM_SINGLE("IN1RP Switch", WM8993_SPEAKER_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_SPEAKER_MIXER, 2, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_SPEAKER_MIXER, 0, 1, 0), -}; - -static const char *aif_text[] = { - "Left", "Right" -}; - -static const struct soc_enum aifoutl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 15, 2, aif_text); - -static const struct snd_kcontrol_new aifoutl_mux = - SOC_DAPM_ENUM("AIFOUTL Mux", aifoutl_enum); - -static const struct soc_enum aifoutr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_1, 14, 2, aif_text); - -static const struct snd_kcontrol_new aifoutr_mux = - SOC_DAPM_ENUM("AIFOUTR Mux", aifoutr_enum); - -static const struct soc_enum aifinl_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 15, 2, aif_text); - -static const struct snd_kcontrol_new aifinl_mux = - SOC_DAPM_ENUM("AIFINL Mux", aifinl_enum); - -static const struct soc_enum aifinr_enum = - SOC_ENUM_SINGLE(WM8993_AUDIO_INTERFACE_2, 14, 2, aif_text); - -static const struct snd_kcontrol_new aifinr_mux = - SOC_DAPM_ENUM("AIFINR Mux", aifinr_enum); - -static const char *sidetone_text[] = { - "None", "Left", "Right" -}; - -static const struct soc_enum sidetonel_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 2, 3, sidetone_text); - -static const struct snd_kcontrol_new sidetonel_mux = - SOC_DAPM_ENUM("Left Sidetone", sidetonel_enum); - -static const struct soc_enum sidetoner_enum = - SOC_ENUM_SINGLE(WM8993_DIGITAL_SIDE_TONE, 0, 3, sidetone_text); - -static const struct snd_kcontrol_new sidetoner_mux = - SOC_DAPM_ENUM("Right Sidetone", sidetoner_enum); - -static const struct snd_soc_dapm_widget wm8993_dapm_widgets[] = { -SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), -SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), -SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), - -SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), -SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), - -SND_SOC_DAPM_MUX("AIFOUTL Mux", SND_SOC_NOPM, 0, 0, &aifoutl_mux), -SND_SOC_DAPM_MUX("AIFOUTR Mux", SND_SOC_NOPM, 0, 0, &aifoutr_mux), - -SND_SOC_DAPM_AIF_OUT("AIFOUTL", "Capture", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_OUT("AIFOUTR", "Capture", 1, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_AIF_IN("AIFINL", "Playback", 0, SND_SOC_NOPM, 0, 0), -SND_SOC_DAPM_AIF_IN("AIFINR", "Playback", 1, SND_SOC_NOPM, 0, 0), - -SND_SOC_DAPM_MUX("DACL Mux", SND_SOC_NOPM, 0, 0, &aifinl_mux), -SND_SOC_DAPM_MUX("DACR Mux", SND_SOC_NOPM, 0, 0, &aifinr_mux), - -SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &sidetonel_mux), -SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &sidetoner_mux), - -SND_SOC_DAPM_DAC("DACL", NULL, WM8993_POWER_MANAGEMENT_3, 1, 0), -SND_SOC_DAPM_DAC("DACR", NULL, WM8993_POWER_MANAGEMENT_3, 0, 0), - -SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0, &hpl_mux), -SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0, &hpr_mux), - -SND_SOC_DAPM_MIXER("SPKL", WM8993_POWER_MANAGEMENT_3, 8, 0, - left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), -SND_SOC_DAPM_MIXER("SPKR", WM8993_POWER_MANAGEMENT_3, 9, 0, - right_speaker_mixer, ARRAY_SIZE(right_speaker_mixer)), - -}; - -static const struct snd_soc_dapm_route routes[] = { - { "ADCL", NULL, "CLK_SYS" }, - { "ADCL", NULL, "CLK_DSP" }, - { "ADCR", NULL, "CLK_SYS" }, - { "ADCR", NULL, "CLK_DSP" }, - - { "AIFOUTL Mux", "Left", "ADCL" }, - { "AIFOUTL Mux", "Right", "ADCR" }, - { "AIFOUTR Mux", "Left", "ADCL" }, - { "AIFOUTR Mux", "Right", "ADCR" }, - - { "AIFOUTL", NULL, "AIFOUTL Mux" }, - { "AIFOUTR", NULL, "AIFOUTR Mux" }, - - { "DACL Mux", "Left", "AIFINL" }, - { "DACL Mux", "Right", "AIFINR" }, - { "DACR Mux", "Left", "AIFINL" }, - { "DACR Mux", "Right", "AIFINR" }, - - { "DACL Sidetone", "Left", "ADCL" }, - { "DACL Sidetone", "Right", "ADCR" }, - { "DACR Sidetone", "Left", "ADCL" }, - { "DACR Sidetone", "Right", "ADCR" }, - - { "DACL", NULL, "CLK_SYS" }, - { "DACL", NULL, "CLK_DSP" }, - { "DACL", NULL, "DACL Mux" }, - { "DACL", NULL, "DACL Sidetone" }, - { "DACR", NULL, "CLK_SYS" }, - { "DACR", NULL, "CLK_DSP" }, - { "DACR", NULL, "DACR Mux" }, - { "DACR", NULL, "DACR Sidetone" }, - - { "Left Output Mixer", "DAC Switch", "DACL" }, - - { "Right Output Mixer", "DAC Switch", "DACR" }, - - { "Left Output PGA", NULL, "CLK_SYS" }, - - { "Right Output PGA", NULL, "CLK_SYS" }, - - { "SPKL", "DAC Switch", "DACL" }, - { "SPKL", NULL, "CLK_SYS" }, - - { "SPKR", "DAC Switch", "DACR" }, - { "SPKR", NULL, "CLK_SYS" }, - - { "Left Headphone Mux", "DAC", "DACL" }, - { "Right Headphone Mux", "DAC", "DACR" }, -}; - -static int wm8993_set_bias_level(struct snd_soc_codec *codec, - enum snd_soc_bias_level level) -{ - struct wm8993_priv *wm8993 = codec->private_data; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - /* VMID=2*40k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK, 0x2); - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2, - WM8993_TSHUT_ENA, WM8993_TSHUT_ENA); - break; - - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) { - /* Bring up VMID with fast soft start */ - snd_soc_update_bits(codec, WM8993_ANTIPOP2, - WM8993_STARTUP_BIAS_ENA | - WM8993_VMID_BUF_ENA | - WM8993_VMID_RAMP_MASK | - WM8993_BIAS_SRC, - WM8993_STARTUP_BIAS_ENA | - WM8993_VMID_BUF_ENA | - WM8993_VMID_RAMP_MASK | - WM8993_BIAS_SRC); - - /* If either line output is single ended we - * need the VMID buffer */ - if (!wm8993->pdata.lineout1_diff || - !wm8993->pdata.lineout2_diff) - snd_soc_update_bits(codec, WM8993_ANTIPOP1, - WM8993_LINEOUT_VMID_BUF_ENA, - WM8993_LINEOUT_VMID_BUF_ENA); - - /* VMID=2*40k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK | - WM8993_BIAS_ENA, - WM8993_BIAS_ENA | 0x2); - msleep(32); - - /* Switch to normal bias */ - snd_soc_update_bits(codec, WM8993_ANTIPOP2, - WM8993_BIAS_SRC | - WM8993_STARTUP_BIAS_ENA, 0); - } - - /* VMID=2*240k */ - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK, 0x4); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_2, - WM8993_TSHUT_ENA, 0); - break; - - case SND_SOC_BIAS_OFF: - snd_soc_update_bits(codec, WM8993_ANTIPOP1, - WM8993_LINEOUT_VMID_BUF_ENA, 0); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA, - 0); - break; - } - - codec->bias_level = level; - - return 0; -} - -static int wm8993_set_sysclk(struct snd_soc_dai *codec_dai, - int clk_id, unsigned int freq, int dir) -{ - struct snd_soc_codec *codec = codec_dai->codec; - struct wm8993_priv *wm8993 = codec->private_data; - - switch (clk_id) { - case WM8993_SYSCLK_MCLK: - wm8993->mclk_rate = freq; - case WM8993_SYSCLK_FLL: - wm8993->sysclk_source = clk_id; - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int wm8993_set_dai_fmt(struct snd_soc_dai *dai, - unsigned int fmt) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = codec->private_data; - unsigned int aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1); - unsigned int aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4); - - aif1 &= ~(WM8993_BCLK_DIR | WM8993_AIF_BCLK_INV | - WM8993_AIF_LRCLK_INV | WM8993_AIF_FMT_MASK); - aif4 &= ~WM8993_LRCLK_DIR; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - wm8993->master = 0; - break; - case SND_SOC_DAIFMT_CBS_CFM: - aif4 |= WM8993_LRCLK_DIR; - wm8993->master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFS: - aif1 |= WM8993_BCLK_DIR; - wm8993->master = 1; - break; - case SND_SOC_DAIFMT_CBM_CFM: - aif1 |= WM8993_BCLK_DIR; - aif4 |= WM8993_LRCLK_DIR; - wm8993->master = 1; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_B: - aif1 |= WM8993_AIF_LRCLK_INV; - case SND_SOC_DAIFMT_DSP_A: - aif1 |= 0x18; - break; - case SND_SOC_DAIFMT_I2S: - aif1 |= 0x10; - break; - case SND_SOC_DAIFMT_RIGHT_J: - break; - case SND_SOC_DAIFMT_LEFT_J: - aif1 |= 0x8; - break; - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_DSP_A: - case SND_SOC_DAIFMT_DSP_B: - /* frame inversion not valid for DSP modes */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8993_AIF_BCLK_INV; - break; - default: - return -EINVAL; - } - break; - - case SND_SOC_DAIFMT_I2S: - case SND_SOC_DAIFMT_RIGHT_J: - case SND_SOC_DAIFMT_LEFT_J: - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - break; - case SND_SOC_DAIFMT_IB_IF: - aif1 |= WM8993_AIF_BCLK_INV | WM8993_AIF_LRCLK_INV; - break; - case SND_SOC_DAIFMT_IB_NF: - aif1 |= WM8993_AIF_BCLK_INV; - break; - case SND_SOC_DAIFMT_NB_IF: - aif1 |= WM8993_AIF_LRCLK_INV; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); - wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); - - return 0; -} - -static int wm8993_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = codec->private_data; - int ret, i, best, best_val, cur_val; - unsigned int clocking1, clocking3, aif1, aif4; - - clocking1 = wm8993_read(codec, WM8993_CLOCKING_1); - clocking1 &= ~WM8993_BCLK_DIV_MASK; - - clocking3 = wm8993_read(codec, WM8993_CLOCKING_3); - clocking3 &= ~(WM8993_CLK_SYS_RATE_MASK | WM8993_SAMPLE_RATE_MASK); - - aif1 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_1); - aif1 &= ~WM8993_AIF_WL_MASK; - - aif4 = wm8993_read(codec, WM8993_AUDIO_INTERFACE_4); - aif4 &= ~WM8993_LRCLK_RATE_MASK; - - /* What BCLK do we need? */ - wm8993->fs = params_rate(params); - wm8993->bclk = 2 * wm8993->fs; - if (wm8993->tdm_slots) { - dev_dbg(codec->dev, "Configuring for %d %d bit TDM slots\n", - wm8993->tdm_slots, wm8993->tdm_width); - wm8993->bclk *= wm8993->tdm_width * wm8993->tdm_slots; - } else { - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - wm8993->bclk *= 16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - wm8993->bclk *= 20; - aif1 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S24_LE: - wm8993->bclk *= 24; - aif1 |= 0x10; - break; - case SNDRV_PCM_FORMAT_S32_LE: - wm8993->bclk *= 32; - aif1 |= 0x18; - break; - default: - return -EINVAL; - } - } - - dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm8993->bclk); - - ret = configure_clock(codec); - if (ret != 0) - return ret; - - /* Select nearest CLK_SYS_RATE */ - best = 0; - best_val = abs((wm8993->sysclk_rate / clk_sys_rates[0].ratio) - - wm8993->fs); - for (i = 1; i < ARRAY_SIZE(clk_sys_rates); i++) { - cur_val = abs((wm8993->sysclk_rate / - clk_sys_rates[i].ratio) - wm8993->fs);; - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected CLK_SYS_RATIO of %d\n", - clk_sys_rates[best].ratio); - clocking3 |= (clk_sys_rates[best].clk_sys_rate - << WM8993_CLK_SYS_RATE_SHIFT); - - /* SAMPLE_RATE */ - best = 0; - best_val = abs(wm8993->fs - sample_rates[0].rate); - for (i = 1; i < ARRAY_SIZE(sample_rates); i++) { - /* Closest match */ - cur_val = abs(wm8993->fs - sample_rates[i].rate); - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - dev_dbg(codec->dev, "Selected SAMPLE_RATE of %dHz\n", - sample_rates[best].rate); - clocking3 |= (sample_rates[best].sample_rate - << WM8993_SAMPLE_RATE_SHIFT); - - /* BCLK_DIV */ - best = 0; - best_val = INT_MAX; - for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { - cur_val = ((wm8993->sysclk_rate * 10) / bclk_divs[i].div) - - wm8993->bclk; - if (cur_val < 0) /* Table is sorted */ - break; - if (cur_val < best_val) { - best = i; - best_val = cur_val; - } - } - wm8993->bclk = (wm8993->sysclk_rate * 10) / bclk_divs[best].div; - dev_dbg(codec->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n", - bclk_divs[best].div, wm8993->bclk); - clocking1 |= bclk_divs[best].bclk_div << WM8993_BCLK_DIV_SHIFT; - - /* LRCLK is a simple fraction of BCLK */ - dev_dbg(codec->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs); - aif4 |= wm8993->bclk / wm8993->fs; - - wm8993_write(codec, WM8993_CLOCKING_1, clocking1); - wm8993_write(codec, WM8993_CLOCKING_3, clocking3); - wm8993_write(codec, WM8993_AUDIO_INTERFACE_1, aif1); - wm8993_write(codec, WM8993_AUDIO_INTERFACE_4, aif4); - - /* ReTune Mobile? */ - if (wm8993->pdata.num_retune_configs) { - u16 eq1 = wm8993_read(codec, WM8993_EQ1); - struct wm8993_retune_mobile_setting *s; - - best = 0; - best_val = abs(wm8993->pdata.retune_configs[0].rate - - wm8993->fs); - for (i = 0; i < wm8993->pdata.num_retune_configs; i++) { - cur_val = abs(wm8993->pdata.retune_configs[i].rate - - wm8993->fs); - if (cur_val < best_val) { - best_val = cur_val; - best = i; - } - } - s = &wm8993->pdata.retune_configs[best]; - - dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", - s->name, s->rate); - - /* Disable EQ while we reconfigure */ - snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, 0); - - for (i = 1; i < ARRAY_SIZE(s->config); i++) - wm8993_write(codec, WM8993_EQ1 + i, s->config[i]); - - snd_soc_update_bits(codec, WM8993_EQ1, WM8993_EQ_ENA, eq1); - } - - return 0; -} - -static int wm8993_digital_mute(struct snd_soc_dai *codec_dai, int mute) -{ - struct snd_soc_codec *codec = codec_dai->codec; - unsigned int reg; - - reg = wm8993_read(codec, WM8993_DAC_CTRL); - - if (mute) - reg |= WM8993_DAC_MUTE; - else - reg &= ~WM8993_DAC_MUTE; - - wm8993_write(codec, WM8993_DAC_CTRL, reg); - - return 0; -} - -static int wm8993_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, - unsigned int rx_mask, int slots, int slot_width) -{ - struct snd_soc_codec *codec = dai->codec; - struct wm8993_priv *wm8993 = codec->private_data; - int aif1 = 0; - int aif2 = 0; - - /* Don't need to validate anything if we're turning off TDM */ - if (slots == 0) { - wm8993->tdm_slots = 0; - goto out; - } - - /* Note that we allow configurations we can't handle ourselves - - * for example, we can generate clocks for slots 2 and up even if - * we can't use those slots ourselves. - */ - aif1 |= WM8993_AIFADC_TDM; - aif2 |= WM8993_AIFDAC_TDM; - - switch (rx_mask) { - case 3: - break; - case 0xc: - aif1 |= WM8993_AIFADC_TDM_CHAN; - break; - default: - return -EINVAL; - } - - - switch (tx_mask) { - case 3: - break; - case 0xc: - aif2 |= WM8993_AIFDAC_TDM_CHAN; - break; - default: - return -EINVAL; - } - -out: - wm8993->tdm_width = slot_width; - wm8993->tdm_slots = slots / 2; - - snd_soc_update_bits(codec, WM8993_AUDIO_INTERFACE_1, - WM8993_AIFADC_TDM | WM8993_AIFADC_TDM_CHAN, aif1); - snd_soc_update_bits(codec, WM8993_AUDIO_INTERFACE_2, - WM8993_AIFDAC_TDM | WM8993_AIFDAC_TDM_CHAN, aif2); - - return 0; -} - -static struct snd_soc_dai_ops wm8993_ops = { - .set_sysclk = wm8993_set_sysclk, - .set_fmt = wm8993_set_dai_fmt, - .hw_params = wm8993_hw_params, - .digital_mute = wm8993_digital_mute, - .set_pll = wm8993_set_fll, - .set_tdm_slot = wm8993_set_tdm_slot, -}; - -#define WM8993_RATES SNDRV_PCM_RATE_8000_48000 - -#define WM8993_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ - SNDRV_PCM_FMTBIT_S20_3LE |\ - SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S32_LE) - -struct snd_soc_dai wm8993_dai = { - .name = "WM8993", - .playback = { - .stream_name = "Playback", - .channels_min = 1, - .channels_max = 2, - .rates = WM8993_RATES, - .formats = WM8993_FORMATS, - }, - .capture = { - .stream_name = "Capture", - .channels_min = 1, - .channels_max = 2, - .rates = WM8993_RATES, - .formats = WM8993_FORMATS, - }, - .ops = &wm8993_ops, - .symmetric_rates = 1, -}; -EXPORT_SYMBOL_GPL(wm8993_dai); - -static struct snd_soc_codec *wm8993_codec; - -static int wm8993_probe(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_codec *codec; - struct wm8993_priv *wm8993; - int ret = 0; - - if (!wm8993_codec) { - dev_err(&pdev->dev, "I2C device not yet probed\n"); - goto err; - } - - socdev->card->codec = wm8993_codec; - codec = wm8993_codec; - wm8993 = codec->private_data; - - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); - if (ret < 0) { - dev_err(codec->dev, "failed to create pcms\n"); - goto err; - } - - snd_soc_add_controls(codec, wm8993_snd_controls, - ARRAY_SIZE(wm8993_snd_controls)); - if (wm8993->pdata.num_retune_configs != 0) { - dev_dbg(codec->dev, "Using ReTune Mobile\n"); - } else { - dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n"); - snd_soc_add_controls(codec, wm8993_eq_controls, - ARRAY_SIZE(wm8993_eq_controls)); - } - - snd_soc_dapm_new_controls(codec, wm8993_dapm_widgets, - ARRAY_SIZE(wm8993_dapm_widgets)); - wm_hubs_add_analogue_controls(codec); - - snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); - wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, - wm8993->pdata.lineout2_diff); - - snd_soc_dapm_new_widgets(codec); - - ret = snd_soc_init_card(socdev); - if (ret < 0) { - dev_err(codec->dev, "failed to register card\n"); - goto card_err; - } - - return ret; - -card_err: - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); -err: - return ret; -} - -static int wm8993_remove(struct platform_device *pdev) -{ - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - - snd_soc_free_pcms(socdev); - snd_soc_dapm_free(socdev); - - return 0; -} - -struct snd_soc_codec_device soc_codec_dev_wm8993 = { - .probe = wm8993_probe, - .remove = wm8993_remove, -}; -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); - -static int wm8993_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) -{ - struct wm8993_priv *wm8993; - struct snd_soc_codec *codec; - unsigned int val; - int ret; - - if (wm8993_codec) { - dev_err(&i2c->dev, "A WM8993 is already registered\n"); - return -EINVAL; - } - - wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL); - if (wm8993 == NULL) - return -ENOMEM; - - codec = &wm8993->codec; - if (i2c->dev.platform_data) - memcpy(&wm8993->pdata, i2c->dev.platform_data, - sizeof(wm8993->pdata)); - - mutex_init(&codec->mutex); - INIT_LIST_HEAD(&codec->dapm_widgets); - INIT_LIST_HEAD(&codec->dapm_paths); - - codec->name = "WM8993"; - codec->read = wm8993_read; - codec->write = wm8993_write; - codec->hw_write = (hw_write_t)i2c_master_send; - codec->reg_cache = wm8993->reg_cache; - codec->reg_cache_size = ARRAY_SIZE(wm8993->reg_cache); - codec->bias_level = SND_SOC_BIAS_OFF; - codec->set_bias_level = wm8993_set_bias_level; - codec->dai = &wm8993_dai; - codec->num_dai = 1; - codec->private_data = wm8993; - - memcpy(wm8993->reg_cache, wm8993_reg_defaults, - sizeof(wm8993->reg_cache)); - - i2c_set_clientdata(i2c, wm8993); - codec->control_data = i2c; - wm8993_codec = codec; - - codec->dev = &i2c->dev; - - val = wm8993_read_hw(codec, WM8993_SOFTWARE_RESET); - if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) { - dev_err(codec->dev, "Invalid ID register value %x\n", val); - ret = -EINVAL; - goto err; - } - - ret = wm8993_write(codec, WM8993_SOFTWARE_RESET, 0xffff); - if (ret != 0) - goto err; - - /* By default we're using the output mixers */ - wm8993->class_w_users = 2; - - /* Latch volume update bits and default ZC on */ - snd_soc_update_bits(codec, WM8993_RIGHT_DAC_DIGITAL_VOLUME, - WM8993_DAC_VU, WM8993_DAC_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_ADC_DIGITAL_VOLUME, - WM8993_ADC_VU, WM8993_ADC_VU); - - /* Manualy manage the HPOUT sequencing for independent stereo - * control. */ - snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, - WM8993_HPOUT1_AUTO_PU, 0); - - /* Use automatic clock configuration */ - snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); - - if (!wm8993->pdata.lineout1_diff) - snd_soc_update_bits(codec, WM8993_LINE_MIXER1, - WM8993_LINEOUT1_MODE, - WM8993_LINEOUT1_MODE); - if (!wm8993->pdata.lineout2_diff) - snd_soc_update_bits(codec, WM8993_LINE_MIXER2, - WM8993_LINEOUT2_MODE, - WM8993_LINEOUT2_MODE); - - if (wm8993->pdata.lineout1fb) - snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, - WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB); - - if (wm8993->pdata.lineout2fb) - snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, - WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB); - - /* Apply the microphone bias/detection configuration - the - * platform data is directly applicable to the register. */ - snd_soc_update_bits(codec, WM8993_MICBIAS, - WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK | - WM8993_MICB1_LVL | WM8993_MICB2_LVL, - wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT | - wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT | - wm8993->pdata.micbias1_lvl | - wm8993->pdata.micbias1_lvl << 1); - - ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - if (ret != 0) - goto err; - - wm8993_dai.dev = codec->dev; - - ret = snd_soc_register_dai(&wm8993_dai); - if (ret != 0) - goto err_bias; - - ret = snd_soc_register_codec(codec); - - return 0; - -err_bias: - wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); -err: - wm8993_codec = NULL; - kfree(wm8993); - return ret; -} - -static int wm8993_i2c_remove(struct i2c_client *client) -{ - struct wm8993_priv *wm8993 = i2c_get_clientdata(client); - - snd_soc_unregister_codec(&wm8993->codec); - snd_soc_unregister_dai(&wm8993_dai); - - wm8993_set_bias_level(&wm8993->codec, SND_SOC_BIAS_OFF); - kfree(wm8993); - - return 0; -} - -static const struct i2c_device_id wm8993_i2c_id[] = { - { "wm8993", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); - -static struct i2c_driver wm8993_i2c_driver = { - .driver = { - .name = "WM8993", - .owner = THIS_MODULE, - }, - .probe = wm8993_i2c_probe, - .remove = wm8993_i2c_remove, - .id_table = wm8993_i2c_id, -}; - - -static int __init wm8993_modinit(void) -{ - int ret; - - ret = i2c_add_driver(&wm8993_i2c_driver); - if (ret != 0) - pr_err("WM8993: Unable to register I2C driver: %d\n", ret); - - return ret; -} -module_init(wm8993_modinit); - -static void __exit wm8993_exit(void) -{ - i2c_del_driver(&wm8993_i2c_driver); -} -module_exit(wm8993_exit); - - -MODULE_DESCRIPTION("ASoC WM8993 driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm8993.h b/trunk/sound/soc/codecs/wm8993.h deleted file mode 100644 index 30e71ca88dad..000000000000 --- a/trunk/sound/soc/codecs/wm8993.h +++ /dev/null @@ -1,2132 +0,0 @@ -#ifndef WM8993_H -#define WM8993_H - -extern struct snd_soc_dai wm8993_dai; -extern struct snd_soc_codec_device soc_codec_dev_wm8993; - -#define WM8993_SYSCLK_MCLK 1 -#define WM8993_SYSCLK_FLL 2 - -#define WM8993_FLL_MCLK 1 -#define WM8993_FLL_BCLK 2 -#define WM8993_FLL_LRCLK 3 - -/* - * Register values. - */ -#define WM8993_SOFTWARE_RESET 0x00 -#define WM8993_POWER_MANAGEMENT_1 0x01 -#define WM8993_POWER_MANAGEMENT_2 0x02 -#define WM8993_POWER_MANAGEMENT_3 0x03 -#define WM8993_AUDIO_INTERFACE_1 0x04 -#define WM8993_AUDIO_INTERFACE_2 0x05 -#define WM8993_CLOCKING_1 0x06 -#define WM8993_CLOCKING_2 0x07 -#define WM8993_AUDIO_INTERFACE_3 0x08 -#define WM8993_AUDIO_INTERFACE_4 0x09 -#define WM8993_DAC_CTRL 0x0A -#define WM8993_LEFT_DAC_DIGITAL_VOLUME 0x0B -#define WM8993_RIGHT_DAC_DIGITAL_VOLUME 0x0C -#define WM8993_DIGITAL_SIDE_TONE 0x0D -#define WM8993_ADC_CTRL 0x0E -#define WM8993_LEFT_ADC_DIGITAL_VOLUME 0x0F -#define WM8993_RIGHT_ADC_DIGITAL_VOLUME 0x10 -#define WM8993_GPIO_CTRL_1 0x12 -#define WM8993_GPIO1 0x13 -#define WM8993_IRQ_DEBOUNCE 0x14 -#define WM8993_GPIOCTRL_2 0x16 -#define WM8993_GPIO_POL 0x17 -#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME 0x18 -#define WM8993_LEFT_LINE_INPUT_3_4_VOLUME 0x19 -#define WM8993_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A -#define WM8993_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B -#define WM8993_LEFT_OUTPUT_VOLUME 0x1C -#define WM8993_RIGHT_OUTPUT_VOLUME 0x1D -#define WM8993_LINE_OUTPUTS_VOLUME 0x1E -#define WM8993_HPOUT2_VOLUME 0x1F -#define WM8993_LEFT_OPGA_VOLUME 0x20 -#define WM8993_RIGHT_OPGA_VOLUME 0x21 -#define WM8993_SPKMIXL_ATTENUATION 0x22 -#define WM8993_SPKMIXR_ATTENUATION 0x23 -#define WM8993_SPKOUT_MIXERS 0x24 -#define WM8993_SPKOUT_BOOST 0x25 -#define WM8993_SPEAKER_VOLUME_LEFT 0x26 -#define WM8993_SPEAKER_VOLUME_RIGHT 0x27 -#define WM8993_INPUT_MIXER2 0x28 -#define WM8993_INPUT_MIXER3 0x29 -#define WM8993_INPUT_MIXER4 0x2A -#define WM8993_INPUT_MIXER5 0x2B -#define WM8993_INPUT_MIXER6 0x2C -#define WM8993_OUTPUT_MIXER1 0x2D -#define WM8993_OUTPUT_MIXER2 0x2E -#define WM8993_OUTPUT_MIXER3 0x2F -#define WM8993_OUTPUT_MIXER4 0x30 -#define WM8993_OUTPUT_MIXER5 0x31 -#define WM8993_OUTPUT_MIXER6 0x32 -#define WM8993_HPOUT2_MIXER 0x33 -#define WM8993_LINE_MIXER1 0x34 -#define WM8993_LINE_MIXER2 0x35 -#define WM8993_SPEAKER_MIXER 0x36 -#define WM8993_ADDITIONAL_CONTROL 0x37 -#define WM8993_ANTIPOP1 0x38 -#define WM8993_ANTIPOP2 0x39 -#define WM8993_MICBIAS 0x3A -#define WM8993_FLL_CONTROL_1 0x3C -#define WM8993_FLL_CONTROL_2 0x3D -#define WM8993_FLL_CONTROL_3 0x3E -#define WM8993_FLL_CONTROL_4 0x3F -#define WM8993_FLL_CONTROL_5 0x40 -#define WM8993_CLOCKING_3 0x41 -#define WM8993_CLOCKING_4 0x42 -#define WM8993_MW_SLAVE_CONTROL 0x43 -#define WM8993_BUS_CONTROL_1 0x45 -#define WM8993_WRITE_SEQUENCER_0 0x46 -#define WM8993_WRITE_SEQUENCER_1 0x47 -#define WM8993_WRITE_SEQUENCER_2 0x48 -#define WM8993_WRITE_SEQUENCER_3 0x49 -#define WM8993_WRITE_SEQUENCER_4 0x4A -#define WM8993_WRITE_SEQUENCER_5 0x4B -#define WM8993_CHARGE_PUMP_1 0x4C -#define WM8993_CLASS_W_0 0x51 -#define WM8993_DC_SERVO_0 0x54 -#define WM8993_DC_SERVO_1 0x55 -#define WM8993_DC_SERVO_3 0x57 -#define WM8993_DC_SERVO_READBACK_0 0x58 -#define WM8993_DC_SERVO_READBACK_1 0x59 -#define WM8993_DC_SERVO_READBACK_2 0x5A -#define WM8993_ANALOGUE_HP_0 0x60 -#define WM8993_EQ1 0x62 -#define WM8993_EQ2 0x63 -#define WM8993_EQ3 0x64 -#define WM8993_EQ4 0x65 -#define WM8993_EQ5 0x66 -#define WM8993_EQ6 0x67 -#define WM8993_EQ7 0x68 -#define WM8993_EQ8 0x69 -#define WM8993_EQ9 0x6A -#define WM8993_EQ10 0x6B -#define WM8993_EQ11 0x6C -#define WM8993_EQ12 0x6D -#define WM8993_EQ13 0x6E -#define WM8993_EQ14 0x6F -#define WM8993_EQ15 0x70 -#define WM8993_EQ16 0x71 -#define WM8993_EQ17 0x72 -#define WM8993_EQ18 0x73 -#define WM8993_EQ19 0x74 -#define WM8993_EQ20 0x75 -#define WM8993_EQ21 0x76 -#define WM8993_EQ22 0x77 -#define WM8993_EQ23 0x78 -#define WM8993_EQ24 0x79 -#define WM8993_DIGITAL_PULLS 0x7A -#define WM8993_DRC_CONTROL_1 0x7B -#define WM8993_DRC_CONTROL_2 0x7C -#define WM8993_DRC_CONTROL_3 0x7D -#define WM8993_DRC_CONTROL_4 0x7E - -#define WM8993_REGISTER_COUNT 0x7F -#define WM8993_MAX_REGISTER 0x7E - -/* - * Field Definitions. - */ - -/* - * R0 (0x00) - Software Reset - */ -#define WM8993_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */ -#define WM8993_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */ -#define WM8993_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */ - -/* - * R1 (0x01) - Power Management (1) - */ -#define WM8993_SPKOUTR_ENA 0x2000 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_MASK 0x2000 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_SHIFT 13 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */ -#define WM8993_SPKOUTL_ENA 0x1000 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_MASK 0x1000 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_SHIFT 12 /* SPKOUTL_ENA */ -#define WM8993_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */ -#define WM8993_HPOUT2_ENA 0x0800 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_MASK 0x0800 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_SHIFT 11 /* HPOUT2_ENA */ -#define WM8993_HPOUT2_ENA_WIDTH 1 /* HPOUT2_ENA */ -#define WM8993_HPOUT1L_ENA 0x0200 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_MASK 0x0200 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_SHIFT 9 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */ -#define WM8993_HPOUT1R_ENA 0x0100 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_MASK 0x0100 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_SHIFT 8 /* HPOUT1R_ENA */ -#define WM8993_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */ -#define WM8993_MICB2_ENA 0x0020 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_MASK 0x0020 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_SHIFT 5 /* MICB2_ENA */ -#define WM8993_MICB2_ENA_WIDTH 1 /* MICB2_ENA */ -#define WM8993_MICB1_ENA 0x0010 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_MASK 0x0010 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_SHIFT 4 /* MICB1_ENA */ -#define WM8993_MICB1_ENA_WIDTH 1 /* MICB1_ENA */ -#define WM8993_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */ -#define WM8993_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */ -#define WM8993_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */ -#define WM8993_BIAS_ENA 0x0001 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_SHIFT 0 /* BIAS_ENA */ -#define WM8993_BIAS_ENA_WIDTH 1 /* BIAS_ENA */ - -/* - * R2 (0x02) - Power Management (2) - */ -#define WM8993_TSHUT_ENA 0x4000 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_MASK 0x4000 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_SHIFT 14 /* TSHUT_ENA */ -#define WM8993_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */ -#define WM8993_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_MASK 0x2000 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_SHIFT 13 /* TSHUT_OPDIS */ -#define WM8993_TSHUT_OPDIS_WIDTH 1 /* TSHUT_OPDIS */ -#define WM8993_OPCLK_ENA 0x0800 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */ -#define WM8993_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */ -#define WM8993_MIXINL_ENA 0x0200 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_MASK 0x0200 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_SHIFT 9 /* MIXINL_ENA */ -#define WM8993_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */ -#define WM8993_MIXINR_ENA 0x0100 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_MASK 0x0100 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_SHIFT 8 /* MIXINR_ENA */ -#define WM8993_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */ -#define WM8993_IN2L_ENA 0x0080 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_MASK 0x0080 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_SHIFT 7 /* IN2L_ENA */ -#define WM8993_IN2L_ENA_WIDTH 1 /* IN2L_ENA */ -#define WM8993_IN1L_ENA 0x0040 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_MASK 0x0040 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_SHIFT 6 /* IN1L_ENA */ -#define WM8993_IN1L_ENA_WIDTH 1 /* IN1L_ENA */ -#define WM8993_IN2R_ENA 0x0020 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_MASK 0x0020 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_SHIFT 5 /* IN2R_ENA */ -#define WM8993_IN2R_ENA_WIDTH 1 /* IN2R_ENA */ -#define WM8993_IN1R_ENA 0x0010 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_MASK 0x0010 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_SHIFT 4 /* IN1R_ENA */ -#define WM8993_IN1R_ENA_WIDTH 1 /* IN1R_ENA */ -#define WM8993_ADCL_ENA 0x0002 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_SHIFT 1 /* ADCL_ENA */ -#define WM8993_ADCL_ENA_WIDTH 1 /* ADCL_ENA */ -#define WM8993_ADCR_ENA 0x0001 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_SHIFT 0 /* ADCR_ENA */ -#define WM8993_ADCR_ENA_WIDTH 1 /* ADCR_ENA */ - -/* - * R3 (0x03) - Power Management (3) - */ -#define WM8993_LINEOUT1N_ENA 0x2000 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_MASK 0x2000 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_SHIFT 13 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1N_ENA_WIDTH 1 /* LINEOUT1N_ENA */ -#define WM8993_LINEOUT1P_ENA 0x1000 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_MASK 0x1000 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_SHIFT 12 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT1P_ENA_WIDTH 1 /* LINEOUT1P_ENA */ -#define WM8993_LINEOUT2N_ENA 0x0800 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_MASK 0x0800 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_SHIFT 11 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2N_ENA_WIDTH 1 /* LINEOUT2N_ENA */ -#define WM8993_LINEOUT2P_ENA 0x0400 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_MASK 0x0400 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_SHIFT 10 /* LINEOUT2P_ENA */ -#define WM8993_LINEOUT2P_ENA_WIDTH 1 /* LINEOUT2P_ENA */ -#define WM8993_SPKRVOL_ENA 0x0200 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_MASK 0x0200 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_SHIFT 9 /* SPKRVOL_ENA */ -#define WM8993_SPKRVOL_ENA_WIDTH 1 /* SPKRVOL_ENA */ -#define WM8993_SPKLVOL_ENA 0x0100 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_MASK 0x0100 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_SHIFT 8 /* SPKLVOL_ENA */ -#define WM8993_SPKLVOL_ENA_WIDTH 1 /* SPKLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA 0x0080 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_MASK 0x0080 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_SHIFT 7 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTLVOL_ENA_WIDTH 1 /* MIXOUTLVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA 0x0040 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_MASK 0x0040 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_SHIFT 6 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTRVOL_ENA_WIDTH 1 /* MIXOUTRVOL_ENA */ -#define WM8993_MIXOUTL_ENA 0x0020 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_MASK 0x0020 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_SHIFT 5 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */ -#define WM8993_MIXOUTR_ENA 0x0010 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_MASK 0x0010 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_SHIFT 4 /* MIXOUTR_ENA */ -#define WM8993_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */ -#define WM8993_DACL_ENA 0x0002 /* DACL_ENA */ -#define WM8993_DACL_ENA_MASK 0x0002 /* DACL_ENA */ -#define WM8993_DACL_ENA_SHIFT 1 /* DACL_ENA */ -#define WM8993_DACL_ENA_WIDTH 1 /* DACL_ENA */ -#define WM8993_DACR_ENA 0x0001 /* DACR_ENA */ -#define WM8993_DACR_ENA_MASK 0x0001 /* DACR_ENA */ -#define WM8993_DACR_ENA_SHIFT 0 /* DACR_ENA */ -#define WM8993_DACR_ENA_WIDTH 1 /* DACR_ENA */ - -/* - * R4 (0x04) - Audio Interface (1) - */ -#define WM8993_AIFADCL_SRC 0x8000 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_MASK 0x8000 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_SHIFT 15 /* AIFADCL_SRC */ -#define WM8993_AIFADCL_SRC_WIDTH 1 /* AIFADCL_SRC */ -#define WM8993_AIFADCR_SRC 0x4000 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_MASK 0x4000 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_SHIFT 14 /* AIFADCR_SRC */ -#define WM8993_AIFADCR_SRC_WIDTH 1 /* AIFADCR_SRC */ -#define WM8993_AIFADC_TDM 0x2000 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_MASK 0x2000 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_SHIFT 13 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_WIDTH 1 /* AIFADC_TDM */ -#define WM8993_AIFADC_TDM_CHAN 0x1000 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_MASK 0x1000 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_SHIFT 12 /* AIFADC_TDM_CHAN */ -#define WM8993_AIFADC_TDM_CHAN_WIDTH 1 /* AIFADC_TDM_CHAN */ -#define WM8993_BCLK_DIR 0x0200 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_MASK 0x0200 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_SHIFT 9 /* BCLK_DIR */ -#define WM8993_BCLK_DIR_WIDTH 1 /* BCLK_DIR */ -#define WM8993_AIF_BCLK_INV 0x0100 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_MASK 0x0100 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_SHIFT 8 /* AIF_BCLK_INV */ -#define WM8993_AIF_BCLK_INV_WIDTH 1 /* AIF_BCLK_INV */ -#define WM8993_AIF_LRCLK_INV 0x0080 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_MASK 0x0080 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_SHIFT 7 /* AIF_LRCLK_INV */ -#define WM8993_AIF_LRCLK_INV_WIDTH 1 /* AIF_LRCLK_INV */ -#define WM8993_AIF_WL_MASK 0x0060 /* AIF_WL - [6:5] */ -#define WM8993_AIF_WL_SHIFT 5 /* AIF_WL - [6:5] */ -#define WM8993_AIF_WL_WIDTH 2 /* AIF_WL - [6:5] */ -#define WM8993_AIF_FMT_MASK 0x0018 /* AIF_FMT - [4:3] */ -#define WM8993_AIF_FMT_SHIFT 3 /* AIF_FMT - [4:3] */ -#define WM8993_AIF_FMT_WIDTH 2 /* AIF_FMT - [4:3] */ - -/* - * R5 (0x05) - Audio Interface (2) - */ -#define WM8993_AIFDACL_SRC 0x8000 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_MASK 0x8000 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_SHIFT 15 /* AIFDACL_SRC */ -#define WM8993_AIFDACL_SRC_WIDTH 1 /* AIFDACL_SRC */ -#define WM8993_AIFDACR_SRC 0x4000 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_MASK 0x4000 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_SHIFT 14 /* AIFDACR_SRC */ -#define WM8993_AIFDACR_SRC_WIDTH 1 /* AIFDACR_SRC */ -#define WM8993_AIFDAC_TDM 0x2000 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_MASK 0x2000 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_SHIFT 13 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_WIDTH 1 /* AIFDAC_TDM */ -#define WM8993_AIFDAC_TDM_CHAN 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_MASK 0x1000 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_SHIFT 12 /* AIFDAC_TDM_CHAN */ -#define WM8993_AIFDAC_TDM_CHAN_WIDTH 1 /* AIFDAC_TDM_CHAN */ -#define WM8993_DAC_BOOST_MASK 0x0C00 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_BOOST_SHIFT 10 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_BOOST_WIDTH 2 /* DAC_BOOST - [11:10] */ -#define WM8993_DAC_COMP 0x0010 /* DAC_COMP */ -#define WM8993_DAC_COMP_MASK 0x0010 /* DAC_COMP */ -#define WM8993_DAC_COMP_SHIFT 4 /* DAC_COMP */ -#define WM8993_DAC_COMP_WIDTH 1 /* DAC_COMP */ -#define WM8993_DAC_COMPMODE 0x0008 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_MASK 0x0008 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_SHIFT 3 /* DAC_COMPMODE */ -#define WM8993_DAC_COMPMODE_WIDTH 1 /* DAC_COMPMODE */ -#define WM8993_ADC_COMP 0x0004 /* ADC_COMP */ -#define WM8993_ADC_COMP_MASK 0x0004 /* ADC_COMP */ -#define WM8993_ADC_COMP_SHIFT 2 /* ADC_COMP */ -#define WM8993_ADC_COMP_WIDTH 1 /* ADC_COMP */ -#define WM8993_ADC_COMPMODE 0x0002 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_MASK 0x0002 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_SHIFT 1 /* ADC_COMPMODE */ -#define WM8993_ADC_COMPMODE_WIDTH 1 /* ADC_COMPMODE */ -#define WM8993_LOOPBACK 0x0001 /* LOOPBACK */ -#define WM8993_LOOPBACK_MASK 0x0001 /* LOOPBACK */ -#define WM8993_LOOPBACK_SHIFT 0 /* LOOPBACK */ -#define WM8993_LOOPBACK_WIDTH 1 /* LOOPBACK */ - -/* - * R6 (0x06) - Clocking 1 - */ -#define WM8993_TOCLK_RATE 0x8000 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_MASK 0x8000 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_SHIFT 15 /* TOCLK_RATE */ -#define WM8993_TOCLK_RATE_WIDTH 1 /* TOCLK_RATE */ -#define WM8993_TOCLK_ENA 0x4000 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_MASK 0x4000 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_SHIFT 14 /* TOCLK_ENA */ -#define WM8993_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */ -#define WM8993_OPCLK_DIV_MASK 0x1E00 /* OPCLK_DIV - [12:9] */ -#define WM8993_OPCLK_DIV_SHIFT 9 /* OPCLK_DIV - [12:9] */ -#define WM8993_OPCLK_DIV_WIDTH 4 /* OPCLK_DIV - [12:9] */ -#define WM8993_DCLK_DIV_MASK 0x01C0 /* DCLK_DIV - [8:6] */ -#define WM8993_DCLK_DIV_SHIFT 6 /* DCLK_DIV - [8:6] */ -#define WM8993_DCLK_DIV_WIDTH 3 /* DCLK_DIV - [8:6] */ -#define WM8993_BCLK_DIV_MASK 0x001E /* BCLK_DIV - [4:1] */ -#define WM8993_BCLK_DIV_SHIFT 1 /* BCLK_DIV - [4:1] */ -#define WM8993_BCLK_DIV_WIDTH 4 /* BCLK_DIV - [4:1] */ - -/* - * R7 (0x07) - Clocking 2 - */ -#define WM8993_MCLK_SRC 0x8000 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_MASK 0x8000 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_SHIFT 15 /* MCLK_SRC */ -#define WM8993_MCLK_SRC_WIDTH 1 /* MCLK_SRC */ -#define WM8993_SYSCLK_SRC 0x4000 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_MASK 0x4000 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_SHIFT 14 /* SYSCLK_SRC */ -#define WM8993_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */ -#define WM8993_MCLK_DIV 0x1000 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_MASK 0x1000 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_SHIFT 12 /* MCLK_DIV */ -#define WM8993_MCLK_DIV_WIDTH 1 /* MCLK_DIV */ -#define WM8993_MCLK_INV 0x0400 /* MCLK_INV */ -#define WM8993_MCLK_INV_MASK 0x0400 /* MCLK_INV */ -#define WM8993_MCLK_INV_SHIFT 10 /* MCLK_INV */ -#define WM8993_MCLK_INV_WIDTH 1 /* MCLK_INV */ -#define WM8993_ADC_DIV_MASK 0x00E0 /* ADC_DIV - [7:5] */ -#define WM8993_ADC_DIV_SHIFT 5 /* ADC_DIV - [7:5] */ -#define WM8993_ADC_DIV_WIDTH 3 /* ADC_DIV - [7:5] */ -#define WM8993_DAC_DIV_MASK 0x001C /* DAC_DIV - [4:2] */ -#define WM8993_DAC_DIV_SHIFT 2 /* DAC_DIV - [4:2] */ -#define WM8993_DAC_DIV_WIDTH 3 /* DAC_DIV - [4:2] */ - -/* - * R8 (0x08) - Audio Interface (3) - */ -#define WM8993_AIF_MSTR1 0x8000 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_MASK 0x8000 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_SHIFT 15 /* AIF_MSTR1 */ -#define WM8993_AIF_MSTR1_WIDTH 1 /* AIF_MSTR1 */ - -/* - * R9 (0x09) - Audio Interface (4) - */ -#define WM8993_AIF_TRIS 0x2000 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_MASK 0x2000 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_SHIFT 13 /* AIF_TRIS */ -#define WM8993_AIF_TRIS_WIDTH 1 /* AIF_TRIS */ -#define WM8993_LRCLK_DIR 0x0800 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_MASK 0x0800 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_SHIFT 11 /* LRCLK_DIR */ -#define WM8993_LRCLK_DIR_WIDTH 1 /* LRCLK_DIR */ -#define WM8993_LRCLK_RATE_MASK 0x07FF /* LRCLK_RATE - [10:0] */ -#define WM8993_LRCLK_RATE_SHIFT 0 /* LRCLK_RATE - [10:0] */ -#define WM8993_LRCLK_RATE_WIDTH 11 /* LRCLK_RATE - [10:0] */ - -/* - * R10 (0x0A) - DAC CTRL - */ -#define WM8993_DAC_OSR128 0x2000 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_MASK 0x2000 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_SHIFT 13 /* DAC_OSR128 */ -#define WM8993_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */ -#define WM8993_DAC_MONO 0x0200 /* DAC_MONO */ -#define WM8993_DAC_MONO_MASK 0x0200 /* DAC_MONO */ -#define WM8993_DAC_MONO_SHIFT 9 /* DAC_MONO */ -#define WM8993_DAC_MONO_WIDTH 1 /* DAC_MONO */ -#define WM8993_DAC_SB_FILT 0x0100 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_MASK 0x0100 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_SHIFT 8 /* DAC_SB_FILT */ -#define WM8993_DAC_SB_FILT_WIDTH 1 /* DAC_SB_FILT */ -#define WM8993_DAC_MUTERATE 0x0080 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_MASK 0x0080 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_SHIFT 7 /* DAC_MUTERATE */ -#define WM8993_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */ -#define WM8993_DAC_UNMUTE_RAMP 0x0040 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_MASK 0x0040 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_SHIFT 6 /* DAC_UNMUTE_RAMP */ -#define WM8993_DAC_UNMUTE_RAMP_WIDTH 1 /* DAC_UNMUTE_RAMP */ -#define WM8993_DEEMPH_MASK 0x0030 /* DEEMPH - [5:4] */ -#define WM8993_DEEMPH_SHIFT 4 /* DEEMPH - [5:4] */ -#define WM8993_DEEMPH_WIDTH 2 /* DEEMPH - [5:4] */ -#define WM8993_DAC_MUTE 0x0004 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_MASK 0x0004 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_SHIFT 2 /* DAC_MUTE */ -#define WM8993_DAC_MUTE_WIDTH 1 /* DAC_MUTE */ -#define WM8993_DACL_DATINV 0x0002 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_MASK 0x0002 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_SHIFT 1 /* DACL_DATINV */ -#define WM8993_DACL_DATINV_WIDTH 1 /* DACL_DATINV */ -#define WM8993_DACR_DATINV 0x0001 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_MASK 0x0001 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_SHIFT 0 /* DACR_DATINV */ -#define WM8993_DACR_DATINV_WIDTH 1 /* DACR_DATINV */ - -/* - * R11 (0x0B) - Left DAC Digital Volume - */ -#define WM8993_DAC_VU 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8993_DACL_VOL_MASK 0x00FF /* DACL_VOL - [7:0] */ -#define WM8993_DACL_VOL_SHIFT 0 /* DACL_VOL - [7:0] */ -#define WM8993_DACL_VOL_WIDTH 8 /* DACL_VOL - [7:0] */ - -/* - * R12 (0x0C) - Right DAC Digital Volume - */ -#define WM8993_DAC_VU 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_MASK 0x0100 /* DAC_VU */ -#define WM8993_DAC_VU_SHIFT 8 /* DAC_VU */ -#define WM8993_DAC_VU_WIDTH 1 /* DAC_VU */ -#define WM8993_DACR_VOL_MASK 0x00FF /* DACR_VOL - [7:0] */ -#define WM8993_DACR_VOL_SHIFT 0 /* DACR_VOL - [7:0] */ -#define WM8993_DACR_VOL_WIDTH 8 /* DACR_VOL - [7:0] */ - -/* - * R13 (0x0D) - Digital Side Tone - */ -#define WM8993_ADCL_DAC_SVOL_MASK 0x1E00 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCL_DAC_SVOL_SHIFT 9 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCL_DAC_SVOL_WIDTH 4 /* ADCL_DAC_SVOL - [12:9] */ -#define WM8993_ADCR_DAC_SVOL_MASK 0x01E0 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADCR_DAC_SVOL_SHIFT 5 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADCR_DAC_SVOL_WIDTH 4 /* ADCR_DAC_SVOL - [8:5] */ -#define WM8993_ADC_TO_DACL_MASK 0x000C /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACL_SHIFT 2 /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACL_WIDTH 2 /* ADC_TO_DACL - [3:2] */ -#define WM8993_ADC_TO_DACR_MASK 0x0003 /* ADC_TO_DACR - [1:0] */ -#define WM8993_ADC_TO_DACR_SHIFT 0 /* ADC_TO_DACR - [1:0] */ -#define WM8993_ADC_TO_DACR_WIDTH 2 /* ADC_TO_DACR - [1:0] */ - -/* - * R14 (0x0E) - ADC CTRL - */ -#define WM8993_ADC_OSR128 0x0200 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_MASK 0x0200 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_SHIFT 9 /* ADC_OSR128 */ -#define WM8993_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */ -#define WM8993_ADC_HPF 0x0100 /* ADC_HPF */ -#define WM8993_ADC_HPF_MASK 0x0100 /* ADC_HPF */ -#define WM8993_ADC_HPF_SHIFT 8 /* ADC_HPF */ -#define WM8993_ADC_HPF_WIDTH 1 /* ADC_HPF */ -#define WM8993_ADC_HPF_CUT_MASK 0x0060 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADC_HPF_CUT_SHIFT 5 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADC_HPF_CUT_WIDTH 2 /* ADC_HPF_CUT - [6:5] */ -#define WM8993_ADCL_DATINV 0x0002 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_MASK 0x0002 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_SHIFT 1 /* ADCL_DATINV */ -#define WM8993_ADCL_DATINV_WIDTH 1 /* ADCL_DATINV */ -#define WM8993_ADCR_DATINV 0x0001 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_MASK 0x0001 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_SHIFT 0 /* ADCR_DATINV */ -#define WM8993_ADCR_DATINV_WIDTH 1 /* ADCR_DATINV */ - -/* - * R15 (0x0F) - Left ADC Digital Volume - */ -#define WM8993_ADC_VU 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8993_ADCL_VOL_MASK 0x00FF /* ADCL_VOL - [7:0] */ -#define WM8993_ADCL_VOL_SHIFT 0 /* ADCL_VOL - [7:0] */ -#define WM8993_ADCL_VOL_WIDTH 8 /* ADCL_VOL - [7:0] */ - -/* - * R16 (0x10) - Right ADC Digital Volume - */ -#define WM8993_ADC_VU 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_MASK 0x0100 /* ADC_VU */ -#define WM8993_ADC_VU_SHIFT 8 /* ADC_VU */ -#define WM8993_ADC_VU_WIDTH 1 /* ADC_VU */ -#define WM8993_ADCR_VOL_MASK 0x00FF /* ADCR_VOL - [7:0] */ -#define WM8993_ADCR_VOL_SHIFT 0 /* ADCR_VOL - [7:0] */ -#define WM8993_ADCR_VOL_WIDTH 8 /* ADCR_VOL - [7:0] */ - -/* - * R18 (0x12) - GPIO CTRL 1 - */ -#define WM8993_JD2_SC_EINT 0x8000 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_MASK 0x8000 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_SHIFT 15 /* JD2_SC_EINT */ -#define WM8993_JD2_SC_EINT_WIDTH 1 /* JD2_SC_EINT */ -#define WM8993_JD2_EINT 0x4000 /* JD2_EINT */ -#define WM8993_JD2_EINT_MASK 0x4000 /* JD2_EINT */ -#define WM8993_JD2_EINT_SHIFT 14 /* JD2_EINT */ -#define WM8993_JD2_EINT_WIDTH 1 /* JD2_EINT */ -#define WM8993_WSEQ_EINT 0x2000 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_MASK 0x2000 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_SHIFT 13 /* WSEQ_EINT */ -#define WM8993_WSEQ_EINT_WIDTH 1 /* WSEQ_EINT */ -#define WM8993_IRQ 0x1000 /* IRQ */ -#define WM8993_IRQ_MASK 0x1000 /* IRQ */ -#define WM8993_IRQ_SHIFT 12 /* IRQ */ -#define WM8993_IRQ_WIDTH 1 /* IRQ */ -#define WM8993_TEMPOK_EINT 0x0800 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_MASK 0x0800 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_SHIFT 11 /* TEMPOK_EINT */ -#define WM8993_TEMPOK_EINT_WIDTH 1 /* TEMPOK_EINT */ -#define WM8993_JD1_SC_EINT 0x0400 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_MASK 0x0400 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_SHIFT 10 /* JD1_SC_EINT */ -#define WM8993_JD1_SC_EINT_WIDTH 1 /* JD1_SC_EINT */ -#define WM8993_JD1_EINT 0x0200 /* JD1_EINT */ -#define WM8993_JD1_EINT_MASK 0x0200 /* JD1_EINT */ -#define WM8993_JD1_EINT_SHIFT 9 /* JD1_EINT */ -#define WM8993_JD1_EINT_WIDTH 1 /* JD1_EINT */ -#define WM8993_FLL_LOCK_EINT 0x0100 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_MASK 0x0100 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_SHIFT 8 /* FLL_LOCK_EINT */ -#define WM8993_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */ -#define WM8993_GPI8_EINT 0x0080 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_MASK 0x0080 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_SHIFT 7 /* GPI8_EINT */ -#define WM8993_GPI8_EINT_WIDTH 1 /* GPI8_EINT */ -#define WM8993_GPI7_EINT 0x0040 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_MASK 0x0040 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_SHIFT 6 /* GPI7_EINT */ -#define WM8993_GPI7_EINT_WIDTH 1 /* GPI7_EINT */ -#define WM8993_GPIO1_EINT 0x0001 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_MASK 0x0001 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_SHIFT 0 /* GPIO1_EINT */ -#define WM8993_GPIO1_EINT_WIDTH 1 /* GPIO1_EINT */ - -/* - * R19 (0x13) - GPIO1 - */ -#define WM8993_GPIO1_PU 0x0020 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_MASK 0x0020 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_SHIFT 5 /* GPIO1_PU */ -#define WM8993_GPIO1_PU_WIDTH 1 /* GPIO1_PU */ -#define WM8993_GPIO1_PD 0x0010 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_MASK 0x0010 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_SHIFT 4 /* GPIO1_PD */ -#define WM8993_GPIO1_PD_WIDTH 1 /* GPIO1_PD */ -#define WM8993_GPIO1_SEL_MASK 0x000F /* GPIO1_SEL - [3:0] */ -#define WM8993_GPIO1_SEL_SHIFT 0 /* GPIO1_SEL - [3:0] */ -#define WM8993_GPIO1_SEL_WIDTH 4 /* GPIO1_SEL - [3:0] */ - -/* - * R20 (0x14) - IRQ_DEBOUNCE - */ -#define WM8993_JD2_SC_DB 0x8000 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_MASK 0x8000 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_SHIFT 15 /* JD2_SC_DB */ -#define WM8993_JD2_SC_DB_WIDTH 1 /* JD2_SC_DB */ -#define WM8993_JD2_DB 0x4000 /* JD2_DB */ -#define WM8993_JD2_DB_MASK 0x4000 /* JD2_DB */ -#define WM8993_JD2_DB_SHIFT 14 /* JD2_DB */ -#define WM8993_JD2_DB_WIDTH 1 /* JD2_DB */ -#define WM8993_WSEQ_DB 0x2000 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_MASK 0x2000 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_SHIFT 13 /* WSEQ_DB */ -#define WM8993_WSEQ_DB_WIDTH 1 /* WSEQ_DB */ -#define WM8993_TEMPOK_DB 0x0800 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_MASK 0x0800 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_SHIFT 11 /* TEMPOK_DB */ -#define WM8993_TEMPOK_DB_WIDTH 1 /* TEMPOK_DB */ -#define WM8993_JD1_SC_DB 0x0400 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_MASK 0x0400 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_SHIFT 10 /* JD1_SC_DB */ -#define WM8993_JD1_SC_DB_WIDTH 1 /* JD1_SC_DB */ -#define WM8993_JD1_DB 0x0200 /* JD1_DB */ -#define WM8993_JD1_DB_MASK 0x0200 /* JD1_DB */ -#define WM8993_JD1_DB_SHIFT 9 /* JD1_DB */ -#define WM8993_JD1_DB_WIDTH 1 /* JD1_DB */ -#define WM8993_FLL_LOCK_DB 0x0100 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_MASK 0x0100 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_SHIFT 8 /* FLL_LOCK_DB */ -#define WM8993_FLL_LOCK_DB_WIDTH 1 /* FLL_LOCK_DB */ -#define WM8993_GPI8_DB 0x0080 /* GPI8_DB */ -#define WM8993_GPI8_DB_MASK 0x0080 /* GPI8_DB */ -#define WM8993_GPI8_DB_SHIFT 7 /* GPI8_DB */ -#define WM8993_GPI8_DB_WIDTH 1 /* GPI8_DB */ -#define WM8993_GPI7_DB 0x0008 /* GPI7_DB */ -#define WM8993_GPI7_DB_MASK 0x0008 /* GPI7_DB */ -#define WM8993_GPI7_DB_SHIFT 3 /* GPI7_DB */ -#define WM8993_GPI7_DB_WIDTH 1 /* GPI7_DB */ -#define WM8993_GPIO1_DB 0x0001 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_MASK 0x0001 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_SHIFT 0 /* GPIO1_DB */ -#define WM8993_GPIO1_DB_WIDTH 1 /* GPIO1_DB */ - -/* - * R22 (0x16) - GPIOCTRL 2 - */ -#define WM8993_IM_JD2_EINT 0x2000 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_MASK 0x2000 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_SHIFT 13 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_EINT_WIDTH 1 /* IM_JD2_EINT */ -#define WM8993_IM_JD2_SC_EINT 0x1000 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_MASK 0x1000 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_SHIFT 12 /* IM_JD2_SC_EINT */ -#define WM8993_IM_JD2_SC_EINT_WIDTH 1 /* IM_JD2_SC_EINT */ -#define WM8993_IM_TEMPOK_EINT 0x0800 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_MASK 0x0800 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_SHIFT 11 /* IM_TEMPOK_EINT */ -#define WM8993_IM_TEMPOK_EINT_WIDTH 1 /* IM_TEMPOK_EINT */ -#define WM8993_IM_JD1_SC_EINT 0x0400 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_MASK 0x0400 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_SHIFT 10 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_SC_EINT_WIDTH 1 /* IM_JD1_SC_EINT */ -#define WM8993_IM_JD1_EINT 0x0200 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_MASK 0x0200 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_SHIFT 9 /* IM_JD1_EINT */ -#define WM8993_IM_JD1_EINT_WIDTH 1 /* IM_JD1_EINT */ -#define WM8993_IM_FLL_LOCK_EINT 0x0100 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_MASK 0x0100 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_SHIFT 8 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */ -#define WM8993_IM_GPI8_EINT 0x0040 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_MASK 0x0040 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_SHIFT 6 /* IM_GPI8_EINT */ -#define WM8993_IM_GPI8_EINT_WIDTH 1 /* IM_GPI8_EINT */ -#define WM8993_IM_GPIO1_EINT 0x0020 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_MASK 0x0020 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_SHIFT 5 /* IM_GPIO1_EINT */ -#define WM8993_IM_GPIO1_EINT_WIDTH 1 /* IM_GPIO1_EINT */ -#define WM8993_GPI8_ENA 0x0010 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_MASK 0x0010 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_SHIFT 4 /* GPI8_ENA */ -#define WM8993_GPI8_ENA_WIDTH 1 /* GPI8_ENA */ -#define WM8993_IM_GPI7_EINT 0x0004 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_MASK 0x0004 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_SHIFT 2 /* IM_GPI7_EINT */ -#define WM8993_IM_GPI7_EINT_WIDTH 1 /* IM_GPI7_EINT */ -#define WM8993_IM_WSEQ_EINT 0x0002 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_MASK 0x0002 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_SHIFT 1 /* IM_WSEQ_EINT */ -#define WM8993_IM_WSEQ_EINT_WIDTH 1 /* IM_WSEQ_EINT */ -#define WM8993_GPI7_ENA 0x0001 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_MASK 0x0001 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_SHIFT 0 /* GPI7_ENA */ -#define WM8993_GPI7_ENA_WIDTH 1 /* GPI7_ENA */ - -/* - * R23 (0x17) - GPIO_POL - */ -#define WM8993_JD2_SC_POL 0x8000 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_MASK 0x8000 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_SHIFT 15 /* JD2_SC_POL */ -#define WM8993_JD2_SC_POL_WIDTH 1 /* JD2_SC_POL */ -#define WM8993_JD2_POL 0x4000 /* JD2_POL */ -#define WM8993_JD2_POL_MASK 0x4000 /* JD2_POL */ -#define WM8993_JD2_POL_SHIFT 14 /* JD2_POL */ -#define WM8993_JD2_POL_WIDTH 1 /* JD2_POL */ -#define WM8993_WSEQ_POL 0x2000 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_MASK 0x2000 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_SHIFT 13 /* WSEQ_POL */ -#define WM8993_WSEQ_POL_WIDTH 1 /* WSEQ_POL */ -#define WM8993_IRQ_POL 0x1000 /* IRQ_POL */ -#define WM8993_IRQ_POL_MASK 0x1000 /* IRQ_POL */ -#define WM8993_IRQ_POL_SHIFT 12 /* IRQ_POL */ -#define WM8993_IRQ_POL_WIDTH 1 /* IRQ_POL */ -#define WM8993_TEMPOK_POL 0x0800 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_MASK 0x0800 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_SHIFT 11 /* TEMPOK_POL */ -#define WM8993_TEMPOK_POL_WIDTH 1 /* TEMPOK_POL */ -#define WM8993_JD1_SC_POL 0x0400 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_MASK 0x0400 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_SHIFT 10 /* JD1_SC_POL */ -#define WM8993_JD1_SC_POL_WIDTH 1 /* JD1_SC_POL */ -#define WM8993_JD1_POL 0x0200 /* JD1_POL */ -#define WM8993_JD1_POL_MASK 0x0200 /* JD1_POL */ -#define WM8993_JD1_POL_SHIFT 9 /* JD1_POL */ -#define WM8993_JD1_POL_WIDTH 1 /* JD1_POL */ -#define WM8993_FLL_LOCK_POL 0x0100 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_MASK 0x0100 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_SHIFT 8 /* FLL_LOCK_POL */ -#define WM8993_FLL_LOCK_POL_WIDTH 1 /* FLL_LOCK_POL */ -#define WM8993_GPI8_POL 0x0080 /* GPI8_POL */ -#define WM8993_GPI8_POL_MASK 0x0080 /* GPI8_POL */ -#define WM8993_GPI8_POL_SHIFT 7 /* GPI8_POL */ -#define WM8993_GPI8_POL_WIDTH 1 /* GPI8_POL */ -#define WM8993_GPI7_POL 0x0040 /* GPI7_POL */ -#define WM8993_GPI7_POL_MASK 0x0040 /* GPI7_POL */ -#define WM8993_GPI7_POL_SHIFT 6 /* GPI7_POL */ -#define WM8993_GPI7_POL_WIDTH 1 /* GPI7_POL */ -#define WM8993_GPIO1_POL 0x0001 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_MASK 0x0001 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_SHIFT 0 /* GPIO1_POL */ -#define WM8993_GPIO1_POL_WIDTH 1 /* GPIO1_POL */ - -/* - * R24 (0x18) - Left Line Input 1&2 Volume - */ -#define WM8993_IN1_VU 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */ -#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8993_IN1L_MUTE 0x0080 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_MASK 0x0080 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_SHIFT 7 /* IN1L_MUTE */ -#define WM8993_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */ -#define WM8993_IN1L_ZC 0x0040 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_MASK 0x0040 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_SHIFT 6 /* IN1L_ZC */ -#define WM8993_IN1L_ZC_WIDTH 1 /* IN1L_ZC */ -#define WM8993_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */ -#define WM8993_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */ -#define WM8993_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */ - -/* - * R25 (0x19) - Left Line Input 3&4 Volume - */ -#define WM8993_IN2_VU 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */ -#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */ -#define WM8993_IN2L_MUTE 0x0080 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_MASK 0x0080 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_SHIFT 7 /* IN2L_MUTE */ -#define WM8993_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */ -#define WM8993_IN2L_ZC 0x0040 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_MASK 0x0040 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_SHIFT 6 /* IN2L_ZC */ -#define WM8993_IN2L_ZC_WIDTH 1 /* IN2L_ZC */ -#define WM8993_IN2L_VOL_MASK 0x001F /* IN2L_VOL - [4:0] */ -#define WM8993_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [4:0] */ -#define WM8993_IN2L_VOL_WIDTH 5 /* IN2L_VOL - [4:0] */ - -/* - * R26 (0x1A) - Right Line Input 1&2 Volume - */ -#define WM8993_IN1_VU 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_MASK 0x0100 /* IN1_VU */ -#define WM8993_IN1_VU_SHIFT 8 /* IN1_VU */ -#define WM8993_IN1_VU_WIDTH 1 /* IN1_VU */ -#define WM8993_IN1R_MUTE 0x0080 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_MASK 0x0080 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_SHIFT 7 /* IN1R_MUTE */ -#define WM8993_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */ -#define WM8993_IN1R_ZC 0x0040 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_MASK 0x0040 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_SHIFT 6 /* IN1R_ZC */ -#define WM8993_IN1R_ZC_WIDTH 1 /* IN1R_ZC */ -#define WM8993_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */ -#define WM8993_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */ -#define WM8993_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */ - -/* - * R27 (0x1B) - Right Line Input 3&4 Volume - */ -#define WM8993_IN2_VU 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_MASK 0x0100 /* IN2_VU */ -#define WM8993_IN2_VU_SHIFT 8 /* IN2_VU */ -#define WM8993_IN2_VU_WIDTH 1 /* IN2_VU */ -#define WM8993_IN2R_MUTE 0x0080 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_MASK 0x0080 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_SHIFT 7 /* IN2R_MUTE */ -#define WM8993_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */ -#define WM8993_IN2R_ZC 0x0040 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_MASK 0x0040 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_SHIFT 6 /* IN2R_ZC */ -#define WM8993_IN2R_ZC_WIDTH 1 /* IN2R_ZC */ -#define WM8993_IN2R_VOL_MASK 0x001F /* IN2R_VOL - [4:0] */ -#define WM8993_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [4:0] */ -#define WM8993_IN2R_VOL_WIDTH 5 /* IN2R_VOL - [4:0] */ - -/* - * R28 (0x1C) - Left Output Volume - */ -#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */ -#define WM8993_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */ -#define WM8993_HPOUT1L_MUTE_N 0x0040 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_MASK 0x0040 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_SHIFT 6 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_MUTE_N_WIDTH 1 /* HPOUT1L_MUTE_N */ -#define WM8993_HPOUT1L_VOL_MASK 0x003F /* HPOUT1L_VOL - [5:0] */ -#define WM8993_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [5:0] */ -#define WM8993_HPOUT1L_VOL_WIDTH 6 /* HPOUT1L_VOL - [5:0] */ - -/* - * R29 (0x1D) - Right Output Volume - */ -#define WM8993_HPOUT1_VU 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */ -#define WM8993_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */ -#define WM8993_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */ -#define WM8993_HPOUT1R_MUTE_N 0x0040 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_MASK 0x0040 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_SHIFT 6 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_MUTE_N_WIDTH 1 /* HPOUT1R_MUTE_N */ -#define WM8993_HPOUT1R_VOL_MASK 0x003F /* HPOUT1R_VOL - [5:0] */ -#define WM8993_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [5:0] */ -#define WM8993_HPOUT1R_VOL_WIDTH 6 /* HPOUT1R_VOL - [5:0] */ - -/* - * R30 (0x1E) - Line Outputs Volume - */ -#define WM8993_LINEOUT1N_MUTE 0x0040 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_MASK 0x0040 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_SHIFT 6 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1N_MUTE_WIDTH 1 /* LINEOUT1N_MUTE */ -#define WM8993_LINEOUT1P_MUTE 0x0020 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_MASK 0x0020 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_SHIFT 5 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1P_MUTE_WIDTH 1 /* LINEOUT1P_MUTE */ -#define WM8993_LINEOUT1_VOL 0x0010 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_MASK 0x0010 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_SHIFT 4 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT1_VOL_WIDTH 1 /* LINEOUT1_VOL */ -#define WM8993_LINEOUT2N_MUTE 0x0004 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_MASK 0x0004 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_SHIFT 2 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2N_MUTE_WIDTH 1 /* LINEOUT2N_MUTE */ -#define WM8993_LINEOUT2P_MUTE 0x0002 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_MASK 0x0002 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_SHIFT 1 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2P_MUTE_WIDTH 1 /* LINEOUT2P_MUTE */ -#define WM8993_LINEOUT2_VOL 0x0001 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_MASK 0x0001 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_SHIFT 0 /* LINEOUT2_VOL */ -#define WM8993_LINEOUT2_VOL_WIDTH 1 /* LINEOUT2_VOL */ - -/* - * R31 (0x1F) - HPOUT2 Volume - */ -#define WM8993_HPOUT2_MUTE 0x0020 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_MASK 0x0020 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_SHIFT 5 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_MUTE_WIDTH 1 /* HPOUT2_MUTE */ -#define WM8993_HPOUT2_VOL 0x0010 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_MASK 0x0010 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_SHIFT 4 /* HPOUT2_VOL */ -#define WM8993_HPOUT2_VOL_WIDTH 1 /* HPOUT2_VOL */ - -/* - * R32 (0x20) - Left OPGA Volume - */ -#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */ -#define WM8993_MIXOUTL_ZC 0x0080 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_MASK 0x0080 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_SHIFT 7 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_ZC_WIDTH 1 /* MIXOUTL_ZC */ -#define WM8993_MIXOUTL_MUTE_N 0x0040 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_MASK 0x0040 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_SHIFT 6 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_MUTE_N_WIDTH 1 /* MIXOUTL_MUTE_N */ -#define WM8993_MIXOUTL_VOL_MASK 0x003F /* MIXOUTL_VOL - [5:0] */ -#define WM8993_MIXOUTL_VOL_SHIFT 0 /* MIXOUTL_VOL - [5:0] */ -#define WM8993_MIXOUTL_VOL_WIDTH 6 /* MIXOUTL_VOL - [5:0] */ - -/* - * R33 (0x21) - Right OPGA Volume - */ -#define WM8993_MIXOUT_VU 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */ -#define WM8993_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */ -#define WM8993_MIXOUTR_ZC 0x0080 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_MASK 0x0080 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_SHIFT 7 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_ZC_WIDTH 1 /* MIXOUTR_ZC */ -#define WM8993_MIXOUTR_MUTE_N 0x0040 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_MASK 0x0040 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_SHIFT 6 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_MUTE_N_WIDTH 1 /* MIXOUTR_MUTE_N */ -#define WM8993_MIXOUTR_VOL_MASK 0x003F /* MIXOUTR_VOL - [5:0] */ -#define WM8993_MIXOUTR_VOL_SHIFT 0 /* MIXOUTR_VOL - [5:0] */ -#define WM8993_MIXOUTR_VOL_WIDTH 6 /* MIXOUTR_VOL - [5:0] */ - -/* - * R34 (0x22) - SPKMIXL Attenuation - */ -#define WM8993_MIXINL_SPKMIXL_VOL 0x0020 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_MASK 0x0020 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_SHIFT 5 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL 0x0010 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_MASK 0x0010 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_SHIFT 4 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_IN1LP_SPKMIXL_VOL_WIDTH 1 /* IN1LP_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL 0x0008 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_MASK 0x0008 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_SHIFT 3 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_MIXOUTL_SPKMIXL_VOL_WIDTH 1 /* MIXOUTL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL 0x0004 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_MASK 0x0004 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_SHIFT 2 /* DACL_SPKMIXL_VOL */ -#define WM8993_DACL_SPKMIXL_VOL_WIDTH 1 /* DACL_SPKMIXL_VOL */ -#define WM8993_SPKMIXL_VOL_MASK 0x0003 /* SPKMIXL_VOL - [1:0] */ -#define WM8993_SPKMIXL_VOL_SHIFT 0 /* SPKMIXL_VOL - [1:0] */ -#define WM8993_SPKMIXL_VOL_WIDTH 2 /* SPKMIXL_VOL - [1:0] */ - -/* - * R35 (0x23) - SPKMIXR Attenuation - */ -#define WM8993_SPKOUT_CLASSAB_MODE 0x0100 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_MASK 0x0100 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_SHIFT 8 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_SPKOUT_CLASSAB_MODE_WIDTH 1 /* SPKOUT_CLASSAB_MODE */ -#define WM8993_MIXINR_SPKMIXR_VOL 0x0020 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_MASK 0x0020 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_SHIFT 5 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL 0x0010 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_MASK 0x0010 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_SHIFT 4 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_IN1RP_SPKMIXR_VOL_WIDTH 1 /* IN1RP_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL 0x0008 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_MASK 0x0008 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_SHIFT 3 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_MIXOUTR_SPKMIXR_VOL_WIDTH 1 /* MIXOUTR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL 0x0004 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_MASK 0x0004 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_SHIFT 2 /* DACR_SPKMIXR_VOL */ -#define WM8993_DACR_SPKMIXR_VOL_WIDTH 1 /* DACR_SPKMIXR_VOL */ -#define WM8993_SPKMIXR_VOL_MASK 0x0003 /* SPKMIXR_VOL - [1:0] */ -#define WM8993_SPKMIXR_VOL_SHIFT 0 /* SPKMIXR_VOL - [1:0] */ -#define WM8993_SPKMIXR_VOL_WIDTH 2 /* SPKMIXR_VOL - [1:0] */ - -/* - * R36 (0x24) - SPKOUT Mixers - */ -#define WM8993_VRX_TO_SPKOUTL 0x0020 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_MASK 0x0020 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_SHIFT 5 /* VRX_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTL_WIDTH 1 /* VRX_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL 0x0010 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_MASK 0x0010 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_SHIFT 4 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXL_TO_SPKOUTL_WIDTH 1 /* SPKMIXL_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL 0x0008 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_MASK 0x0008 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_SHIFT 3 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_SPKMIXR_TO_SPKOUTL_WIDTH 1 /* SPKMIXR_TO_SPKOUTL */ -#define WM8993_VRX_TO_SPKOUTR 0x0004 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_MASK 0x0004 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_SHIFT 2 /* VRX_TO_SPKOUTR */ -#define WM8993_VRX_TO_SPKOUTR_WIDTH 1 /* VRX_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR 0x0002 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_MASK 0x0002 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_SHIFT 1 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXL_TO_SPKOUTR_WIDTH 1 /* SPKMIXL_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR 0x0001 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_MASK 0x0001 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_SHIFT 0 /* SPKMIXR_TO_SPKOUTR */ -#define WM8993_SPKMIXR_TO_SPKOUTR_WIDTH 1 /* SPKMIXR_TO_SPKOUTR */ - -/* - * R37 (0x25) - SPKOUT Boost - */ -#define WM8993_SPKOUTL_BOOST_MASK 0x0038 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTL_BOOST_SHIFT 3 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTL_BOOST_WIDTH 3 /* SPKOUTL_BOOST - [5:3] */ -#define WM8993_SPKOUTR_BOOST_MASK 0x0007 /* SPKOUTR_BOOST - [2:0] */ -#define WM8993_SPKOUTR_BOOST_SHIFT 0 /* SPKOUTR_BOOST - [2:0] */ -#define WM8993_SPKOUTR_BOOST_WIDTH 3 /* SPKOUTR_BOOST - [2:0] */ - -/* - * R38 (0x26) - Speaker Volume Left - */ -#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ -#define WM8993_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */ -#define WM8993_SPKOUTL_MUTE_N 0x0040 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_MASK 0x0040 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_SHIFT 6 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_MUTE_N_WIDTH 1 /* SPKOUTL_MUTE_N */ -#define WM8993_SPKOUTL_VOL_MASK 0x003F /* SPKOUTL_VOL - [5:0] */ -#define WM8993_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [5:0] */ -#define WM8993_SPKOUTL_VOL_WIDTH 6 /* SPKOUTL_VOL - [5:0] */ - -/* - * R39 (0x27) - Speaker Volume Right - */ -#define WM8993_SPKOUT_VU 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */ -#define WM8993_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */ -#define WM8993_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */ -#define WM8993_SPKOUTR_MUTE_N 0x0040 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_MASK 0x0040 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_SHIFT 6 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_MUTE_N_WIDTH 1 /* SPKOUTR_MUTE_N */ -#define WM8993_SPKOUTR_VOL_MASK 0x003F /* SPKOUTR_VOL - [5:0] */ -#define WM8993_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [5:0] */ -#define WM8993_SPKOUTR_VOL_WIDTH 6 /* SPKOUTR_VOL - [5:0] */ - -/* - * R40 (0x28) - Input Mixer2 - */ -#define WM8993_IN2LP_TO_IN2L 0x0080 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_MASK 0x0080 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_SHIFT 7 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LP_TO_IN2L_WIDTH 1 /* IN2LP_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L 0x0040 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_MASK 0x0040 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_SHIFT 6 /* IN2LN_TO_IN2L */ -#define WM8993_IN2LN_TO_IN2L_WIDTH 1 /* IN2LN_TO_IN2L */ -#define WM8993_IN1LP_TO_IN1L 0x0020 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_MASK 0x0020 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_SHIFT 5 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LP_TO_IN1L_WIDTH 1 /* IN1LP_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L 0x0010 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_MASK 0x0010 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_SHIFT 4 /* IN1LN_TO_IN1L */ -#define WM8993_IN1LN_TO_IN1L_WIDTH 1 /* IN1LN_TO_IN1L */ -#define WM8993_IN2RP_TO_IN2R 0x0008 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_MASK 0x0008 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_SHIFT 3 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RP_TO_IN2R_WIDTH 1 /* IN2RP_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R 0x0004 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_MASK 0x0004 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_SHIFT 2 /* IN2RN_TO_IN2R */ -#define WM8993_IN2RN_TO_IN2R_WIDTH 1 /* IN2RN_TO_IN2R */ -#define WM8993_IN1RP_TO_IN1R 0x0002 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_MASK 0x0002 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_SHIFT 1 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RP_TO_IN1R_WIDTH 1 /* IN1RP_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R 0x0001 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_MASK 0x0001 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_SHIFT 0 /* IN1RN_TO_IN1R */ -#define WM8993_IN1RN_TO_IN1R_WIDTH 1 /* IN1RN_TO_IN1R */ - -/* - * R41 (0x29) - Input Mixer3 - */ -#define WM8993_IN2L_TO_MIXINL 0x0100 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_MASK 0x0100 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_SHIFT 8 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */ -#define WM8993_IN2L_MIXINL_VOL 0x0080 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_MASK 0x0080 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_SHIFT 7 /* IN2L_MIXINL_VOL */ -#define WM8993_IN2L_MIXINL_VOL_WIDTH 1 /* IN2L_MIXINL_VOL */ -#define WM8993_IN1L_TO_MIXINL 0x0020 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_MASK 0x0020 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_SHIFT 5 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_TO_MIXINL_WIDTH 1 /* IN1L_TO_MIXINL */ -#define WM8993_IN1L_MIXINL_VOL 0x0010 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_MASK 0x0010 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_SHIFT 4 /* IN1L_MIXINL_VOL */ -#define WM8993_IN1L_MIXINL_VOL_WIDTH 1 /* IN1L_MIXINL_VOL */ -#define WM8993_MIXOUTL_MIXINL_VOL_MASK 0x0007 /* MIXOUTL_MIXINL_VOL - [2:0] */ -#define WM8993_MIXOUTL_MIXINL_VOL_SHIFT 0 /* MIXOUTL_MIXINL_VOL - [2:0] */ -#define WM8993_MIXOUTL_MIXINL_VOL_WIDTH 3 /* MIXOUTL_MIXINL_VOL - [2:0] */ - -/* - * R42 (0x2A) - Input Mixer4 - */ -#define WM8993_IN2R_TO_MIXINR 0x0100 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_MASK 0x0100 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_SHIFT 8 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */ -#define WM8993_IN2R_MIXINR_VOL 0x0080 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_MASK 0x0080 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_SHIFT 7 /* IN2R_MIXINR_VOL */ -#define WM8993_IN2R_MIXINR_VOL_WIDTH 1 /* IN2R_MIXINR_VOL */ -#define WM8993_IN1R_TO_MIXINR 0x0020 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_MASK 0x0020 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_SHIFT 5 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_TO_MIXINR_WIDTH 1 /* IN1R_TO_MIXINR */ -#define WM8993_IN1R_MIXINR_VOL 0x0010 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_MASK 0x0010 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_SHIFT 4 /* IN1R_MIXINR_VOL */ -#define WM8993_IN1R_MIXINR_VOL_WIDTH 1 /* IN1R_MIXINR_VOL */ -#define WM8993_MIXOUTR_MIXINR_VOL_MASK 0x0007 /* MIXOUTR_MIXINR_VOL - [2:0] */ -#define WM8993_MIXOUTR_MIXINR_VOL_SHIFT 0 /* MIXOUTR_MIXINR_VOL - [2:0] */ -#define WM8993_MIXOUTR_MIXINR_VOL_WIDTH 3 /* MIXOUTR_MIXINR_VOL - [2:0] */ - -/* - * R43 (0x2B) - Input Mixer5 - */ -#define WM8993_IN1LP_MIXINL_VOL_MASK 0x01C0 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_IN1LP_MIXINL_VOL_SHIFT 6 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_IN1LP_MIXINL_VOL_WIDTH 3 /* IN1LP_MIXINL_VOL - [8:6] */ -#define WM8993_VRX_MIXINL_VOL_MASK 0x0007 /* VRX_MIXINL_VOL - [2:0] */ -#define WM8993_VRX_MIXINL_VOL_SHIFT 0 /* VRX_MIXINL_VOL - [2:0] */ -#define WM8993_VRX_MIXINL_VOL_WIDTH 3 /* VRX_MIXINL_VOL - [2:0] */ - -/* - * R44 (0x2C) - Input Mixer6 - */ -#define WM8993_IN1RP_MIXINR_VOL_MASK 0x01C0 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_IN1RP_MIXINR_VOL_SHIFT 6 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_IN1RP_MIXINR_VOL_WIDTH 3 /* IN1RP_MIXINR_VOL - [8:6] */ -#define WM8993_VRX_MIXINR_VOL_MASK 0x0007 /* VRX_MIXINR_VOL - [2:0] */ -#define WM8993_VRX_MIXINR_VOL_SHIFT 0 /* VRX_MIXINR_VOL - [2:0] */ -#define WM8993_VRX_MIXINR_VOL_WIDTH 3 /* VRX_MIXINR_VOL - [2:0] */ - -/* - * R45 (0x2D) - Output Mixer1 - */ -#define WM8993_DACL_TO_HPOUT1L 0x0100 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_MASK 0x0100 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_SHIFT 8 /* DACL_TO_HPOUT1L */ -#define WM8993_DACL_TO_HPOUT1L_WIDTH 1 /* DACL_TO_HPOUT1L */ -#define WM8993_MIXINR_TO_MIXOUTL 0x0080 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_MASK 0x0080 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_SHIFT 7 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINR_TO_MIXOUTL_WIDTH 1 /* MIXINR_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL 0x0040 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_MASK 0x0040 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_SHIFT 6 /* MIXINL_TO_MIXOUTL */ -#define WM8993_MIXINL_TO_MIXOUTL_WIDTH 1 /* MIXINL_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL 0x0020 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_MASK 0x0020 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_SHIFT 5 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2RN_TO_MIXOUTL_WIDTH 1 /* IN2RN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL 0x0010 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_MASK 0x0010 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_SHIFT 4 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN2LN_TO_MIXOUTL_WIDTH 1 /* IN2LN_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL 0x0008 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_MASK 0x0008 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_SHIFT 3 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1R_TO_MIXOUTL_WIDTH 1 /* IN1R_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL 0x0004 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_MASK 0x0004 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_SHIFT 2 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN1L_TO_MIXOUTL_WIDTH 1 /* IN1L_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL 0x0002 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_MASK 0x0002 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_SHIFT 1 /* IN2LP_TO_MIXOUTL */ -#define WM8993_IN2LP_TO_MIXOUTL_WIDTH 1 /* IN2LP_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL 0x0001 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_MASK 0x0001 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_SHIFT 0 /* DACL_TO_MIXOUTL */ -#define WM8993_DACL_TO_MIXOUTL_WIDTH 1 /* DACL_TO_MIXOUTL */ - -/* - * R46 (0x2E) - Output Mixer2 - */ -#define WM8993_DACR_TO_HPOUT1R 0x0100 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_MASK 0x0100 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_SHIFT 8 /* DACR_TO_HPOUT1R */ -#define WM8993_DACR_TO_HPOUT1R_WIDTH 1 /* DACR_TO_HPOUT1R */ -#define WM8993_MIXINL_TO_MIXOUTR 0x0080 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_MASK 0x0080 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_SHIFT 7 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINL_TO_MIXOUTR_WIDTH 1 /* MIXINL_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR 0x0040 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_MASK 0x0040 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_SHIFT 6 /* MIXINR_TO_MIXOUTR */ -#define WM8993_MIXINR_TO_MIXOUTR_WIDTH 1 /* MIXINR_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR 0x0020 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_MASK 0x0020 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_SHIFT 5 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2LN_TO_MIXOUTR_WIDTH 1 /* IN2LN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR 0x0010 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_MASK 0x0010 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_SHIFT 4 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN2RN_TO_MIXOUTR_WIDTH 1 /* IN2RN_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR 0x0008 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_MASK 0x0008 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_SHIFT 3 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1L_TO_MIXOUTR_WIDTH 1 /* IN1L_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR 0x0004 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_MASK 0x0004 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_SHIFT 2 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN1R_TO_MIXOUTR_WIDTH 1 /* IN1R_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR 0x0002 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_MASK 0x0002 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_SHIFT 1 /* IN2RP_TO_MIXOUTR */ -#define WM8993_IN2RP_TO_MIXOUTR_WIDTH 1 /* IN2RP_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR 0x0001 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_MASK 0x0001 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_SHIFT 0 /* DACR_TO_MIXOUTR */ -#define WM8993_DACR_TO_MIXOUTR_WIDTH 1 /* DACR_TO_MIXOUTR */ - -/* - * R47 (0x2F) - Output Mixer3 - */ -#define WM8993_IN2LP_MIXOUTL_VOL_MASK 0x0E00 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LP_MIXOUTL_VOL_SHIFT 9 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LP_MIXOUTL_VOL_WIDTH 3 /* IN2LP_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2LN_MIXOUTL_VOL_MASK 0x01C0 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTL_VOL_SHIFT 6 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTL_VOL_WIDTH 3 /* IN2LN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN1R_MIXOUTL_VOL_MASK 0x0038 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTL_VOL_SHIFT 3 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTL_VOL_WIDTH 3 /* IN1R_MIXOUTL_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTL_VOL_MASK 0x0007 /* IN1L_MIXOUTL_VOL - [2:0] */ -#define WM8993_IN1L_MIXOUTL_VOL_SHIFT 0 /* IN1L_MIXOUTL_VOL - [2:0] */ -#define WM8993_IN1L_MIXOUTL_VOL_WIDTH 3 /* IN1L_MIXOUTL_VOL - [2:0] */ - -/* - * R48 (0x30) - Output Mixer4 - */ -#define WM8993_IN2RP_MIXOUTR_VOL_MASK 0x0E00 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RP_MIXOUTR_VOL_SHIFT 9 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RP_MIXOUTR_VOL_WIDTH 3 /* IN2RP_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2RN_MIXOUTR_VOL_MASK 0x01C0 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTR_VOL_SHIFT 6 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTR_VOL_WIDTH 3 /* IN2RN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN1L_MIXOUTR_VOL_MASK 0x0038 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTR_VOL_SHIFT 3 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1L_MIXOUTR_VOL_WIDTH 3 /* IN1L_MIXOUTR_VOL - [5:3] */ -#define WM8993_IN1R_MIXOUTR_VOL_MASK 0x0007 /* IN1R_MIXOUTR_VOL - [2:0] */ -#define WM8993_IN1R_MIXOUTR_VOL_SHIFT 0 /* IN1R_MIXOUTR_VOL - [2:0] */ -#define WM8993_IN1R_MIXOUTR_VOL_WIDTH 3 /* IN1R_MIXOUTR_VOL - [2:0] */ - -/* - * R49 (0x31) - Output Mixer5 - */ -#define WM8993_DACL_MIXOUTL_VOL_MASK 0x0E00 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_DACL_MIXOUTL_VOL_SHIFT 9 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_DACL_MIXOUTL_VOL_WIDTH 3 /* DACL_MIXOUTL_VOL - [11:9] */ -#define WM8993_IN2RN_MIXOUTL_VOL_MASK 0x01C0 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTL_VOL_SHIFT 6 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_IN2RN_MIXOUTL_VOL_WIDTH 3 /* IN2RN_MIXOUTL_VOL - [8:6] */ -#define WM8993_MIXINR_MIXOUTL_VOL_MASK 0x0038 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTL_VOL_SHIFT 3 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTL_VOL_WIDTH 3 /* MIXINR_MIXOUTL_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTL_VOL_MASK 0x0007 /* MIXINL_MIXOUTL_VOL - [2:0] */ -#define WM8993_MIXINL_MIXOUTL_VOL_SHIFT 0 /* MIXINL_MIXOUTL_VOL - [2:0] */ -#define WM8993_MIXINL_MIXOUTL_VOL_WIDTH 3 /* MIXINL_MIXOUTL_VOL - [2:0] */ - -/* - * R50 (0x32) - Output Mixer6 - */ -#define WM8993_DACR_MIXOUTR_VOL_MASK 0x0E00 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_DACR_MIXOUTR_VOL_SHIFT 9 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_DACR_MIXOUTR_VOL_WIDTH 3 /* DACR_MIXOUTR_VOL - [11:9] */ -#define WM8993_IN2LN_MIXOUTR_VOL_MASK 0x01C0 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTR_VOL_SHIFT 6 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_IN2LN_MIXOUTR_VOL_WIDTH 3 /* IN2LN_MIXOUTR_VOL - [8:6] */ -#define WM8993_MIXINL_MIXOUTR_VOL_MASK 0x0038 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTR_VOL_SHIFT 3 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINL_MIXOUTR_VOL_WIDTH 3 /* MIXINL_MIXOUTR_VOL - [5:3] */ -#define WM8993_MIXINR_MIXOUTR_VOL_MASK 0x0007 /* MIXINR_MIXOUTR_VOL - [2:0] */ -#define WM8993_MIXINR_MIXOUTR_VOL_SHIFT 0 /* MIXINR_MIXOUTR_VOL - [2:0] */ -#define WM8993_MIXINR_MIXOUTR_VOL_WIDTH 3 /* MIXINR_MIXOUTR_VOL - [2:0] */ - -/* - * R51 (0x33) - HPOUT2 Mixer - */ -#define WM8993_VRX_TO_HPOUT2 0x0020 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_MASK 0x0020 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_SHIFT 5 /* VRX_TO_HPOUT2 */ -#define WM8993_VRX_TO_HPOUT2_WIDTH 1 /* VRX_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_MASK 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_SHIFT 4 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTLVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTLVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_MASK 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_SHIFT 3 /* MIXOUTRVOL_TO_HPOUT2 */ -#define WM8993_MIXOUTRVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTRVOL_TO_HPOUT2 */ - -/* - * R52 (0x34) - Line Mixer1 - */ -#define WM8993_MIXOUTL_TO_LINEOUT1N 0x0040 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_MASK 0x0040 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_SHIFT 6 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTL_TO_LINEOUT1N_WIDTH 1 /* MIXOUTL_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N 0x0020 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_MASK 0x0020 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_SHIFT 5 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_MIXOUTR_TO_LINEOUT1N_WIDTH 1 /* MIXOUTR_TO_LINEOUT1N */ -#define WM8993_LINEOUT1_MODE 0x0010 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_MASK 0x0010 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_SHIFT 4 /* LINEOUT1_MODE */ -#define WM8993_LINEOUT1_MODE_WIDTH 1 /* LINEOUT1_MODE */ -#define WM8993_IN1R_TO_LINEOUT1P 0x0004 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_MASK 0x0004 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_SHIFT 2 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1R_TO_LINEOUT1P_WIDTH 1 /* IN1R_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P 0x0002 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_MASK 0x0002 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_SHIFT 1 /* IN1L_TO_LINEOUT1P */ -#define WM8993_IN1L_TO_LINEOUT1P_WIDTH 1 /* IN1L_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P 0x0001 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_MASK 0x0001 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_SHIFT 0 /* MIXOUTL_TO_LINEOUT1P */ -#define WM8993_MIXOUTL_TO_LINEOUT1P_WIDTH 1 /* MIXOUTL_TO_LINEOUT1P */ - -/* - * R53 (0x35) - Line Mixer2 - */ -#define WM8993_MIXOUTR_TO_LINEOUT2N 0x0040 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_MASK 0x0040 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_SHIFT 6 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTR_TO_LINEOUT2N_WIDTH 1 /* MIXOUTR_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N 0x0020 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_MASK 0x0020 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_SHIFT 5 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_MIXOUTL_TO_LINEOUT2N_WIDTH 1 /* MIXOUTL_TO_LINEOUT2N */ -#define WM8993_LINEOUT2_MODE 0x0010 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_MASK 0x0010 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_SHIFT 4 /* LINEOUT2_MODE */ -#define WM8993_LINEOUT2_MODE_WIDTH 1 /* LINEOUT2_MODE */ -#define WM8993_IN1L_TO_LINEOUT2P 0x0004 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_MASK 0x0004 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_SHIFT 2 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1L_TO_LINEOUT2P_WIDTH 1 /* IN1L_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P 0x0002 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_MASK 0x0002 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_SHIFT 1 /* IN1R_TO_LINEOUT2P */ -#define WM8993_IN1R_TO_LINEOUT2P_WIDTH 1 /* IN1R_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P 0x0001 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_MASK 0x0001 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_SHIFT 0 /* MIXOUTR_TO_LINEOUT2P */ -#define WM8993_MIXOUTR_TO_LINEOUT2P_WIDTH 1 /* MIXOUTR_TO_LINEOUT2P */ - -/* - * R54 (0x36) - Speaker Mixer - */ -#define WM8993_SPKAB_REF_SEL 0x0100 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_MASK 0x0100 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_SHIFT 8 /* SPKAB_REF_SEL */ -#define WM8993_SPKAB_REF_SEL_WIDTH 1 /* SPKAB_REF_SEL */ -#define WM8993_MIXINL_TO_SPKMIXL 0x0080 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_MASK 0x0080 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_SHIFT 7 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */ -#define WM8993_MIXINR_TO_SPKMIXR 0x0040 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_MASK 0x0040 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_SHIFT 6 /* MIXINR_TO_SPKMIXR */ -#define WM8993_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */ -#define WM8993_IN1LP_TO_SPKMIXL 0x0020 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_MASK 0x0020 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_SHIFT 5 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1LP_TO_SPKMIXL_WIDTH 1 /* IN1LP_TO_SPKMIXL */ -#define WM8993_IN1RP_TO_SPKMIXR 0x0010 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_MASK 0x0010 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_SHIFT 4 /* IN1RP_TO_SPKMIXR */ -#define WM8993_IN1RP_TO_SPKMIXR_WIDTH 1 /* IN1RP_TO_SPKMIXR */ -#define WM8993_MIXOUTL_TO_SPKMIXL 0x0008 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_MASK 0x0008 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_SHIFT 3 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTL_TO_SPKMIXL_WIDTH 1 /* MIXOUTL_TO_SPKMIXL */ -#define WM8993_MIXOUTR_TO_SPKMIXR 0x0004 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_MASK 0x0004 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_SHIFT 2 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_MIXOUTR_TO_SPKMIXR_WIDTH 1 /* MIXOUTR_TO_SPKMIXR */ -#define WM8993_DACL_TO_SPKMIXL 0x0002 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_MASK 0x0002 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_SHIFT 1 /* DACL_TO_SPKMIXL */ -#define WM8993_DACL_TO_SPKMIXL_WIDTH 1 /* DACL_TO_SPKMIXL */ -#define WM8993_DACR_TO_SPKMIXR 0x0001 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_MASK 0x0001 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_SHIFT 0 /* DACR_TO_SPKMIXR */ -#define WM8993_DACR_TO_SPKMIXR_WIDTH 1 /* DACR_TO_SPKMIXR */ - -/* - * R55 (0x37) - Additional Control - */ -#define WM8993_LINEOUT1_FB 0x0080 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_MASK 0x0080 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_SHIFT 7 /* LINEOUT1_FB */ -#define WM8993_LINEOUT1_FB_WIDTH 1 /* LINEOUT1_FB */ -#define WM8993_LINEOUT2_FB 0x0040 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_MASK 0x0040 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_SHIFT 6 /* LINEOUT2_FB */ -#define WM8993_LINEOUT2_FB_WIDTH 1 /* LINEOUT2_FB */ -#define WM8993_VROI 0x0001 /* VROI */ -#define WM8993_VROI_MASK 0x0001 /* VROI */ -#define WM8993_VROI_SHIFT 0 /* VROI */ -#define WM8993_VROI_WIDTH 1 /* VROI */ - -/* - * R56 (0x38) - AntiPOP1 - */ -#define WM8993_LINEOUT_VMID_BUF_ENA 0x0080 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_MASK 0x0080 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_SHIFT 7 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_LINEOUT_VMID_BUF_ENA_WIDTH 1 /* LINEOUT_VMID_BUF_ENA */ -#define WM8993_HPOUT2_IN_ENA 0x0040 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_MASK 0x0040 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_SHIFT 6 /* HPOUT2_IN_ENA */ -#define WM8993_HPOUT2_IN_ENA_WIDTH 1 /* HPOUT2_IN_ENA */ -#define WM8993_LINEOUT1_DISCH 0x0020 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_MASK 0x0020 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_SHIFT 5 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT1_DISCH_WIDTH 1 /* LINEOUT1_DISCH */ -#define WM8993_LINEOUT2_DISCH 0x0010 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_MASK 0x0010 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_SHIFT 4 /* LINEOUT2_DISCH */ -#define WM8993_LINEOUT2_DISCH_WIDTH 1 /* LINEOUT2_DISCH */ - -/* - * R57 (0x39) - AntiPOP2 - */ -#define WM8993_VMID_RAMP_MASK 0x0060 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_RAMP_SHIFT 5 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_RAMP_WIDTH 2 /* VMID_RAMP - [6:5] */ -#define WM8993_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */ -#define WM8993_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */ -#define WM8993_STARTUP_BIAS_ENA 0x0004 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_MASK 0x0004 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_SHIFT 2 /* STARTUP_BIAS_ENA */ -#define WM8993_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */ -#define WM8993_BIAS_SRC 0x0002 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_MASK 0x0002 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_SHIFT 1 /* BIAS_SRC */ -#define WM8993_BIAS_SRC_WIDTH 1 /* BIAS_SRC */ -#define WM8993_VMID_DISCH 0x0001 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_MASK 0x0001 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_SHIFT 0 /* VMID_DISCH */ -#define WM8993_VMID_DISCH_WIDTH 1 /* VMID_DISCH */ - -/* - * R58 (0x3A) - MICBIAS - */ -#define WM8993_JD_SCTHR_MASK 0x00C0 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_SCTHR_SHIFT 6 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_SCTHR_WIDTH 2 /* JD_SCTHR - [7:6] */ -#define WM8993_JD_THR_MASK 0x0030 /* JD_THR - [5:4] */ -#define WM8993_JD_THR_SHIFT 4 /* JD_THR - [5:4] */ -#define WM8993_JD_THR_WIDTH 2 /* JD_THR - [5:4] */ -#define WM8993_JD_ENA 0x0004 /* JD_ENA */ -#define WM8993_JD_ENA_MASK 0x0004 /* JD_ENA */ -#define WM8993_JD_ENA_SHIFT 2 /* JD_ENA */ -#define WM8993_JD_ENA_WIDTH 1 /* JD_ENA */ -#define WM8993_MICB2_LVL 0x0002 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_MASK 0x0002 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_SHIFT 1 /* MICB2_LVL */ -#define WM8993_MICB2_LVL_WIDTH 1 /* MICB2_LVL */ -#define WM8993_MICB1_LVL 0x0001 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_MASK 0x0001 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_SHIFT 0 /* MICB1_LVL */ -#define WM8993_MICB1_LVL_WIDTH 1 /* MICB1_LVL */ - -/* - * R60 (0x3C) - FLL Control 1 - */ -#define WM8993_FLL_FRAC 0x0004 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_MASK 0x0004 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_SHIFT 2 /* FLL_FRAC */ -#define WM8993_FLL_FRAC_WIDTH 1 /* FLL_FRAC */ -#define WM8993_FLL_OSC_ENA 0x0002 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_MASK 0x0002 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_SHIFT 1 /* FLL_OSC_ENA */ -#define WM8993_FLL_OSC_ENA_WIDTH 1 /* FLL_OSC_ENA */ -#define WM8993_FLL_ENA 0x0001 /* FLL_ENA */ -#define WM8993_FLL_ENA_MASK 0x0001 /* FLL_ENA */ -#define WM8993_FLL_ENA_SHIFT 0 /* FLL_ENA */ -#define WM8993_FLL_ENA_WIDTH 1 /* FLL_ENA */ - -/* - * R61 (0x3D) - FLL Control 2 - */ -#define WM8993_FLL_OUTDIV_MASK 0x0700 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_OUTDIV_WIDTH 3 /* FLL_OUTDIV - [10:8] */ -#define WM8993_FLL_CTRL_RATE_MASK 0x0070 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_CTRL_RATE_SHIFT 4 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_CTRL_RATE_WIDTH 3 /* FLL_CTRL_RATE - [6:4] */ -#define WM8993_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */ -#define WM8993_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */ -#define WM8993_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */ - -/* - * R62 (0x3E) - FLL Control 3 - */ -#define WM8993_FLL_K_MASK 0xFFFF /* FLL_K - [15:0] */ -#define WM8993_FLL_K_SHIFT 0 /* FLL_K - [15:0] */ -#define WM8993_FLL_K_WIDTH 16 /* FLL_K - [15:0] */ - -/* - * R63 (0x3F) - FLL Control 4 - */ -#define WM8993_FLL_N_MASK 0x7FE0 /* FLL_N - [14:5] */ -#define WM8993_FLL_N_SHIFT 5 /* FLL_N - [14:5] */ -#define WM8993_FLL_N_WIDTH 10 /* FLL_N - [14:5] */ -#define WM8993_FLL_GAIN_MASK 0x000F /* FLL_GAIN - [3:0] */ -#define WM8993_FLL_GAIN_SHIFT 0 /* FLL_GAIN - [3:0] */ -#define WM8993_FLL_GAIN_WIDTH 4 /* FLL_GAIN - [3:0] */ - -/* - * R64 (0x40) - FLL Control 5 - */ -#define WM8993_FLL_FRC_NCO_VAL_MASK 0x1F80 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO_VAL_SHIFT 7 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO_VAL_WIDTH 6 /* FLL_FRC_NCO_VAL - [12:7] */ -#define WM8993_FLL_FRC_NCO 0x0040 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_MASK 0x0040 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_SHIFT 6 /* FLL_FRC_NCO */ -#define WM8993_FLL_FRC_NCO_WIDTH 1 /* FLL_FRC_NCO */ -#define WM8993_FLL_CLK_REF_DIV_MASK 0x0018 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_REF_DIV_SHIFT 3 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [4:3] */ -#define WM8993_FLL_CLK_SRC_MASK 0x0003 /* FLL_CLK_SRC - [1:0] */ -#define WM8993_FLL_CLK_SRC_SHIFT 0 /* FLL_CLK_SRC - [1:0] */ -#define WM8993_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */ - -/* - * R65 (0x41) - Clocking 3 - */ -#define WM8993_CLK_DCS_DIV_MASK 0x3C00 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_CLK_DCS_DIV_SHIFT 10 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_CLK_DCS_DIV_WIDTH 4 /* CLK_DCS_DIV - [13:10] */ -#define WM8993_SAMPLE_RATE_MASK 0x0380 /* SAMPLE_RATE - [9:7] */ -#define WM8993_SAMPLE_RATE_SHIFT 7 /* SAMPLE_RATE - [9:7] */ -#define WM8993_SAMPLE_RATE_WIDTH 3 /* SAMPLE_RATE - [9:7] */ -#define WM8993_CLK_SYS_RATE_MASK 0x001E /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_SYS_RATE_SHIFT 1 /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_SYS_RATE_WIDTH 4 /* CLK_SYS_RATE - [4:1] */ -#define WM8993_CLK_DSP_ENA 0x0001 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_MASK 0x0001 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_SHIFT 0 /* CLK_DSP_ENA */ -#define WM8993_CLK_DSP_ENA_WIDTH 1 /* CLK_DSP_ENA */ - -/* - * R66 (0x42) - Clocking 4 - */ -#define WM8993_DAC_DIV4 0x0200 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_MASK 0x0200 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_SHIFT 9 /* DAC_DIV4 */ -#define WM8993_DAC_DIV4_WIDTH 1 /* DAC_DIV4 */ -#define WM8993_CLK_256K_DIV_MASK 0x007E /* CLK_256K_DIV - [6:1] */ -#define WM8993_CLK_256K_DIV_SHIFT 1 /* CLK_256K_DIV - [6:1] */ -#define WM8993_CLK_256K_DIV_WIDTH 6 /* CLK_256K_DIV - [6:1] */ -#define WM8993_SR_MODE 0x0001 /* SR_MODE */ -#define WM8993_SR_MODE_MASK 0x0001 /* SR_MODE */ -#define WM8993_SR_MODE_SHIFT 0 /* SR_MODE */ -#define WM8993_SR_MODE_WIDTH 1 /* SR_MODE */ - -/* - * R67 (0x43) - MW Slave Control - */ -#define WM8993_MASK_WRITE_ENA 0x0001 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_MASK 0x0001 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_SHIFT 0 /* MASK_WRITE_ENA */ -#define WM8993_MASK_WRITE_ENA_WIDTH 1 /* MASK_WRITE_ENA */ - -/* - * R69 (0x45) - Bus Control 1 - */ -#define WM8993_CLK_SYS_ENA 0x0002 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_MASK 0x0002 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_SHIFT 1 /* CLK_SYS_ENA */ -#define WM8993_CLK_SYS_ENA_WIDTH 1 /* CLK_SYS_ENA */ - -/* - * R70 (0x46) - Write Sequencer 0 - */ -#define WM8993_WSEQ_ENA 0x0100 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_MASK 0x0100 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_SHIFT 8 /* WSEQ_ENA */ -#define WM8993_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */ -#define WM8993_WSEQ_WRITE_INDEX_MASK 0x001F /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8993_WSEQ_WRITE_INDEX_SHIFT 0 /* WSEQ_WRITE_INDEX - [4:0] */ -#define WM8993_WSEQ_WRITE_INDEX_WIDTH 5 /* WSEQ_WRITE_INDEX - [4:0] */ - -/* - * R71 (0x47) - Write Sequencer 1 - */ -#define WM8993_WSEQ_DATA_WIDTH_MASK 0x7000 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_WIDTH_SHIFT 12 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_WIDTH_WIDTH 3 /* WSEQ_DATA_WIDTH - [14:12] */ -#define WM8993_WSEQ_DATA_START_MASK 0x0F00 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_DATA_START_SHIFT 8 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_DATA_START_WIDTH 4 /* WSEQ_DATA_START - [11:8] */ -#define WM8993_WSEQ_ADDR_MASK 0x00FF /* WSEQ_ADDR - [7:0] */ -#define WM8993_WSEQ_ADDR_SHIFT 0 /* WSEQ_ADDR - [7:0] */ -#define WM8993_WSEQ_ADDR_WIDTH 8 /* WSEQ_ADDR - [7:0] */ - -/* - * R72 (0x48) - Write Sequencer 2 - */ -#define WM8993_WSEQ_EOS 0x4000 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_MASK 0x4000 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_SHIFT 14 /* WSEQ_EOS */ -#define WM8993_WSEQ_EOS_WIDTH 1 /* WSEQ_EOS */ -#define WM8993_WSEQ_DELAY_MASK 0x0F00 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DELAY_SHIFT 8 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DELAY_WIDTH 4 /* WSEQ_DELAY - [11:8] */ -#define WM8993_WSEQ_DATA_MASK 0x00FF /* WSEQ_DATA - [7:0] */ -#define WM8993_WSEQ_DATA_SHIFT 0 /* WSEQ_DATA - [7:0] */ -#define WM8993_WSEQ_DATA_WIDTH 8 /* WSEQ_DATA - [7:0] */ - -/* - * R73 (0x49) - Write Sequencer 3 - */ -#define WM8993_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */ -#define WM8993_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */ -#define WM8993_WSEQ_START 0x0100 /* WSEQ_START */ -#define WM8993_WSEQ_START_MASK 0x0100 /* WSEQ_START */ -#define WM8993_WSEQ_START_SHIFT 8 /* WSEQ_START */ -#define WM8993_WSEQ_START_WIDTH 1 /* WSEQ_START */ -#define WM8993_WSEQ_START_INDEX_MASK 0x003F /* WSEQ_START_INDEX - [5:0] */ -#define WM8993_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [5:0] */ -#define WM8993_WSEQ_START_INDEX_WIDTH 6 /* WSEQ_START_INDEX - [5:0] */ - -/* - * R74 (0x4A) - Write Sequencer 4 - */ -#define WM8993_WSEQ_BUSY 0x0001 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_MASK 0x0001 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_SHIFT 0 /* WSEQ_BUSY */ -#define WM8993_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */ - -/* - * R75 (0x4B) - Write Sequencer 5 - */ -#define WM8993_WSEQ_CURRENT_INDEX_MASK 0x003F /* WSEQ_CURRENT_INDEX - [5:0] */ -#define WM8993_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [5:0] */ -#define WM8993_WSEQ_CURRENT_INDEX_WIDTH 6 /* WSEQ_CURRENT_INDEX - [5:0] */ - -/* - * R76 (0x4C) - Charge Pump 1 - */ -#define WM8993_CP_ENA 0x8000 /* CP_ENA */ -#define WM8993_CP_ENA_MASK 0x8000 /* CP_ENA */ -#define WM8993_CP_ENA_SHIFT 15 /* CP_ENA */ -#define WM8993_CP_ENA_WIDTH 1 /* CP_ENA */ - -/* - * R81 (0x51) - Class W 0 - */ -#define WM8993_CP_DYN_FREQ 0x0002 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_MASK 0x0002 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_SHIFT 1 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_FREQ_WIDTH 1 /* CP_DYN_FREQ */ -#define WM8993_CP_DYN_V 0x0001 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_MASK 0x0001 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_SHIFT 0 /* CP_DYN_V */ -#define WM8993_CP_DYN_V_WIDTH 1 /* CP_DYN_V */ - -/* - * R84 (0x54) - DC Servo 0 - */ -#define WM8993_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */ -#define WM8993_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */ -#define WM8993_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */ -#define WM8993_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */ -#define WM8993_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */ -#define WM8993_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */ -#define WM8993_DCS_TRIG_DAC_WR_1 0x0008 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_MASK 0x0008 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_SHIFT 3 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */ -#define WM8993_DCS_TRIG_DAC_WR_0 0x0004 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_MASK 0x0004 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_SHIFT 2 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */ -#define WM8993_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */ -#define WM8993_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */ -#define WM8993_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */ - -/* - * R85 (0x55) - DC Servo 1 - */ -#define WM8993_DCS_SERIES_NO_01_MASK 0x0FE0 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_SERIES_NO_01_SHIFT 5 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [11:5] */ -#define WM8993_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8993_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */ -#define WM8993_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */ - -/* - * R87 (0x57) - DC Servo 3 - */ -#define WM8993_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */ -#define WM8993_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8993_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */ -#define WM8993_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */ - -/* - * R88 (0x58) - DC Servo Readback 0 - */ -#define WM8993_DCS_DATAPATH_BUSY 0x4000 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_MASK 0x4000 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_SHIFT 14 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_DATAPATH_BUSY_WIDTH 1 /* DCS_DATAPATH_BUSY */ -#define WM8993_DCS_CHANNEL_MASK 0x3000 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CHANNEL_SHIFT 12 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CHANNEL_WIDTH 2 /* DCS_CHANNEL - [13:12] */ -#define WM8993_DCS_CAL_COMPLETE_MASK 0x0300 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_CAL_COMPLETE_WIDTH 2 /* DCS_CAL_COMPLETE - [9:8] */ -#define WM8993_DCS_DAC_WR_COMPLETE_MASK 0x0030 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_DAC_WR_COMPLETE_WIDTH 2 /* DCS_DAC_WR_COMPLETE - [5:4] */ -#define WM8993_DCS_STARTUP_COMPLETE_MASK 0x0003 /* DCS_STARTUP_COMPLETE - [1:0] */ -#define WM8993_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [1:0] */ -#define WM8993_DCS_STARTUP_COMPLETE_WIDTH 2 /* DCS_STARTUP_COMPLETE - [1:0] */ - -/* - * R89 (0x59) - DC Servo Readback 1 - */ -#define WM8993_DCS_INTEG_CHAN_1_MASK 0x00FF /* DCS_INTEG_CHAN_1 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_1_SHIFT 0 /* DCS_INTEG_CHAN_1 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_1_WIDTH 8 /* DCS_INTEG_CHAN_1 - [7:0] */ - -/* - * R90 (0x5A) - DC Servo Readback 2 - */ -#define WM8993_DCS_INTEG_CHAN_0_MASK 0x00FF /* DCS_INTEG_CHAN_0 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_0_SHIFT 0 /* DCS_INTEG_CHAN_0 - [7:0] */ -#define WM8993_DCS_INTEG_CHAN_0_WIDTH 8 /* DCS_INTEG_CHAN_0 - [7:0] */ - -/* - * R96 (0x60) - Analogue HP 0 - */ -#define WM8993_HPOUT1_AUTO_PU 0x0100 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_MASK 0x0100 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_SHIFT 8 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1_AUTO_PU_WIDTH 1 /* HPOUT1_AUTO_PU */ -#define WM8993_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */ -#define WM8993_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */ -#define WM8993_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */ -#define WM8993_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */ -#define WM8993_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */ -#define WM8993_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */ -#define WM8993_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */ - -/* - * R98 (0x62) - EQ1 - */ -#define WM8993_EQ_ENA 0x0001 /* EQ_ENA */ -#define WM8993_EQ_ENA_MASK 0x0001 /* EQ_ENA */ -#define WM8993_EQ_ENA_SHIFT 0 /* EQ_ENA */ -#define WM8993_EQ_ENA_WIDTH 1 /* EQ_ENA */ - -/* - * R99 (0x63) - EQ2 - */ -#define WM8993_EQ_B1_GAIN_MASK 0x001F /* EQ_B1_GAIN - [4:0] */ -#define WM8993_EQ_B1_GAIN_SHIFT 0 /* EQ_B1_GAIN - [4:0] */ -#define WM8993_EQ_B1_GAIN_WIDTH 5 /* EQ_B1_GAIN - [4:0] */ - -/* - * R100 (0x64) - EQ3 - */ -#define WM8993_EQ_B2_GAIN_MASK 0x001F /* EQ_B2_GAIN - [4:0] */ -#define WM8993_EQ_B2_GAIN_SHIFT 0 /* EQ_B2_GAIN - [4:0] */ -#define WM8993_EQ_B2_GAIN_WIDTH 5 /* EQ_B2_GAIN - [4:0] */ - -/* - * R101 (0x65) - EQ4 - */ -#define WM8993_EQ_B3_GAIN_MASK 0x001F /* EQ_B3_GAIN - [4:0] */ -#define WM8993_EQ_B3_GAIN_SHIFT 0 /* EQ_B3_GAIN - [4:0] */ -#define WM8993_EQ_B3_GAIN_WIDTH 5 /* EQ_B3_GAIN - [4:0] */ - -/* - * R102 (0x66) - EQ5 - */ -#define WM8993_EQ_B4_GAIN_MASK 0x001F /* EQ_B4_GAIN - [4:0] */ -#define WM8993_EQ_B4_GAIN_SHIFT 0 /* EQ_B4_GAIN - [4:0] */ -#define WM8993_EQ_B4_GAIN_WIDTH 5 /* EQ_B4_GAIN - [4:0] */ - -/* - * R103 (0x67) - EQ6 - */ -#define WM8993_EQ_B5_GAIN_MASK 0x001F /* EQ_B5_GAIN - [4:0] */ -#define WM8993_EQ_B5_GAIN_SHIFT 0 /* EQ_B5_GAIN - [4:0] */ -#define WM8993_EQ_B5_GAIN_WIDTH 5 /* EQ_B5_GAIN - [4:0] */ - -/* - * R104 (0x68) - EQ7 - */ -#define WM8993_EQ_B1_A_MASK 0xFFFF /* EQ_B1_A - [15:0] */ -#define WM8993_EQ_B1_A_SHIFT 0 /* EQ_B1_A - [15:0] */ -#define WM8993_EQ_B1_A_WIDTH 16 /* EQ_B1_A - [15:0] */ - -/* - * R105 (0x69) - EQ8 - */ -#define WM8993_EQ_B1_B_MASK 0xFFFF /* EQ_B1_B - [15:0] */ -#define WM8993_EQ_B1_B_SHIFT 0 /* EQ_B1_B - [15:0] */ -#define WM8993_EQ_B1_B_WIDTH 16 /* EQ_B1_B - [15:0] */ - -/* - * R106 (0x6A) - EQ9 - */ -#define WM8993_EQ_B1_PG_MASK 0xFFFF /* EQ_B1_PG - [15:0] */ -#define WM8993_EQ_B1_PG_SHIFT 0 /* EQ_B1_PG - [15:0] */ -#define WM8993_EQ_B1_PG_WIDTH 16 /* EQ_B1_PG - [15:0] */ - -/* - * R107 (0x6B) - EQ10 - */ -#define WM8993_EQ_B2_A_MASK 0xFFFF /* EQ_B2_A - [15:0] */ -#define WM8993_EQ_B2_A_SHIFT 0 /* EQ_B2_A - [15:0] */ -#define WM8993_EQ_B2_A_WIDTH 16 /* EQ_B2_A - [15:0] */ - -/* - * R108 (0x6C) - EQ11 - */ -#define WM8993_EQ_B2_B_MASK 0xFFFF /* EQ_B2_B - [15:0] */ -#define WM8993_EQ_B2_B_SHIFT 0 /* EQ_B2_B - [15:0] */ -#define WM8993_EQ_B2_B_WIDTH 16 /* EQ_B2_B - [15:0] */ - -/* - * R109 (0x6D) - EQ12 - */ -#define WM8993_EQ_B2_C_MASK 0xFFFF /* EQ_B2_C - [15:0] */ -#define WM8993_EQ_B2_C_SHIFT 0 /* EQ_B2_C - [15:0] */ -#define WM8993_EQ_B2_C_WIDTH 16 /* EQ_B2_C - [15:0] */ - -/* - * R110 (0x6E) - EQ13 - */ -#define WM8993_EQ_B2_PG_MASK 0xFFFF /* EQ_B2_PG - [15:0] */ -#define WM8993_EQ_B2_PG_SHIFT 0 /* EQ_B2_PG - [15:0] */ -#define WM8993_EQ_B2_PG_WIDTH 16 /* EQ_B2_PG - [15:0] */ - -/* - * R111 (0x6F) - EQ14 - */ -#define WM8993_EQ_B3_A_MASK 0xFFFF /* EQ_B3_A - [15:0] */ -#define WM8993_EQ_B3_A_SHIFT 0 /* EQ_B3_A - [15:0] */ -#define WM8993_EQ_B3_A_WIDTH 16 /* EQ_B3_A - [15:0] */ - -/* - * R112 (0x70) - EQ15 - */ -#define WM8993_EQ_B3_B_MASK 0xFFFF /* EQ_B3_B - [15:0] */ -#define WM8993_EQ_B3_B_SHIFT 0 /* EQ_B3_B - [15:0] */ -#define WM8993_EQ_B3_B_WIDTH 16 /* EQ_B3_B - [15:0] */ - -/* - * R113 (0x71) - EQ16 - */ -#define WM8993_EQ_B3_C_MASK 0xFFFF /* EQ_B3_C - [15:0] */ -#define WM8993_EQ_B3_C_SHIFT 0 /* EQ_B3_C - [15:0] */ -#define WM8993_EQ_B3_C_WIDTH 16 /* EQ_B3_C - [15:0] */ - -/* - * R114 (0x72) - EQ17 - */ -#define WM8993_EQ_B3_PG_MASK 0xFFFF /* EQ_B3_PG - [15:0] */ -#define WM8993_EQ_B3_PG_SHIFT 0 /* EQ_B3_PG - [15:0] */ -#define WM8993_EQ_B3_PG_WIDTH 16 /* EQ_B3_PG - [15:0] */ - -/* - * R115 (0x73) - EQ18 - */ -#define WM8993_EQ_B4_A_MASK 0xFFFF /* EQ_B4_A - [15:0] */ -#define WM8993_EQ_B4_A_SHIFT 0 /* EQ_B4_A - [15:0] */ -#define WM8993_EQ_B4_A_WIDTH 16 /* EQ_B4_A - [15:0] */ - -/* - * R116 (0x74) - EQ19 - */ -#define WM8993_EQ_B4_B_MASK 0xFFFF /* EQ_B4_B - [15:0] */ -#define WM8993_EQ_B4_B_SHIFT 0 /* EQ_B4_B - [15:0] */ -#define WM8993_EQ_B4_B_WIDTH 16 /* EQ_B4_B - [15:0] */ - -/* - * R117 (0x75) - EQ20 - */ -#define WM8993_EQ_B4_C_MASK 0xFFFF /* EQ_B4_C - [15:0] */ -#define WM8993_EQ_B4_C_SHIFT 0 /* EQ_B4_C - [15:0] */ -#define WM8993_EQ_B4_C_WIDTH 16 /* EQ_B4_C - [15:0] */ - -/* - * R118 (0x76) - EQ21 - */ -#define WM8993_EQ_B4_PG_MASK 0xFFFF /* EQ_B4_PG - [15:0] */ -#define WM8993_EQ_B4_PG_SHIFT 0 /* EQ_B4_PG - [15:0] */ -#define WM8993_EQ_B4_PG_WIDTH 16 /* EQ_B4_PG - [15:0] */ - -/* - * R119 (0x77) - EQ22 - */ -#define WM8993_EQ_B5_A_MASK 0xFFFF /* EQ_B5_A - [15:0] */ -#define WM8993_EQ_B5_A_SHIFT 0 /* EQ_B5_A - [15:0] */ -#define WM8993_EQ_B5_A_WIDTH 16 /* EQ_B5_A - [15:0] */ - -/* - * R120 (0x78) - EQ23 - */ -#define WM8993_EQ_B5_B_MASK 0xFFFF /* EQ_B5_B - [15:0] */ -#define WM8993_EQ_B5_B_SHIFT 0 /* EQ_B5_B - [15:0] */ -#define WM8993_EQ_B5_B_WIDTH 16 /* EQ_B5_B - [15:0] */ - -/* - * R121 (0x79) - EQ24 - */ -#define WM8993_EQ_B5_PG_MASK 0xFFFF /* EQ_B5_PG - [15:0] */ -#define WM8993_EQ_B5_PG_SHIFT 0 /* EQ_B5_PG - [15:0] */ -#define WM8993_EQ_B5_PG_WIDTH 16 /* EQ_B5_PG - [15:0] */ - -/* - * R122 (0x7A) - Digital Pulls - */ -#define WM8993_MCLK_PU 0x0080 /* MCLK_PU */ -#define WM8993_MCLK_PU_MASK 0x0080 /* MCLK_PU */ -#define WM8993_MCLK_PU_SHIFT 7 /* MCLK_PU */ -#define WM8993_MCLK_PU_WIDTH 1 /* MCLK_PU */ -#define WM8993_MCLK_PD 0x0040 /* MCLK_PD */ -#define WM8993_MCLK_PD_MASK 0x0040 /* MCLK_PD */ -#define WM8993_MCLK_PD_SHIFT 6 /* MCLK_PD */ -#define WM8993_MCLK_PD_WIDTH 1 /* MCLK_PD */ -#define WM8993_DACDAT_PU 0x0020 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_MASK 0x0020 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_SHIFT 5 /* DACDAT_PU */ -#define WM8993_DACDAT_PU_WIDTH 1 /* DACDAT_PU */ -#define WM8993_DACDAT_PD 0x0010 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_MASK 0x0010 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_SHIFT 4 /* DACDAT_PD */ -#define WM8993_DACDAT_PD_WIDTH 1 /* DACDAT_PD */ -#define WM8993_LRCLK_PU 0x0008 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_MASK 0x0008 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_SHIFT 3 /* LRCLK_PU */ -#define WM8993_LRCLK_PU_WIDTH 1 /* LRCLK_PU */ -#define WM8993_LRCLK_PD 0x0004 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_MASK 0x0004 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_SHIFT 2 /* LRCLK_PD */ -#define WM8993_LRCLK_PD_WIDTH 1 /* LRCLK_PD */ -#define WM8993_BCLK_PU 0x0002 /* BCLK_PU */ -#define WM8993_BCLK_PU_MASK 0x0002 /* BCLK_PU */ -#define WM8993_BCLK_PU_SHIFT 1 /* BCLK_PU */ -#define WM8993_BCLK_PU_WIDTH 1 /* BCLK_PU */ -#define WM8993_BCLK_PD 0x0001 /* BCLK_PD */ -#define WM8993_BCLK_PD_MASK 0x0001 /* BCLK_PD */ -#define WM8993_BCLK_PD_SHIFT 0 /* BCLK_PD */ -#define WM8993_BCLK_PD_WIDTH 1 /* BCLK_PD */ - -/* - * R123 (0x7B) - DRC Control 1 - */ -#define WM8993_DRC_ENA 0x8000 /* DRC_ENA */ -#define WM8993_DRC_ENA_MASK 0x8000 /* DRC_ENA */ -#define WM8993_DRC_ENA_SHIFT 15 /* DRC_ENA */ -#define WM8993_DRC_ENA_WIDTH 1 /* DRC_ENA */ -#define WM8993_DRC_DAC_PATH 0x4000 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_MASK 0x4000 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_SHIFT 14 /* DRC_DAC_PATH */ -#define WM8993_DRC_DAC_PATH_WIDTH 1 /* DRC_DAC_PATH */ -#define WM8993_DRC_SMOOTH_ENA 0x0800 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_MASK 0x0800 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_SHIFT 11 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_SMOOTH_ENA_WIDTH 1 /* DRC_SMOOTH_ENA */ -#define WM8993_DRC_QR_ENA 0x0400 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_MASK 0x0400 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_SHIFT 10 /* DRC_QR_ENA */ -#define WM8993_DRC_QR_ENA_WIDTH 1 /* DRC_QR_ENA */ -#define WM8993_DRC_ANTICLIP_ENA 0x0200 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_MASK 0x0200 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_SHIFT 9 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_ANTICLIP_ENA_WIDTH 1 /* DRC_ANTICLIP_ENA */ -#define WM8993_DRC_HYST_ENA 0x0100 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_MASK 0x0100 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_SHIFT 8 /* DRC_HYST_ENA */ -#define WM8993_DRC_HYST_ENA_WIDTH 1 /* DRC_HYST_ENA */ -#define WM8993_DRC_THRESH_HYST_MASK 0x0030 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_THRESH_HYST_SHIFT 4 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_THRESH_HYST_WIDTH 2 /* DRC_THRESH_HYST - [5:4] */ -#define WM8993_DRC_MINGAIN_MASK 0x000C /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MINGAIN_WIDTH 2 /* DRC_MINGAIN - [3:2] */ -#define WM8993_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */ -#define WM8993_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */ -#define WM8993_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */ - -/* - * R124 (0x7C) - DRC Control 2 - */ -#define WM8993_DRC_ATTACK_RATE_MASK 0xF000 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_ATTACK_RATE_SHIFT 12 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_ATTACK_RATE_WIDTH 4 /* DRC_ATTACK_RATE - [15:12] */ -#define WM8993_DRC_DECAY_RATE_MASK 0x0F00 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_DECAY_RATE_SHIFT 8 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_DECAY_RATE_WIDTH 4 /* DRC_DECAY_RATE - [11:8] */ -#define WM8993_DRC_THRESH_COMP_MASK 0x00FC /* DRC_THRESH_COMP - [7:2] */ -#define WM8993_DRC_THRESH_COMP_SHIFT 2 /* DRC_THRESH_COMP - [7:2] */ -#define WM8993_DRC_THRESH_COMP_WIDTH 6 /* DRC_THRESH_COMP - [7:2] */ - -/* - * R125 (0x7D) - DRC Control 3 - */ -#define WM8993_DRC_AMP_COMP_MASK 0xF800 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_AMP_COMP_SHIFT 11 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_AMP_COMP_WIDTH 5 /* DRC_AMP_COMP - [15:11] */ -#define WM8993_DRC_R0_SLOPE_COMP_MASK 0x0700 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_R0_SLOPE_COMP_SHIFT 8 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_R0_SLOPE_COMP_WIDTH 3 /* DRC_R0_SLOPE_COMP - [10:8] */ -#define WM8993_DRC_FF_DELAY 0x0080 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_MASK 0x0080 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_SHIFT 7 /* DRC_FF_DELAY */ -#define WM8993_DRC_FF_DELAY_WIDTH 1 /* DRC_FF_DELAY */ -#define WM8993_DRC_THRESH_QR_MASK 0x000C /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_THRESH_QR_SHIFT 2 /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_THRESH_QR_WIDTH 2 /* DRC_THRESH_QR - [3:2] */ -#define WM8993_DRC_RATE_QR_MASK 0x0003 /* DRC_RATE_QR - [1:0] */ -#define WM8993_DRC_RATE_QR_SHIFT 0 /* DRC_RATE_QR - [1:0] */ -#define WM8993_DRC_RATE_QR_WIDTH 2 /* DRC_RATE_QR - [1:0] */ - -/* - * R126 (0x7E) - DRC Control 4 - */ -#define WM8993_DRC_R1_SLOPE_COMP_MASK 0xE000 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_R1_SLOPE_COMP_SHIFT 13 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_R1_SLOPE_COMP_WIDTH 3 /* DRC_R1_SLOPE_COMP - [15:13] */ -#define WM8993_DRC_STARTUP_GAIN_MASK 0x1F00 /* DRC_STARTUP_GAIN - [12:8] */ -#define WM8993_DRC_STARTUP_GAIN_SHIFT 8 /* DRC_STARTUP_GAIN - [12:8] */ -#define WM8993_DRC_STARTUP_GAIN_WIDTH 5 /* DRC_STARTUP_GAIN - [12:8] */ - -#endif diff --git a/trunk/sound/soc/codecs/wm9081.c b/trunk/sound/soc/codecs/wm9081.c index c64e55aa63b6..86fc57e25f97 100644 --- a/trunk/sound/soc/codecs/wm9081.c +++ b/trunk/sound/soc/codecs/wm9081.c @@ -165,23 +165,87 @@ struct wm9081_priv { int master; int fll_fref; int fll_fout; - int tdm_width; struct wm9081_retune_mobile_config *retune; }; -static int wm9081_volatile_register(unsigned int reg) +static int wm9081_reg_is_volatile(int reg) { switch (reg) { - case WM9081_SOFTWARE_RESET: - return 1; default: return 0; } } +static unsigned int wm9081_read_reg_cache(struct snd_soc_codec *codec, + unsigned int reg) +{ + u16 *cache = codec->reg_cache; + BUG_ON(reg > WM9081_MAX_REGISTER); + return cache[reg]; +} + +static unsigned int wm9081_read_hw(struct snd_soc_codec *codec, u8 reg) +{ + struct i2c_msg xfer[2]; + u16 data; + int ret; + struct i2c_client *client = codec->control_data; + + BUG_ON(reg > WM9081_MAX_REGISTER); + + /* Write register */ + xfer[0].addr = client->addr; + xfer[0].flags = 0; + xfer[0].len = 1; + xfer[0].buf = ® + + /* Read data */ + xfer[1].addr = client->addr; + xfer[1].flags = I2C_M_RD; + xfer[1].len = 2; + xfer[1].buf = (u8 *)&data; + + ret = i2c_transfer(client->adapter, xfer, 2); + if (ret != 2) { + dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); + return 0; + } + + return (data >> 8) | ((data & 0xff) << 8); +} + +static unsigned int wm9081_read(struct snd_soc_codec *codec, unsigned int reg) +{ + if (wm9081_reg_is_volatile(reg)) + return wm9081_read_hw(codec, reg); + else + return wm9081_read_reg_cache(codec, reg); +} + +static int wm9081_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + u16 *cache = codec->reg_cache; + u8 data[3]; + + BUG_ON(reg > WM9081_MAX_REGISTER); + + if (!wm9081_reg_is_volatile(reg)) + cache[reg] = value; + + data[0] = reg; + data[1] = value >> 8; + data[2] = value & 0x00ff; + + if (codec->hw_write(codec->control_data, data, 3) == 3) + return 0; + else + return -EIO; +} + static int wm9081_reset(struct snd_soc_codec *codec) { - return snd_soc_write(codec, WM9081_SOFTWARE_RESET, 0); + return wm9081_write(codec, WM9081_SOFTWARE_RESET, 0); } static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0); @@ -292,7 +356,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg; - reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2); + reg = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_2); if (reg & WM9081_SPK_MODE) ucontrol->value.integer.value[0] = 1; else @@ -311,8 +375,8 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned int reg_pwr = snd_soc_read(codec, WM9081_POWER_MANAGEMENT); - unsigned int reg2 = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_2); + unsigned int reg_pwr = wm9081_read(codec, WM9081_POWER_MANAGEMENT); + unsigned int reg2 = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_2); /* Are we changing anything? */ if (ucontrol->value.integer.value[0] == @@ -333,7 +397,7 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol, reg2 &= ~WM9081_SPK_MODE; } - snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2); + wm9081_write(codec, WM9081_ANALOGUE_SPEAKER_2, reg2); return 0; } @@ -392,7 +456,7 @@ static int speaker_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; - unsigned int reg = snd_soc_read(codec, WM9081_POWER_MANAGEMENT); + unsigned int reg = wm9081_read(codec, WM9081_POWER_MANAGEMENT); switch (event) { case SND_SOC_DAPM_POST_PMU: @@ -404,7 +468,7 @@ static int speaker_event(struct snd_soc_dapm_widget *w, break; } - snd_soc_write(codec, WM9081_POWER_MANAGEMENT, reg); + wm9081_write(codec, WM9081_POWER_MANAGEMENT, reg); return 0; } @@ -543,7 +607,7 @@ static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id, if (ret != 0) return ret; - reg5 = snd_soc_read(codec, WM9081_FLL_CONTROL_5); + reg5 = wm9081_read(codec, WM9081_FLL_CONTROL_5); reg5 &= ~WM9081_FLL_CLK_SRC_MASK; switch (fll_id) { @@ -557,44 +621,44 @@ static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id, } /* Disable CLK_SYS while we reconfigure */ - clk_sys_reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3); + clk_sys_reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_3); if (clk_sys_reg & WM9081_CLK_SYS_ENA) - snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, + wm9081_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg & ~WM9081_CLK_SYS_ENA); /* Any FLL configuration change requires that the FLL be * disabled first. */ - reg1 = snd_soc_read(codec, WM9081_FLL_CONTROL_1); + reg1 = wm9081_read(codec, WM9081_FLL_CONTROL_1); reg1 &= ~WM9081_FLL_ENA; - snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1); + wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1); /* Apply the configuration */ if (fll_div.k) reg1 |= WM9081_FLL_FRAC_MASK; else reg1 &= ~WM9081_FLL_FRAC_MASK; - snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1); + wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1); - snd_soc_write(codec, WM9081_FLL_CONTROL_2, + wm9081_write(codec, WM9081_FLL_CONTROL_2, (fll_div.fll_outdiv << WM9081_FLL_OUTDIV_SHIFT) | (fll_div.fll_fratio << WM9081_FLL_FRATIO_SHIFT)); - snd_soc_write(codec, WM9081_FLL_CONTROL_3, fll_div.k); + wm9081_write(codec, WM9081_FLL_CONTROL_3, fll_div.k); - reg4 = snd_soc_read(codec, WM9081_FLL_CONTROL_4); + reg4 = wm9081_read(codec, WM9081_FLL_CONTROL_4); reg4 &= ~WM9081_FLL_N_MASK; reg4 |= fll_div.n << WM9081_FLL_N_SHIFT; - snd_soc_write(codec, WM9081_FLL_CONTROL_4, reg4); + wm9081_write(codec, WM9081_FLL_CONTROL_4, reg4); reg5 &= ~WM9081_FLL_CLK_REF_DIV_MASK; reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT; - snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5); + wm9081_write(codec, WM9081_FLL_CONTROL_5, reg5); /* Enable the FLL */ - snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA); + wm9081_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA); /* Then bring CLK_SYS up again if it was disabled */ if (clk_sys_reg & WM9081_CLK_SYS_ENA) - snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg); + wm9081_write(codec, WM9081_CLOCK_CONTROL_3, clk_sys_reg); dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); @@ -643,10 +707,6 @@ static int configure_clock(struct snd_soc_codec *codec) target > 3000000) break; } - - if (i == ARRAY_SIZE(clk_sys_rates)) - return -EINVAL; - } else if (wm9081->fs) { for (i = 0; i < ARRAY_SIZE(clk_sys_rates); i++) { new_sysclk = clk_sys_rates[i].ratio @@ -654,10 +714,6 @@ static int configure_clock(struct snd_soc_codec *codec) if (new_sysclk > 3000000) break; } - - if (i == ARRAY_SIZE(clk_sys_rates)) - return -EINVAL; - } else { new_sysclk = 12288000; } @@ -678,19 +734,19 @@ static int configure_clock(struct snd_soc_codec *codec) return -EINVAL; } - reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_1); + reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_1); if (mclkdiv) reg |= WM9081_MCLKDIV2; else reg &= ~WM9081_MCLKDIV2; - snd_soc_write(codec, WM9081_CLOCK_CONTROL_1, reg); + wm9081_write(codec, WM9081_CLOCK_CONTROL_1, reg); - reg = snd_soc_read(codec, WM9081_CLOCK_CONTROL_3); + reg = wm9081_read(codec, WM9081_CLOCK_CONTROL_3); if (fll) reg |= WM9081_CLK_SRC_SEL; else reg &= ~WM9081_CLK_SRC_SEL; - snd_soc_write(codec, WM9081_CLOCK_CONTROL_3, reg); + wm9081_write(codec, WM9081_CLOCK_CONTROL_3, reg); dev_dbg(codec->dev, "CLK_SYS is %dHz\n", wm9081->sysclk_rate); @@ -790,76 +846,76 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: /* VMID=2*40k */ - reg = snd_soc_read(codec, WM9081_VMID_CONTROL); + reg = wm9081_read(codec, WM9081_VMID_CONTROL); reg &= ~WM9081_VMID_SEL_MASK; reg |= 0x2; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + wm9081_write(codec, WM9081_VMID_CONTROL, reg); /* Normal bias current */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1); reg &= ~WM9081_STBY_BIAS_ENA; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg); break; case SND_SOC_BIAS_STANDBY: /* Initial cold start */ if (codec->bias_level == SND_SOC_BIAS_OFF) { /* Disable LINEOUT discharge */ - reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL); + reg = wm9081_read(codec, WM9081_ANTI_POP_CONTROL); reg &= ~WM9081_LINEOUT_DISCH; - snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg); + wm9081_write(codec, WM9081_ANTI_POP_CONTROL, reg); /* Select startup bias source */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1); reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg); /* VMID 2*4k; Soft VMID ramp enable */ - reg = snd_soc_read(codec, WM9081_VMID_CONTROL); + reg = wm9081_read(codec, WM9081_VMID_CONTROL); reg |= WM9081_VMID_RAMP | 0x6; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + wm9081_write(codec, WM9081_VMID_CONTROL, reg); mdelay(100); /* Normal bias enable & soft start off */ reg |= WM9081_BIAS_ENA; reg &= ~WM9081_VMID_RAMP; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + wm9081_write(codec, WM9081_VMID_CONTROL, reg); /* Standard bias source */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1); reg &= ~WM9081_BIAS_SRC; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg); } /* VMID 2*240k */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1); reg &= ~WM9081_VMID_SEL_MASK; reg |= 0x40; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + wm9081_write(codec, WM9081_VMID_CONTROL, reg); /* Standby bias current on */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1); reg |= WM9081_STBY_BIAS_ENA; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg); break; case SND_SOC_BIAS_OFF: /* Startup bias source */ - reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1); + reg = wm9081_read(codec, WM9081_BIAS_CONTROL_1); reg |= WM9081_BIAS_SRC; - snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg); + wm9081_write(codec, WM9081_BIAS_CONTROL_1, reg); /* Disable VMID and biases with soft ramping */ - reg = snd_soc_read(codec, WM9081_VMID_CONTROL); + reg = wm9081_read(codec, WM9081_VMID_CONTROL); reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA); reg |= WM9081_VMID_RAMP; - snd_soc_write(codec, WM9081_VMID_CONTROL, reg); + wm9081_write(codec, WM9081_VMID_CONTROL, reg); /* Actively discharge LINEOUT */ - reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL); + reg = wm9081_read(codec, WM9081_ANTI_POP_CONTROL); reg |= WM9081_LINEOUT_DISCH; - snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg); + wm9081_write(codec, WM9081_ANTI_POP_CONTROL, reg); break; } @@ -873,7 +929,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, { struct snd_soc_codec *codec = dai->codec; struct wm9081_priv *wm9081 = codec->private_data; - unsigned int aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2); + unsigned int aif2 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_2); aif2 &= ~(WM9081_AIF_BCLK_INV | WM9081_AIF_LRCLK_INV | WM9081_BCLK_DIR | WM9081_LRCLK_DIR | WM9081_AIF_FMT_MASK); @@ -954,7 +1010,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai, return -EINVAL; } - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2); + wm9081_write(codec, WM9081_AUDIO_INTERFACE_2, aif2); return 0; } @@ -968,51 +1024,47 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, int ret, i, best, best_val, cur_val; unsigned int clk_ctrl2, aif1, aif2, aif3, aif4; - clk_ctrl2 = snd_soc_read(codec, WM9081_CLOCK_CONTROL_2); + clk_ctrl2 = wm9081_read(codec, WM9081_CLOCK_CONTROL_2); clk_ctrl2 &= ~(WM9081_CLK_SYS_RATE_MASK | WM9081_SAMPLE_RATE_MASK); - aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1); + aif1 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_1); - aif2 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_2); + aif2 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_2); aif2 &= ~WM9081_AIF_WL_MASK; - aif3 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_3); + aif3 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_3); aif3 &= ~WM9081_BCLK_DIV_MASK; - aif4 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_4); + aif4 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_4); aif4 &= ~WM9081_LRCLK_RATE_MASK; + /* What BCLK do we need? */ wm9081->fs = params_rate(params); + wm9081->bclk = 2 * wm9081->fs; + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + wm9081->bclk *= 16; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + wm9081->bclk *= 20; + aif2 |= 0x4; + break; + case SNDRV_PCM_FORMAT_S24_LE: + wm9081->bclk *= 24; + aif2 |= 0x8; + break; + case SNDRV_PCM_FORMAT_S32_LE: + wm9081->bclk *= 32; + aif2 |= 0xc; + break; + default: + return -EINVAL; + } - if (wm9081->tdm_width) { - /* If TDM is set up then that fixes our BCLK. */ + if (aif1 & WM9081_AIFDAC_TDM_MODE_MASK) { int slots = ((aif1 & WM9081_AIFDAC_TDM_MODE_MASK) >> WM9081_AIFDAC_TDM_MODE_SHIFT) + 1; - - wm9081->bclk = wm9081->fs * wm9081->tdm_width * slots; - } else { - /* Otherwise work out a BCLK from the sample size */ - wm9081->bclk = 2 * wm9081->fs; - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - wm9081->bclk *= 16; - break; - case SNDRV_PCM_FORMAT_S20_3LE: - wm9081->bclk *= 20; - aif2 |= 0x4; - break; - case SNDRV_PCM_FORMAT_S24_LE: - wm9081->bclk *= 24; - aif2 |= 0x8; - break; - case SNDRV_PCM_FORMAT_S32_LE: - wm9081->bclk *= 32; - aif2 |= 0xc; - break; - default: - return -EINVAL; - } + wm9081->bclk *= slots; } dev_dbg(codec->dev, "Target BCLK is %dHz\n", wm9081->bclk); @@ -1097,22 +1149,22 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, s->name, s->rate); /* If the EQ is enabled then disable it while we write out */ - eq1 = snd_soc_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA; + eq1 = wm9081_read(codec, WM9081_EQ_1) & WM9081_EQ_ENA; if (eq1 & WM9081_EQ_ENA) - snd_soc_write(codec, WM9081_EQ_1, 0); + wm9081_write(codec, WM9081_EQ_1, 0); /* Write out the other values */ for (i = 1; i < ARRAY_SIZE(s->config); i++) - snd_soc_write(codec, WM9081_EQ_1 + i, s->config[i]); + wm9081_write(codec, WM9081_EQ_1 + i, s->config[i]); eq1 |= (s->config[0] & ~WM9081_EQ_ENA); - snd_soc_write(codec, WM9081_EQ_1, eq1); + wm9081_write(codec, WM9081_EQ_1, eq1); } - snd_soc_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2); - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_2, aif2); - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_3, aif3); - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_4, aif4); + wm9081_write(codec, WM9081_CLOCK_CONTROL_2, clk_ctrl2); + wm9081_write(codec, WM9081_AUDIO_INTERFACE_2, aif2); + wm9081_write(codec, WM9081_AUDIO_INTERFACE_3, aif3); + wm9081_write(codec, WM9081_AUDIO_INTERFACE_4, aif4); return 0; } @@ -1122,14 +1174,14 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) struct snd_soc_codec *codec = codec_dai->codec; unsigned int reg; - reg = snd_soc_read(codec, WM9081_DAC_DIGITAL_2); + reg = wm9081_read(codec, WM9081_DAC_DIGITAL_2); if (mute) reg |= WM9081_DAC_MUTE; else reg &= ~WM9081_DAC_MUTE; - snd_soc_write(codec, WM9081_DAC_DIGITAL_2, reg); + wm9081_write(codec, WM9081_DAC_DIGITAL_2, reg); return 0; } @@ -1155,25 +1207,19 @@ static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai, } static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) + unsigned int mask, int slots) { struct snd_soc_codec *codec = dai->codec; - struct wm9081_priv *wm9081 = codec->private_data; - unsigned int aif1 = snd_soc_read(codec, WM9081_AUDIO_INTERFACE_1); + unsigned int aif1 = wm9081_read(codec, WM9081_AUDIO_INTERFACE_1); aif1 &= ~(WM9081_AIFDAC_TDM_SLOT_MASK | WM9081_AIFDAC_TDM_MODE_MASK); - if (slots < 0 || slots > 4) + if (slots < 1 || slots > 4) return -EINVAL; - wm9081->tdm_width = slot_width; - - if (slots == 0) - slots = 1; - aif1 |= (slots - 1) << WM9081_AIFDAC_TDM_MODE_SHIFT; - switch (rx_mask) { + switch (mask) { case 1: break; case 2: @@ -1189,7 +1235,7 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, return -EINVAL; } - snd_soc_write(codec, WM9081_AUDIO_INTERFACE_1, aif1); + wm9081_write(codec, WM9081_AUDIO_INTERFACE_1, aif1); return 0; } @@ -1311,7 +1357,7 @@ static int wm9081_resume(struct platform_device *pdev) if (i == WM9081_SOFTWARE_RESET) continue; - snd_soc_write(codec, i, reg_cache[i]); + wm9081_write(codec, i, reg_cache[i]); } wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); @@ -1331,8 +1377,7 @@ struct snd_soc_codec_device soc_codec_dev_wm9081 = { }; EXPORT_SYMBOL_GPL(soc_codec_dev_wm9081); -static int wm9081_register(struct wm9081_priv *wm9081, - enum snd_soc_control_type control) +static int wm9081_register(struct wm9081_priv *wm9081) { struct snd_soc_codec *codec = &wm9081->codec; int ret; @@ -1351,24 +1396,19 @@ static int wm9081_register(struct wm9081_priv *wm9081, codec->private_data = wm9081; codec->name = "WM9081"; codec->owner = THIS_MODULE; + codec->read = wm9081_read; + codec->write = wm9081_write; codec->dai = &wm9081_dai; codec->num_dai = 1; codec->reg_cache_size = ARRAY_SIZE(wm9081->reg_cache); codec->reg_cache = &wm9081->reg_cache; codec->bias_level = SND_SOC_BIAS_OFF; codec->set_bias_level = wm9081_set_bias_level; - codec->volatile_register = wm9081_volatile_register; memcpy(codec->reg_cache, wm9081_reg_defaults, sizeof(wm9081_reg_defaults)); - ret = snd_soc_codec_set_cache_io(codec, 8, 16, control); - if (ret != 0) { - dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); - return ret; - } - - reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET); + reg = wm9081_read_hw(codec, WM9081_SOFTWARE_RESET); if (reg != 0x9081) { dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg); ret = -EINVAL; @@ -1384,10 +1424,10 @@ static int wm9081_register(struct wm9081_priv *wm9081, wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); /* Enable zero cross by default */ - reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT); - snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); - reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); - snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, + reg = wm9081_read(codec, WM9081_ANALOGUE_LINEOUT); + wm9081_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC); + reg = wm9081_read(codec, WM9081_ANALOGUE_SPEAKER_PGA); + wm9081_write(codec, WM9081_ANALOGUE_SPEAKER_PGA, reg | WM9081_SPKPGAZC); wm9081_dai.dev = codec->dev; @@ -1442,7 +1482,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, codec->dev = &i2c->dev; - return wm9081_register(wm9081, SND_SOC_I2C); + return wm9081_register(wm9081); } static __devexit int wm9081_i2c_remove(struct i2c_client *client) @@ -1452,21 +1492,6 @@ static __devexit int wm9081_i2c_remove(struct i2c_client *client) return 0; } -#ifdef CONFIG_PM -static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg) -{ - return snd_soc_suspend_device(&client->dev); -} - -static int wm9081_i2c_resume(struct i2c_client *client) -{ - return snd_soc_resume_device(&client->dev); -} -#else -#define wm9081_i2c_suspend NULL -#define wm9081_i2c_resume NULL -#endif - static const struct i2c_device_id wm9081_i2c_id[] = { { "wm9081", 0 }, { } @@ -1480,8 +1505,6 @@ static struct i2c_driver wm9081_i2c_driver = { }, .probe = wm9081_i2c_probe, .remove = __devexit_p(wm9081_i2c_remove), - .suspend = wm9081_i2c_suspend, - .resume = wm9081_i2c_resume, .id_table = wm9081_i2c_id, }; diff --git a/trunk/sound/soc/codecs/wm9705.c b/trunk/sound/soc/codecs/wm9705.c index e7d2840d9e59..fa88b463e71f 100644 --- a/trunk/sound/soc/codecs/wm9705.c +++ b/trunk/sound/soc/codecs/wm9705.c @@ -406,7 +406,7 @@ static int wm9705_soc_probe(struct platform_device *pdev) ret = snd_soc_init_card(socdev); if (ret < 0) { printk(KERN_ERR "wm9705: failed to register card\n"); - goto reset_err; + goto pcm_err; } return 0; diff --git a/trunk/sound/soc/codecs/wm_hubs.c b/trunk/sound/soc/codecs/wm_hubs.c deleted file mode 100644 index e542027eea89..000000000000 --- a/trunk/sound/soc/codecs/wm_hubs.c +++ /dev/null @@ -1,743 +0,0 @@ -/* - * wm_hubs.c -- WM8993/4 common code - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wm8993.h" -#include "wm_hubs.h" - -const DECLARE_TLV_DB_SCALE(wm_hubs_spkmix_tlv, -300, 300, 0); -EXPORT_SYMBOL_GPL(wm_hubs_spkmix_tlv); - -static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0); -static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0); -static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1); -static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0); -static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0); -static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1); -static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0); -static const unsigned int spkboost_tlv[] = { - TLV_DB_RANGE_HEAD(7), - 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0), - 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0), -}; -static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0); - -static const char *speaker_ref_text[] = { - "SPKVDD/2", - "VMID", -}; - -static const struct soc_enum speaker_ref = - SOC_ENUM_SINGLE(WM8993_SPEAKER_MIXER, 8, 2, speaker_ref_text); - -static const char *speaker_mode_text[] = { - "Class D", - "Class AB", -}; - -static const struct soc_enum speaker_mode = - SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); - -static void wait_for_dc_servo(struct snd_soc_codec *codec) -{ - unsigned int reg; - int count = 0; - - dev_dbg(codec->dev, "Waiting for DC servo...\n"); - do { - count++; - msleep(1); - reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0); - dev_dbg(codec->dev, "DC servo status: %x\n", reg); - } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK) - != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000); - - if ((reg & WM8993_DCS_CAL_COMPLETE_MASK) - != WM8993_DCS_CAL_COMPLETE_MASK) - dev_err(codec->dev, "Timed out waiting for DC Servo\n"); -} - -/* - * Update the DC servo calibration on gain changes - */ -static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - int ret; - - ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); - - /* Only need to do this if the outputs are active */ - if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) - & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) - snd_soc_update_bits(codec, - WM8993_DC_SERVO_0, - WM8993_DCS_TRIG_SINGLE_0 | - WM8993_DCS_TRIG_SINGLE_1, - WM8993_DCS_TRIG_SINGLE_0 | - WM8993_DCS_TRIG_SINGLE_1); - - return ret; -} - -static const struct snd_kcontrol_new analogue_snd_controls[] = { -SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 0), - -SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1), -SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 0), - - -SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 0), - -SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0, - inpga_tlv), -SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1), -SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 0), - -SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0, - inmix_tlv), -SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv), -SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0, - inmix_tlv), - -SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0, - inmix_sw_tlv), -SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0, - inmix_tlv), -SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv), -SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0, - inmix_tlv), - -SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1, - outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer Right Input Volume", - WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer Left Input Volume", - WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1, - outmix_tlv), - -SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume", - WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume", - WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN1L Volume", - WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN1R Volume", - WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume", - WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer Left Input Volume", - WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer Right Input Volume", - WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv), -SOC_SINGLE_TLV("Right Output Mixer DAC Volume", - WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv), - -SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv), -SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0), -SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME, - WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0), - -SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1), -SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv), - -SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION, - 5, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION, - 4, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION, - 3, 1, 1, wm_hubs_spkmix_tlv), - -SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION, - 5, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION, - 4, 1, 1, wm_hubs_spkmix_tlv), -SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION, - 3, 1, 1, wm_hubs_spkmix_tlv), - -SOC_DOUBLE_R_TLV("Speaker Mixer Volume", - WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION, - 0, 3, 1, spkmixout_tlv), -SOC_DOUBLE_R_TLV("Speaker Volume", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 0, 63, 0, outpga_tlv), -SOC_DOUBLE_R("Speaker Switch", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 6, 1, 0), -SOC_DOUBLE_R("Speaker ZC Switch", - WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT, - 7, 1, 0), -SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 0, 3, 7, 0, - spkboost_tlv), -SOC_ENUM("Speaker Reference", speaker_ref), -SOC_ENUM("Speaker Mode", speaker_mode), - -{ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume", - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | - SNDRV_CTL_ELEM_ACCESS_READWRITE, - .tlv.p = outpga_tlv, - .info = snd_soc_info_volsw_2r, - .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo, - .private_value = (unsigned long)&(struct soc_mixer_control) { - .reg = WM8993_LEFT_OUTPUT_VOLUME, - .rreg = WM8993_RIGHT_OUTPUT_VOLUME, - .shift = 0, .max = 63 - }, -}, -SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME, - WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0), -SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME, - WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0), - -SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1), -SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1), -SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1, - line_tlv), - -SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1), -SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1), -SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1, - line_tlv), -}; - -static int hp_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_codec *codec = w->codec; - unsigned int reg = snd_soc_read(codec, WM8993_ANALOGUE_HP_0); - - switch (event) { - case SND_SOC_DAPM_POST_PMU: - snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, - WM8993_CP_ENA, WM8993_CP_ENA); - - msleep(5); - - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA); - - reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY; - snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); - - /* Start the DC servo */ - snd_soc_update_bits(codec, WM8993_DC_SERVO_0, - 0xFFFF, - WM8993_DCS_ENA_CHAN_0 | - WM8993_DCS_ENA_CHAN_1 | - WM8993_DCS_TRIG_STARTUP_1 | - WM8993_DCS_TRIG_STARTUP_0); - wait_for_dc_servo(codec); - - reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | - WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; - snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); - break; - - case SND_SOC_DAPM_PRE_PMD: - reg &= ~(WM8993_HPOUT1L_RMV_SHORT | - WM8993_HPOUT1L_DLY | - WM8993_HPOUT1L_OUTP | - WM8993_HPOUT1R_RMV_SHORT | - WM8993_HPOUT1R_DLY | - WM8993_HPOUT1R_OUTP); - - snd_soc_update_bits(codec, WM8993_DC_SERVO_0, - 0xffff, 0); - - snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); - snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, - WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, - 0); - - snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, - WM8993_CP_ENA, 0); - break; - } - - return 0; -} - -static int earpiece_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *control, int event) -{ - struct snd_soc_codec *codec = w->codec; - u16 reg = snd_soc_read(codec, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA; - - switch (event) { - case SND_SOC_DAPM_PRE_PMU: - reg |= WM8993_HPOUT2_IN_ENA; - snd_soc_write(codec, WM8993_ANTIPOP1, reg); - udelay(50); - break; - - case SND_SOC_DAPM_POST_PMD: - snd_soc_write(codec, WM8993_ANTIPOP1, reg); - break; - - default: - BUG(); - break; - } - - return 0; -} - -static const struct snd_kcontrol_new in1l_pga[] = { -SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0), -SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0), -}; - -static const struct snd_kcontrol_new in1r_pga[] = { -SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new in2l_pga[] = { -SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0), -}; - -static const struct snd_kcontrol_new in2r_pga[] = { -SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0), -}; - -static const struct snd_kcontrol_new mixinl[] = { -SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0), -}; - -static const struct snd_kcontrol_new mixinr[] = { -SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0), -}; - -static const struct snd_kcontrol_new left_output_mixer[] = { -SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0), -SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0), -SOC_DAPM_SINGLE("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new right_output_mixer[] = { -SOC_DAPM_SINGLE("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0), -SOC_DAPM_SINGLE("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0), -SOC_DAPM_SINGLE("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0), -SOC_DAPM_SINGLE("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new earpiece_mixer[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0), -SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0), -}; - -static const struct snd_kcontrol_new left_speaker_boost[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0), -SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0), -SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0), -}; - -static const struct snd_kcontrol_new right_speaker_boost[] = { -SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0), -SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0), -SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line1_mix[] = { -SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0), -SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line1n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0), -}; - -static const struct snd_kcontrol_new line1p_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line2_mix[] = { -SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0), -SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0), -SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), -}; - -static const struct snd_kcontrol_new line2n_mix[] = { -SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0), -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0), -}; - -static const struct snd_kcontrol_new line2p_mix[] = { -SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0), -}; - -static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = { -SND_SOC_DAPM_INPUT("IN1LN"), -SND_SOC_DAPM_INPUT("IN1LP"), -SND_SOC_DAPM_INPUT("IN2LN"), -SND_SOC_DAPM_INPUT("IN2LP/VXRN"), -SND_SOC_DAPM_INPUT("IN1RN"), -SND_SOC_DAPM_INPUT("IN1RP"), -SND_SOC_DAPM_INPUT("IN2RN"), -SND_SOC_DAPM_INPUT("IN2RP/VXRP"), - -SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), -SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), - -SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, - in1l_pga, ARRAY_SIZE(in1l_pga)), -SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0, - in1r_pga, ARRAY_SIZE(in1r_pga)), - -SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0, - in2l_pga, ARRAY_SIZE(in2l_pga)), -SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0, - in2r_pga, ARRAY_SIZE(in2r_pga)), - -/* Dummy widgets to represent differential paths */ -SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), - -SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0, - mixinl, ARRAY_SIZE(mixinl)), -SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0, - mixinr, ARRAY_SIZE(mixinr)), - -SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0, - left_output_mixer, ARRAY_SIZE(left_output_mixer)), -SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, - right_output_mixer, ARRAY_SIZE(right_output_mixer)), - -SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0), -SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0), - -SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0, - NULL, 0, - hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), - -SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, - earpiece_mixer, ARRAY_SIZE(earpiece_mixer)), -SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0, - NULL, 0, earpiece_event, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - -SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0, - left_speaker_boost, ARRAY_SIZE(left_speaker_boost)), -SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0, - right_speaker_boost, ARRAY_SIZE(right_speaker_boost)), - -SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0, - NULL, 0), -SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0, - NULL, 0), - -SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0, - line1_mix, ARRAY_SIZE(line1_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0, - line2_mix, ARRAY_SIZE(line2_mix)), - -SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0, - line1n_mix, ARRAY_SIZE(line1n_mix)), -SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0, - line1p_mix, ARRAY_SIZE(line1p_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0, - line2n_mix, ARRAY_SIZE(line2n_mix)), -SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0, - line2p_mix, ARRAY_SIZE(line2p_mix)), - -SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0, - NULL, 0), -SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0, - NULL, 0), - -SND_SOC_DAPM_OUTPUT("SPKOUTLP"), -SND_SOC_DAPM_OUTPUT("SPKOUTLN"), -SND_SOC_DAPM_OUTPUT("SPKOUTRP"), -SND_SOC_DAPM_OUTPUT("SPKOUTRN"), -SND_SOC_DAPM_OUTPUT("HPOUT1L"), -SND_SOC_DAPM_OUTPUT("HPOUT1R"), -SND_SOC_DAPM_OUTPUT("HPOUT2P"), -SND_SOC_DAPM_OUTPUT("HPOUT2N"), -SND_SOC_DAPM_OUTPUT("LINEOUT1P"), -SND_SOC_DAPM_OUTPUT("LINEOUT1N"), -SND_SOC_DAPM_OUTPUT("LINEOUT2P"), -SND_SOC_DAPM_OUTPUT("LINEOUT2N"), -}; - -static const struct snd_soc_dapm_route analogue_routes[] = { - { "IN1L PGA", "IN1LP Switch", "IN1LP" }, - { "IN1L PGA", "IN1LN Switch", "IN1LN" }, - - { "IN1R PGA", "IN1RP Switch", "IN1RP" }, - { "IN1R PGA", "IN1RN Switch", "IN1RN" }, - - { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" }, - { "IN2L PGA", "IN2LN Switch", "IN2LN" }, - - { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" }, - { "IN2R PGA", "IN2RN Switch", "IN2RN" }, - - { "Direct Voice", NULL, "IN2LP/VXRN" }, - { "Direct Voice", NULL, "IN2RP/VXRP" }, - - { "MIXINL", "IN1L Switch", "IN1L PGA" }, - { "MIXINL", "IN2L Switch", "IN2L PGA" }, - { "MIXINL", NULL, "Direct Voice" }, - { "MIXINL", NULL, "IN1LP" }, - { "MIXINL", NULL, "Left Output Mixer" }, - - { "MIXINR", "IN1R Switch", "IN1R PGA" }, - { "MIXINR", "IN2R Switch", "IN2R PGA" }, - { "MIXINR", NULL, "Direct Voice" }, - { "MIXINR", NULL, "IN1RP" }, - { "MIXINR", NULL, "Right Output Mixer" }, - - { "ADCL", NULL, "MIXINL" }, - { "ADCR", NULL, "MIXINR" }, - - { "Left Output Mixer", "Left Input Switch", "MIXINL" }, - { "Left Output Mixer", "Right Input Switch", "MIXINR" }, - { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, - { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, - { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" }, - { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, - { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, - - { "Right Output Mixer", "Left Input Switch", "MIXINL" }, - { "Right Output Mixer", "Right Input Switch", "MIXINR" }, - { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, - { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, - { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" }, - { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, - { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, - - { "Left Output PGA", NULL, "Left Output Mixer" }, - { "Left Output PGA", NULL, "TOCLK" }, - - { "Right Output PGA", NULL, "Right Output Mixer" }, - { "Right Output PGA", NULL, "TOCLK" }, - - { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" }, - { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, - { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, - - { "Earpiece Driver", NULL, "Earpiece Mixer" }, - { "HPOUT2N", NULL, "Earpiece Driver" }, - { "HPOUT2P", NULL, "Earpiece Driver" }, - - { "SPKL", "Input Switch", "MIXINL" }, - { "SPKL", "IN1LP Switch", "IN1LP" }, - { "SPKL", "Output Switch", "Left Output Mixer" }, - { "SPKL", NULL, "TOCLK" }, - - { "SPKR", "Input Switch", "MIXINR" }, - { "SPKR", "IN1RP Switch", "IN1RP" }, - { "SPKR", "Output Switch", "Right Output Mixer" }, - { "SPKR", NULL, "TOCLK" }, - - { "SPKL Boost", "Direct Voice Switch", "Direct Voice" }, - { "SPKL Boost", "SPKL Switch", "SPKL" }, - { "SPKL Boost", "SPKR Switch", "SPKR" }, - - { "SPKR Boost", "Direct Voice Switch", "Direct Voice" }, - { "SPKR Boost", "SPKR Switch", "SPKR" }, - { "SPKR Boost", "SPKL Switch", "SPKL" }, - - { "SPKL Driver", NULL, "SPKL Boost" }, - { "SPKL Driver", NULL, "CLK_SYS" }, - - { "SPKR Driver", NULL, "SPKR Boost" }, - { "SPKR Driver", NULL, "CLK_SYS" }, - - { "SPKOUTLP", NULL, "SPKL Driver" }, - { "SPKOUTLN", NULL, "SPKL Driver" }, - { "SPKOUTRP", NULL, "SPKR Driver" }, - { "SPKOUTRN", NULL, "SPKR Driver" }, - - { "Left Headphone Mux", "Mixer", "Left Output Mixer" }, - { "Right Headphone Mux", "Mixer", "Right Output Mixer" }, - - { "Headphone PGA", NULL, "Left Headphone Mux" }, - { "Headphone PGA", NULL, "Right Headphone Mux" }, - { "Headphone PGA", NULL, "CLK_SYS" }, - - { "HPOUT1L", NULL, "Headphone PGA" }, - { "HPOUT1R", NULL, "Headphone PGA" }, - - { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, - { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, - { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, - { "LINEOUT2P", NULL, "LINEOUT2P Driver" }, -}; - -static const struct snd_soc_dapm_route lineout1_diff_routes[] = { - { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" }, - { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" }, - { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" }, - - { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" }, - { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout1_se_routes[] = { - { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" }, - { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" }, - - { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" }, - - { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" }, - { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout2_diff_routes[] = { - { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" }, - { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" }, - { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" }, - - { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" }, - { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" }, -}; - -static const struct snd_soc_dapm_route lineout2_se_routes[] = { - { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" }, - { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" }, - - { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" }, - - { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" }, - { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" }, -}; - -int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec) -{ - /* Latch volume update bits & default ZC on */ - snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_1_2_VOLUME, - WM8993_IN1_VU, WM8993_IN1_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, - WM8993_IN1_VU, WM8993_IN1_VU); - snd_soc_update_bits(codec, WM8993_LEFT_LINE_INPUT_3_4_VOLUME, - WM8993_IN2_VU, WM8993_IN2_VU); - snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, - WM8993_IN2_VU, WM8993_IN2_VU); - - snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT, - WM8993_SPKOUT_VU, WM8993_SPKOUT_VU); - - snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME, - WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC); - snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME, - WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC, - WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC); - - snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME, - WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC); - snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME, - WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU, - WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU); - - snd_soc_add_controls(codec, analogue_snd_controls, - ARRAY_SIZE(analogue_snd_controls)); - - snd_soc_dapm_new_controls(codec, analogue_dapm_widgets, - ARRAY_SIZE(analogue_dapm_widgets)); - return 0; -} -EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls); - -int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, - int lineout1_diff, int lineout2_diff) -{ - snd_soc_dapm_add_routes(codec, analogue_routes, - ARRAY_SIZE(analogue_routes)); - - if (lineout1_diff) - snd_soc_dapm_add_routes(codec, - lineout1_diff_routes, - ARRAY_SIZE(lineout1_diff_routes)); - else - snd_soc_dapm_add_routes(codec, - lineout1_se_routes, - ARRAY_SIZE(lineout1_se_routes)); - - if (lineout2_diff) - snd_soc_dapm_add_routes(codec, - lineout2_diff_routes, - ARRAY_SIZE(lineout2_diff_routes)); - else - snd_soc_dapm_add_routes(codec, - lineout2_se_routes, - ARRAY_SIZE(lineout2_se_routes)); - - return 0; -} -EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); - -MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/codecs/wm_hubs.h b/trunk/sound/soc/codecs/wm_hubs.h deleted file mode 100644 index ec09cb6a2939..000000000000 --- a/trunk/sound/soc/codecs/wm_hubs.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * wm_hubs.h -- WM899x common code - * - * Copyright 2009 Wolfson Microelectronics plc - * - * Author: Mark Brown - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _WM_HUBS_H -#define _WM_HUBS_H - -struct snd_soc_codec; - -extern const unsigned int wm_hubs_spkmix_tlv[]; - -extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); -extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int); - -#endif diff --git a/trunk/sound/soc/davinci/Kconfig b/trunk/sound/soc/davinci/Kconfig index 4dfd4ad9d90e..411a710be660 100644 --- a/trunk/sound/soc/davinci/Kconfig +++ b/trunk/sound/soc/davinci/Kconfig @@ -9,9 +9,6 @@ config SND_DAVINCI_SOC config SND_DAVINCI_SOC_I2S tristate -config SND_DAVINCI_SOC_MCASP - tristate - config SND_DAVINCI_SOC_EVM tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM" depends on SND_DAVINCI_SOC @@ -22,16 +19,6 @@ config SND_DAVINCI_SOC_EVM Say Y if you want to add support for SoC audio on TI DaVinci DM6446 or DM355 EVM platforms. -config SND_DM6467_SOC_EVM - tristate "SoC Audio support for DaVinci DM6467 EVM" - depends on SND_DAVINCI_SOC && MACH_DAVINCI_DM6467_EVM - select SND_DAVINCI_SOC_MCASP - select SND_SOC_TLV320AIC3X - select SND_SOC_SPDIF - - help - Say Y if you want to add support for SoC audio on TI - config SND_DAVINCI_SOC_SFFSDR tristate "SoC Audio support for SFFSDR" depends on SND_DAVINCI_SOC && MACH_SFFSDR @@ -41,23 +28,3 @@ config SND_DAVINCI_SOC_SFFSDR help Say Y if you want to add support for SoC audio on Lyrtech SFFSDR board. - -config SND_DA830_SOC_EVM - tristate "SoC Audio support for DA830/OMAP-L137 EVM" - depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA830_EVM - select SND_DAVINCI_SOC_MCASP - select SND_SOC_TLV320AIC3X - - help - Say Y if you want to add support for SoC audio on TI - DA830/OMAP-L137 EVM - -config SND_DA850_SOC_EVM - tristate "SoC Audio support for DA850/OMAP-L138 EVM" - depends on SND_DAVINCI_SOC && MACH_DAVINCI_DA850_EVM - select SND_DAVINCI_SOC_MCASP - select SND_SOC_TLV320AIC3X - help - Say Y if you want to add support for SoC audio on TI - DA850/OMAP-L138 EVM - diff --git a/trunk/sound/soc/davinci/Makefile b/trunk/sound/soc/davinci/Makefile index a6939d71b988..ca8bae1fc3f6 100644 --- a/trunk/sound/soc/davinci/Makefile +++ b/trunk/sound/soc/davinci/Makefile @@ -1,18 +1,13 @@ # DAVINCI Platform Support snd-soc-davinci-objs := davinci-pcm.o snd-soc-davinci-i2s-objs := davinci-i2s.o -snd-soc-davinci-mcasp-objs:= davinci-mcasp.o obj-$(CONFIG_SND_DAVINCI_SOC) += snd-soc-davinci.o obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o -obj-$(CONFIG_SND_DAVINCI_SOC_MCASP) += snd-soc-davinci-mcasp.o # DAVINCI Machine Support snd-soc-evm-objs := davinci-evm.o snd-soc-sffsdr-objs := davinci-sffsdr.o obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o -obj-$(CONFIG_SND_DM6467_SOC_EVM) += snd-soc-evm.o -obj-$(CONFIG_SND_DA830_SOC_EVM) += snd-soc-evm.o -obj-$(CONFIG_SND_DA850_SOC_EVM) += snd-soc-evm.o obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o diff --git a/trunk/sound/soc/davinci/davinci-evm.c b/trunk/sound/soc/davinci/davinci-evm.c index 67414f659405..58fd1cbedd88 100644 --- a/trunk/sound/soc/davinci/davinci-evm.c +++ b/trunk/sound/soc/davinci/davinci-evm.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -28,10 +27,9 @@ #include #include "../codecs/tlv320aic3x.h" -#include "../codecs/spdif_transciever.h" #include "davinci-pcm.h" #include "davinci-i2s.h" -#include "davinci-mcasp.h" + #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) @@ -45,7 +43,7 @@ static int evm_hw_params(struct snd_pcm_substream *substream, unsigned sysclk; /* ASP1 on DM355 EVM is clocked by an external oscillator */ - if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm()) + if (machine_is_davinci_dm355_evm()) sysclk = 27000000; /* ASP0 in DM6446 EVM is clocked by U55, as configured by @@ -55,10 +53,6 @@ static int evm_hw_params(struct snd_pcm_substream *substream, else if (machine_is_davinci_evm()) sysclk = 12288000; - else if (machine_is_davinci_da830_evm() || - machine_is_davinci_da850_evm()) - sysclk = 24576000; - else return -EINVAL; @@ -150,32 +144,6 @@ static struct snd_soc_dai_link evm_dai = { .ops = &evm_ops, }; -static struct snd_soc_dai_link dm6467_evm_dai[] = { - { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], - .codec_dai = &aic3x_dai, - .init = evm_aic3x_init, - .ops = &evm_ops, - }, - { - .name = "McASP", - .stream_name = "spdif", - .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_DIT_DAI], - .codec_dai = &dit_stub_dai, - .ops = &evm_ops, - }, -}; -static struct snd_soc_dai_link da8xx_evm_dai = { - .name = "TLV320AIC3X", - .stream_name = "AIC3X", - .cpu_dai = &davinci_mcasp_dai[DAVINCI_MCASP_I2S_DAI], - .codec_dai = &aic3x_dai, - .init = evm_aic3x_init, - .ops = &evm_ops, -}; - /* davinci-evm audio machine driver */ static struct snd_soc_card snd_soc_card_evm = { .name = "DaVinci EVM", @@ -184,80 +152,73 @@ static struct snd_soc_card snd_soc_card_evm = { .num_links = 1, }; -/* davinci dm6467 evm audio machine driver */ -static struct snd_soc_card dm6467_snd_soc_card_evm = { - .name = "DaVinci DM6467 EVM", - .platform = &davinci_soc_platform, - .dai_link = dm6467_evm_dai, - .num_links = ARRAY_SIZE(dm6467_evm_dai), +/* evm audio private data */ +static struct aic3x_setup_data evm_aic3x_setup = { + .i2c_bus = 1, + .i2c_address = 0x1b, }; -static struct snd_soc_card da830_snd_soc_card = { - .name = "DA830/OMAP-L137 EVM", - .dai_link = &da8xx_evm_dai, - .platform = &davinci_soc_platform, - .num_links = 1, -}; - -static struct snd_soc_card da850_snd_soc_card = { - .name = "DA850/OMAP-L138 EVM", - .dai_link = &da8xx_evm_dai, - .platform = &davinci_soc_platform, - .num_links = 1, -}; - -static struct aic3x_setup_data aic3x_setup; - /* evm audio subsystem */ static struct snd_soc_device evm_snd_devdata = { .card = &snd_soc_card_evm, .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, + .codec_data = &evm_aic3x_setup, }; -/* evm audio subsystem */ -static struct snd_soc_device dm6467_evm_snd_devdata = { - .card = &dm6467_snd_soc_card_evm, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, +/* DM6446 EVM uses ASP0; line-out is a pair of RCA jacks */ +static struct resource evm_snd_resources[] = { + { + .start = DAVINCI_ASP0_BASE, + .end = DAVINCI_ASP0_BASE + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, }; -/* evm audio subsystem */ -static struct snd_soc_device da830_evm_snd_devdata = { - .card = &da830_snd_soc_card, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, +static struct evm_snd_platform_data evm_snd_data = { + .tx_dma_ch = DAVINCI_DMA_ASP0_TX, + .rx_dma_ch = DAVINCI_DMA_ASP0_RX, }; -static struct snd_soc_device da850_evm_snd_devdata = { - .card = &da850_snd_soc_card, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &aic3x_setup, +/* DM335 EVM uses ASP1; line-out is a stereo mini-jack */ +static struct resource dm335evm_snd_resources[] = { + { + .start = DAVINCI_ASP1_BASE, + .end = DAVINCI_ASP1_BASE + SZ_8K - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct evm_snd_platform_data dm335evm_snd_data = { + .tx_dma_ch = DAVINCI_DMA_ASP1_TX, + .rx_dma_ch = DAVINCI_DMA_ASP1_RX, }; static struct platform_device *evm_snd_device; static int __init evm_init(void) { - struct snd_soc_device *evm_snd_dev_data; + struct resource *resources; + unsigned num_resources; + struct evm_snd_platform_data *data; int index; int ret; if (machine_is_davinci_evm()) { - evm_snd_dev_data = &evm_snd_devdata; + davinci_cfg_reg(DM644X_MCBSP); + + resources = evm_snd_resources; + num_resources = ARRAY_SIZE(evm_snd_resources); + data = &evm_snd_data; index = 0; } else if (machine_is_davinci_dm355_evm()) { - evm_snd_dev_data = &evm_snd_devdata; - index = 1; - } else if (machine_is_davinci_dm6467_evm()) { - evm_snd_dev_data = &dm6467_evm_snd_devdata; - index = 0; - } else if (machine_is_davinci_da830_evm()) { - evm_snd_dev_data = &da830_evm_snd_devdata; + /* we don't use ASP1 IRQs, or we'd need to mux them ... */ + davinci_cfg_reg(DM355_EVT8_ASP1_TX); + davinci_cfg_reg(DM355_EVT9_ASP1_RX); + + resources = dm335evm_snd_resources; + num_resources = ARRAY_SIZE(dm335evm_snd_resources); + data = &dm335evm_snd_data; index = 1; - } else if (machine_is_davinci_da850_evm()) { - evm_snd_dev_data = &da850_evm_snd_devdata; - index = 0; } else return -EINVAL; @@ -265,8 +226,17 @@ static int __init evm_init(void) if (!evm_snd_device) return -ENOMEM; - platform_set_drvdata(evm_snd_device, evm_snd_dev_data); - evm_snd_dev_data->dev = &evm_snd_device->dev; + platform_set_drvdata(evm_snd_device, &evm_snd_devdata); + evm_snd_devdata.dev = &evm_snd_device->dev; + platform_device_add_data(evm_snd_device, data, sizeof(*data)); + + ret = platform_device_add_resources(evm_snd_device, resources, + num_resources); + if (ret) { + platform_device_put(evm_snd_device); + return ret; + } + ret = platform_device_add(evm_snd_device); if (ret) platform_device_put(evm_snd_device); diff --git a/trunk/sound/soc/davinci/davinci-i2s.c b/trunk/sound/soc/davinci/davinci-i2s.c index 12a6c549ee6e..b1ea52fc83c7 100644 --- a/trunk/sound/soc/davinci/davinci-i2s.c +++ b/trunk/sound/soc/davinci/davinci-i2s.c @@ -22,8 +22,6 @@ #include #include -#include - #include "davinci-pcm.h" @@ -65,7 +63,6 @@ #define DAVINCI_MCBSP_RCR_RWDLEN1(v) ((v) << 5) #define DAVINCI_MCBSP_RCR_RFRLEN1(v) ((v) << 8) #define DAVINCI_MCBSP_RCR_RDATDLY(v) ((v) << 16) -#define DAVINCI_MCBSP_RCR_RFIG (1 << 18) #define DAVINCI_MCBSP_RCR_RWDLEN2(v) ((v) << 21) #define DAVINCI_MCBSP_XCR_XWDLEN1(v) ((v) << 5) @@ -88,6 +85,14 @@ #define DAVINCI_MCBSP_PCR_FSRM (1 << 10) #define DAVINCI_MCBSP_PCR_FSXM (1 << 11) +#define MOD_REG_BIT(val, mask, set) do { \ + if (set) { \ + val |= mask; \ + } else { \ + val &= ~mask; \ + } \ +} while (0) + enum { DAVINCI_MCBSP_WORD_8 = 0, DAVINCI_MCBSP_WORD_12, @@ -107,10 +112,6 @@ static struct davinci_pcm_dma_params davinci_i2s_pcm_in = { struct davinci_mcbsp_dev { void __iomem *base; -#define MOD_DSP_A 0 -#define MOD_DSP_B 1 - int mode; - u32 pcr; struct clk *clk; struct davinci_pcm_dma_params *dma_params[2]; }; @@ -126,100 +127,96 @@ static inline u32 davinci_mcbsp_read_reg(struct davinci_mcbsp_dev *dev, int reg) return __raw_readl(dev->base + reg); } -static void toggle_clock(struct davinci_mcbsp_dev *dev, int playback) -{ - u32 m = playback ? DAVINCI_MCBSP_PCR_CLKXP : DAVINCI_MCBSP_PCR_CLKRP; - /* The clock needs to toggle to complete reset. - * So, fake it by toggling the clk polarity. - */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr ^ m); - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, dev->pcr); -} - -static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev, - struct snd_pcm_substream *substream) +static void davinci_mcbsp_start(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; struct snd_soc_device *socdev = rtd->socdev; struct snd_soc_platform *platform = socdev->card->platform; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - u32 spcr; - u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - if (spcr & mask) { - /* start off disabled */ - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, - spcr & ~mask); - toggle_clock(dev, playback); - } - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM | - DAVINCI_MCBSP_PCR_CLKXM | DAVINCI_MCBSP_PCR_CLKRM)) { - /* Start the sample generator */ - spcr |= DAVINCI_MCBSP_SPCR_GRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - } + u32 w; + int ret; - if (playback) { + /* Start the sample generator and enable transmitter/receiver */ + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* Stop the DMA to avoid data loss */ /* while the transmitter is out of reset to handle XSYNCERR */ if (platform->pcm_ops->trigger) { - int ret = platform->pcm_ops->trigger(substream, + ret = platform->pcm_ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP); if (ret < 0) printk(KERN_DEBUG "Playback DMA stop failed\n"); } /* Enable the transmitter */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); /* wait for any unexpected frame sync error to occur */ udelay(100); /* Disable the transmitter to clear any outstanding XSYNCERR */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~DAVINCI_MCBSP_SPCR_XRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); /* Restart the DMA */ if (platform->pcm_ops->trigger) { - int ret = platform->pcm_ops->trigger(substream, + ret = platform->pcm_ops->trigger(substream, SNDRV_PCM_TRIGGER_START); if (ret < 0) printk(KERN_DEBUG "Playback DMA start failed\n"); } - } + /* Enable the transmitter */ + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); - /* Enable transmitter or receiver */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr |= mask; + } else { - if (dev->pcr & (DAVINCI_MCBSP_PCR_FSXM | DAVINCI_MCBSP_PCR_FSRM)) { - /* Start frame sync */ - spcr |= DAVINCI_MCBSP_SPCR_FRST; + /* Enable the reciever */ + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + + + /* Start frame sync */ + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_FRST, 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } -static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) +static void davinci_mcbsp_stop(struct snd_pcm_substream *substream) { - u32 spcr; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; + u32 w; /* Reset transmitter/receiver and sample rate/frame sync generators */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); - spcr &= ~(DAVINCI_MCBSP_SPCR_GRST | DAVINCI_MCBSP_SPCR_FRST); - spcr &= playback ? ~DAVINCI_MCBSP_SPCR_XRST : ~DAVINCI_MCBSP_SPCR_RRST; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); - toggle_clock(dev, playback); + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST | + DAVINCI_MCBSP_SPCR_FRST, 0); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); + else + MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 0); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } static int davinci_i2s_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *cpu_dai) + struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = cpu_dai->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; + cpu_dai->dma_data = dev->dma_params[substream->stream]; + return 0; } @@ -231,11 +228,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, struct davinci_mcbsp_dev *dev = cpu_dai->private_data; unsigned int pcr; unsigned int srgr; + unsigned int rcr; + unsigned int xcr; srgr = DAVINCI_MCBSP_SRGR_FSGM | DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); - /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* cpu is master */ @@ -260,8 +258,11 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } - /* interface format */ + rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1); + xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_B: + break; case SND_SOC_DAIFMT_I2S: /* Davinci doesn't support TRUE I2S, but some codecs will have * the left and right channels contiguous. This allows @@ -281,10 +282,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, */ fmt ^= SND_SOC_DAIFMT_NB_IF; case SND_SOC_DAIFMT_DSP_A: - dev->mode = MOD_DSP_A; - break; - case SND_SOC_DAIFMT_DSP_B: - dev->mode = MOD_DSP_B; + rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); + xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); break; default: printk(KERN_ERR "%s:bad format\n", __func__); @@ -344,8 +343,9 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); - dev->pcr = pcr; davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); return 0; } @@ -353,40 +353,31 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct davinci_pcm_dma_params *dma_params = dai->dma_data; - struct davinci_mcbsp_dev *dev = dai->private_data; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; + struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; struct snd_interval *i = NULL; int mcbsp_word_length; - unsigned int rcr, xcr, srgr; - u32 spcr; + u32 w; /* general line settings */ - spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } else { - spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); } i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); - srgr = DAVINCI_MCBSP_SRGR_FSGM; - srgr |= DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1); + w = DAVINCI_MCBSP_SRGR_FSGM; + MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1); i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); - srgr |= DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1); - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); + MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w); - rcr = DAVINCI_MCBSP_RCR_RFIG; - xcr = DAVINCI_MCBSP_XCR_XFIG; - if (dev->mode == MOD_DSP_B) { - rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0); - xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0); - } else { - rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); - xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); - } /* Determine xfer data type */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: @@ -406,31 +397,18 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - dma_params->acnt = dma_params->data_type; - rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1); - - rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | - DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); - xcr |= DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | - DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length); + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | + DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); - else - davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); - return 0; -} + } else { + w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG); + MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | + DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1); + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w); -static int davinci_i2s_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = dai->private_data; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - davinci_mcbsp_stop(dev, playback); - if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) { - /* codec is master */ - davinci_mcbsp_start(dev, substream); } return 0; } @@ -438,72 +416,35 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream, static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = dai->private_data; int ret = 0; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) - return 0; /* return if codec is master */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_mcbsp_start(dev, substream); + davinci_mcbsp_start(substream); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcbsp_stop(dev, playback); + davinci_mcbsp_stop(substream); break; default: ret = -EINVAL; } - return ret; -} -static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct davinci_mcbsp_dev *dev = dai->private_data; - int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - davinci_mcbsp_stop(dev, playback); + return ret; } -#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 - -static struct snd_soc_dai_ops davinci_i2s_dai_ops = { - .startup = davinci_i2s_startup, - .shutdown = davinci_i2s_shutdown, - .prepare = davinci_i2s_prepare, - .trigger = davinci_i2s_trigger, - .hw_params = davinci_i2s_hw_params, - .set_fmt = davinci_i2s_set_dai_fmt, - -}; - -struct snd_soc_dai davinci_i2s_dai = { - .name = "davinci-i2s", - .id = 0, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_I2S_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .ops = &davinci_i2s_dai_ops, - -}; -EXPORT_SYMBOL_GPL(davinci_i2s_dai); - -static int davinci_i2s_probe(struct platform_device *pdev) +static int davinci_i2s_probe(struct platform_device *pdev, + struct snd_soc_dai *dai) { - struct snd_platform_data *pdata = pdev->dev.platform_data; + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_card *card = socdev->card; + struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai; struct davinci_mcbsp_dev *dev; - struct resource *mem, *ioarea, *res; + struct resource *mem, *ioarea; + struct evm_snd_platform_data *pdata; int ret; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -525,6 +466,8 @@ static int davinci_i2s_probe(struct platform_device *pdev) goto err_release_region; } + cpu_dai->private_data = dev; + dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { ret = -ENODEV; @@ -533,37 +476,18 @@ static int davinci_i2s_probe(struct platform_device *pdev) clk_enable(dev->clk); dev->base = (void __iomem *)IO_ADDRESS(mem->start); + pdata = pdev->dev.platform_data; dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &davinci_i2s_pcm_out; + dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = pdata->tx_dma_ch; dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->dma_addr = (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DXR_REG); dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &davinci_i2s_pcm_in; + dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = pdata->rx_dma_ch; dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->dma_addr = (dma_addr_t)(io_v2p(dev->base) + DAVINCI_MCBSP_DRR_REG); - /* first TX, then RX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENXIO; - goto err_free_mem; - } - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]->channel = res->start; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - ret = -ENXIO; - goto err_free_mem; - } - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE]->channel = res->start; - - davinci_i2s_dai.private_data = dev; - ret = snd_soc_register_dai(&davinci_i2s_dai); - if (ret != 0) - goto err_free_mem; - return 0; err_free_mem: @@ -574,40 +498,62 @@ static int davinci_i2s_probe(struct platform_device *pdev) return ret; } -static int davinci_i2s_remove(struct platform_device *pdev) +static void davinci_i2s_remove(struct platform_device *pdev, + struct snd_soc_dai *dai) { - struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data; + struct snd_soc_device *socdev = platform_get_drvdata(pdev); + struct snd_soc_card *card = socdev->card; + struct snd_soc_dai *cpu_dai = card->dai_link->cpu_dai; + struct davinci_mcbsp_dev *dev = cpu_dai->private_data; struct resource *mem; - snd_soc_unregister_dai(&davinci_i2s_dai); clk_disable(dev->clk); clk_put(dev->clk); dev->clk = NULL; + kfree(dev); + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(mem->start, (mem->end - mem->start) + 1); - - return 0; } -static struct platform_driver davinci_mcbsp_driver = { - .probe = davinci_i2s_probe, - .remove = davinci_i2s_remove, - .driver = { - .name = "davinci-asp", - .owner = THIS_MODULE, - }, +#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 + +static struct snd_soc_dai_ops davinci_i2s_dai_ops = { + .startup = davinci_i2s_startup, + .trigger = davinci_i2s_trigger, + .hw_params = davinci_i2s_hw_params, + .set_fmt = davinci_i2s_set_dai_fmt, +}; + +struct snd_soc_dai davinci_i2s_dai = { + .name = "davinci-i2s", + .id = 0, + .probe = davinci_i2s_probe, + .remove = davinci_i2s_remove, + .playback = { + .channels_min = 2, + .channels_max = 2, + .rates = DAVINCI_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .capture = { + .channels_min = 2, + .channels_max = 2, + .rates = DAVINCI_I2S_RATES, + .formats = SNDRV_PCM_FMTBIT_S16_LE,}, + .ops = &davinci_i2s_dai_ops, }; +EXPORT_SYMBOL_GPL(davinci_i2s_dai); static int __init davinci_i2s_init(void) { - return platform_driver_register(&davinci_mcbsp_driver); + return snd_soc_register_dai(&davinci_i2s_dai); } module_init(davinci_i2s_init); static void __exit davinci_i2s_exit(void) { - platform_driver_unregister(&davinci_mcbsp_driver); + snd_soc_unregister_dai(&davinci_i2s_dai); } module_exit(davinci_i2s_exit); diff --git a/trunk/sound/soc/davinci/davinci-mcasp.c b/trunk/sound/soc/davinci/davinci-mcasp.c deleted file mode 100644 index eca22d7829d2..000000000000 --- a/trunk/sound/soc/davinci/davinci-mcasp.c +++ /dev/null @@ -1,973 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * Multi-channel Audio Serial Port Driver - * - * Author: Nirmal Pandey , - * Suresh Rajashekara - * Steve Chen - * - * Copyright: (C) 2009 MontaVista Software, Inc., - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "davinci-pcm.h" -#include "davinci-mcasp.h" - -/* - * McASP register definitions - */ -#define DAVINCI_MCASP_PID_REG 0x00 -#define DAVINCI_MCASP_PWREMUMGT_REG 0x04 - -#define DAVINCI_MCASP_PFUNC_REG 0x10 -#define DAVINCI_MCASP_PDIR_REG 0x14 -#define DAVINCI_MCASP_PDOUT_REG 0x18 -#define DAVINCI_MCASP_PDSET_REG 0x1c - -#define DAVINCI_MCASP_PDCLR_REG 0x20 - -#define DAVINCI_MCASP_TLGC_REG 0x30 -#define DAVINCI_MCASP_TLMR_REG 0x34 - -#define DAVINCI_MCASP_GBLCTL_REG 0x44 -#define DAVINCI_MCASP_AMUTE_REG 0x48 -#define DAVINCI_MCASP_LBCTL_REG 0x4c - -#define DAVINCI_MCASP_TXDITCTL_REG 0x50 - -#define DAVINCI_MCASP_GBLCTLR_REG 0x60 -#define DAVINCI_MCASP_RXMASK_REG 0x64 -#define DAVINCI_MCASP_RXFMT_REG 0x68 -#define DAVINCI_MCASP_RXFMCTL_REG 0x6c - -#define DAVINCI_MCASP_ACLKRCTL_REG 0x70 -#define DAVINCI_MCASP_AHCLKRCTL_REG 0x74 -#define DAVINCI_MCASP_RXTDM_REG 0x78 -#define DAVINCI_MCASP_EVTCTLR_REG 0x7c - -#define DAVINCI_MCASP_RXSTAT_REG 0x80 -#define DAVINCI_MCASP_RXTDMSLOT_REG 0x84 -#define DAVINCI_MCASP_RXCLKCHK_REG 0x88 -#define DAVINCI_MCASP_REVTCTL_REG 0x8c - -#define DAVINCI_MCASP_GBLCTLX_REG 0xa0 -#define DAVINCI_MCASP_TXMASK_REG 0xa4 -#define DAVINCI_MCASP_TXFMT_REG 0xa8 -#define DAVINCI_MCASP_TXFMCTL_REG 0xac - -#define DAVINCI_MCASP_ACLKXCTL_REG 0xb0 -#define DAVINCI_MCASP_AHCLKXCTL_REG 0xb4 -#define DAVINCI_MCASP_TXTDM_REG 0xb8 -#define DAVINCI_MCASP_EVTCTLX_REG 0xbc - -#define DAVINCI_MCASP_TXSTAT_REG 0xc0 -#define DAVINCI_MCASP_TXTDMSLOT_REG 0xc4 -#define DAVINCI_MCASP_TXCLKCHK_REG 0xc8 -#define DAVINCI_MCASP_XEVTCTL_REG 0xcc - -/* Left(even TDM Slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRA_REG 0x100 -/* Right(odd TDM slot) Channel Status Register File */ -#define DAVINCI_MCASP_DITCSRB_REG 0x118 -/* Left(even TDM slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRA_REG 0x130 -/* Right(odd TDM Slot) User Data Register File */ -#define DAVINCI_MCASP_DITUDRB_REG 0x148 - -/* Serializer n Control Register */ -#define DAVINCI_MCASP_XRSRCTL_BASE_REG 0x180 -#define DAVINCI_MCASP_XRSRCTL_REG(n) (DAVINCI_MCASP_XRSRCTL_BASE_REG + \ - (n << 2)) - -/* Transmit Buffer for Serializer n */ -#define DAVINCI_MCASP_TXBUF_REG 0x200 -/* Receive Buffer for Serializer n */ -#define DAVINCI_MCASP_RXBUF_REG 0x280 - -/* McASP FIFO Registers */ -#define DAVINCI_MCASP_WFIFOCTL (0x1010) -#define DAVINCI_MCASP_WFIFOSTS (0x1014) -#define DAVINCI_MCASP_RFIFOCTL (0x1018) -#define DAVINCI_MCASP_RFIFOSTS (0x101C) - -/* - * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management - * Register Bits - */ -#define MCASP_FREE BIT(0) -#define MCASP_SOFT BIT(1) - -/* - * DAVINCI_MCASP_PFUNC_REG - Pin Function / GPIO Enable Register Bits - */ -#define AXR(n) (1<private_data; - cpu_dai->dma_data = dev->dma_params[substream->stream]; - return 0; -} - -static void mcasp_start_rx(struct davinci_audio_dev *dev) -{ - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXHCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSERCLR); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, RXFSRST); -} - -static void mcasp_start_tx(struct davinci_audio_dev *dev) -{ - u8 offset = 0, i; - u32 cnt; - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXHCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXCLKRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSERCLR); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); - - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXSMRST); - mcasp_set_ctl_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, TXFSRST); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); - for (i = 0; i < dev->num_serializer; i++) { - if (dev->serial_dir[i] == TX_MODE) { - offset = i; - break; - } - } - - /* wait for TX ready */ - cnt = 0; - while (!(mcasp_get_reg(dev->base + DAVINCI_MCASP_XRSRCTL_REG(offset)) & - TXSTATE) && (cnt < 100000)) - cnt++; - - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXBUF_REG, 0); -} - -static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - mcasp_start_tx(dev); - else - mcasp_start_rx(dev); - - /* enable FIFO */ - if (dev->txnumevt) - mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); - - if (dev->rxnumevt) - mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); -} - -static void mcasp_stop_rx(struct davinci_audio_dev *dev) -{ - mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLR_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); -} - -static void mcasp_stop_tx(struct davinci_audio_dev *dev) -{ - mcasp_set_reg(dev->base + DAVINCI_MCASP_GBLCTLX_REG, 0); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); -} - -static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) -{ - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - mcasp_stop_tx(dev); - else - mcasp_stop_rx(dev); - - /* disable FIFO */ - if (dev->txnumevt) - mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); - - if (dev->rxnumevt) - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); -} - -static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - struct davinci_audio_dev *dev = cpu_dai->private_data; - void __iomem *base = dev->base; - - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - /* codec is clock and frame slave */ - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x7 << 26)); - break; - case SND_SOC_DAIFMT_CBM_CFS: - /* codec is clock master and frame slave */ - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, (0x2d << 26)); - break; - case SND_SOC_DAIFMT_CBM_CFM: - /* codec is clock and frame master */ - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXE); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, AFSXE); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE); - - mcasp_clr_bits(base + DAVINCI_MCASP_PDIR_REG, (0x3f << 26)); - break; - - default: - return -EINVAL; - } - - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_NF: - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_NB_IF: - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_IB_IF: - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_set_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - case SND_SOC_DAIFMT_NB_NF: - mcasp_set_bits(base + DAVINCI_MCASP_ACLKXCTL_REG, ACLKXPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_TXFMCTL_REG, FSXPOL); - - mcasp_clr_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRPOL); - mcasp_clr_bits(base + DAVINCI_MCASP_RXFMCTL_REG, FSRPOL); - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int davinci_config_channel_size(struct davinci_audio_dev *dev, - int channel_size) -{ - u32 fmt = 0; - - switch (channel_size) { - case DAVINCI_AUDIO_WORD_8: - fmt = 0x03; - break; - - case DAVINCI_AUDIO_WORD_12: - fmt = 0x05; - break; - - case DAVINCI_AUDIO_WORD_16: - fmt = 0x07; - break; - - case DAVINCI_AUDIO_WORD_20: - fmt = 0x09; - break; - - case DAVINCI_AUDIO_WORD_24: - fmt = 0x0B; - break; - - case DAVINCI_AUDIO_WORD_28: - fmt = 0x0D; - break; - - case DAVINCI_AUDIO_WORD_32: - fmt = 0x0F; - break; - - default: - return -EINVAL; - } - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, - RXSSZ(fmt), RXSSZ(0x0F)); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, - TXSSZ(fmt), TXSSZ(0x0F)); - return 0; -} - -static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) -{ - int i; - u8 tx_ser = 0; - u8 rx_ser = 0; - - /* Default configuration */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PWREMUMGT_REG, MCASP_SOFT); - - /* All PINS as McASP */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_PFUNC_REG, 0x00000000); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, - TXDATADMADIS); - } else { - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXSTAT_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_REVTCTL_REG, - RXDATADMADIS); - } - - for (i = 0; i < dev->num_serializer; i++) { - mcasp_set_bits(dev->base + DAVINCI_MCASP_XRSRCTL_REG(i), - dev->serial_dir[i]); - if (dev->serial_dir[i] == TX_MODE) { - mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, - AXR(i)); - tx_ser++; - } else if (dev->serial_dir[i] == RX_MODE) { - mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, - AXR(i)); - rx_ser++; - } - } - - if (dev->txnumevt && stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (dev->txnumevt * tx_ser > 64) - dev->txnumevt = 1; - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, - NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, - ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); - mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); - } - - if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { - if (dev->rxnumevt * rx_ser > 64) - dev->rxnumevt = 1; - - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, - NUMDMA_MASK); - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, - ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); - mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); - } -} - -static void davinci_hw_param(struct davinci_audio_dev *dev, int stream) -{ - int i, active_slots; - u32 mask = 0; - - active_slots = (dev->tdm_slots > 31) ? 32 : dev->tdm_slots; - for (i = 0; i < active_slots; i++) - mask |= (1 << i); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, TX_ASYNC); - - if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, - AHCLKXE); - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask); - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD); - - if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32)) - mcasp_mod_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, - FSXMOD(dev->tdm_slots), FSXMOD(0x1FF)); - else - printk(KERN_ERR "playback tdm slot %d not supported\n", - dev->tdm_slots); - - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR); - } else { - /* bit stream is MSB first with no delay */ - /* DSP_B mode */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD); - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, - AHCLKRE); - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask); - - if ((dev->tdm_slots >= 2) || (dev->tdm_slots <= 32)) - mcasp_mod_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, - FSRMOD(dev->tdm_slots), FSRMOD(0x1FF)); - else - printk(KERN_ERR "capture tdm slot %d not supported\n", - dev->tdm_slots); - - mcasp_set_reg(dev->base + DAVINCI_MCASP_RXMASK_REG, 0xFFFFFFFF); - mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR); - } -} - -/* S/PDIF */ -static void davinci_hw_dit_param(struct davinci_audio_dev *dev) -{ - /* Set the PDIR for Serialiser as output */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AFSX); - - /* TXMASK for 24 bits */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXMASK_REG, 0x00FFFFFF); - - /* Set the TX format : 24 bit right rotation, 32 bit slot, Pad 0 - and LSB first */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, - TXROT(6) | TXSSZ(15)); - - /* Set TX frame synch : DIT Mode, 1 bit width, internal, rising edge */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXFMCTL_REG, - AFSXE | FSXMOD(0x180)); - - /* Set the TX tdm : for all the slots */ - mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, 0xFFFFFFFF); - - /* Set the TX clock controls : div = 1 and internal */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG, - ACLKXE | TX_ASYNC); - - mcasp_clr_bits(dev->base + DAVINCI_MCASP_XEVTCTL_REG, TXDATADMADIS); - - /* Only 44100 and 48000 are valid, both have the same setting */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXDIV(3)); - - /* Enable the DIT */ - mcasp_set_bits(dev->base + DAVINCI_MCASP_TXDITCTL_REG, DITEN); -} - -static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) -{ - struct davinci_audio_dev *dev = cpu_dai->private_data; - struct davinci_pcm_dma_params *dma_params = - dev->dma_params[substream->stream]; - int word_length; - u8 numevt; - - davinci_hw_common_param(dev, substream->stream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - numevt = dev->txnumevt; - else - numevt = dev->rxnumevt; - - if (!numevt) - numevt = 1; - - if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) - davinci_hw_dit_param(dev); - else - davinci_hw_param(dev, substream->stream); - - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S8: - dma_params->data_type = 1; - word_length = DAVINCI_AUDIO_WORD_8; - break; - - case SNDRV_PCM_FORMAT_S16_LE: - dma_params->data_type = 2; - word_length = DAVINCI_AUDIO_WORD_16; - break; - - case SNDRV_PCM_FORMAT_S32_LE: - dma_params->data_type = 4; - word_length = DAVINCI_AUDIO_WORD_32; - break; - - default: - printk(KERN_WARNING "davinci-mcasp: unsupported PCM format"); - return -EINVAL; - } - - if (dev->version == MCASP_VERSION_2) { - dma_params->data_type *= numevt; - dma_params->acnt = 4 * numevt; - } else - dma_params->acnt = dma_params->data_type; - - davinci_config_channel_size(dev, word_length); - - return 0; -} - -static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, - int cmd, struct snd_soc_dai *cpu_dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct davinci_audio_dev *dev = rtd->dai->cpu_dai->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - davinci_mcasp_start(dev, substream->stream); - break; - - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - davinci_mcasp_stop(dev, substream->stream); - break; - - default: - ret = -EINVAL; - } - - return ret; -} - -static struct snd_soc_dai_ops davinci_mcasp_dai_ops = { - .startup = davinci_mcasp_startup, - .trigger = davinci_mcasp_trigger, - .hw_params = davinci_mcasp_hw_params, - .set_fmt = davinci_mcasp_set_dai_fmt, - -}; - -struct snd_soc_dai davinci_mcasp_dai[] = { - { - .name = "davinci-i2s", - .id = 0, - .playback = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_MCASP_RATES, - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, - .capture = { - .channels_min = 2, - .channels_max = 2, - .rates = DAVINCI_MCASP_RATES, - .formats = SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S32_LE, - }, - .ops = &davinci_mcasp_dai_ops, - - }, - { - .name = "davinci-dit", - .id = 1, - .playback = { - .channels_min = 1, - .channels_max = 384, - .rates = DAVINCI_MCASP_RATES, - .formats = SNDRV_PCM_FMTBIT_S16_LE, - }, - .ops = &davinci_mcasp_dai_ops, - }, - -}; -EXPORT_SYMBOL_GPL(davinci_mcasp_dai); - -static int davinci_mcasp_probe(struct platform_device *pdev) -{ - struct davinci_pcm_dma_params *dma_data; - struct resource *mem, *ioarea, *res; - struct snd_platform_data *pdata; - struct davinci_audio_dev *dev; - int count = 0; - int ret = 0; - - dev = kzalloc(sizeof(struct davinci_audio_dev), GFP_KERNEL); - if (!dev) - return -ENOMEM; - - dma_data = kzalloc(sizeof(struct davinci_pcm_dma_params) * 2, - GFP_KERNEL); - if (!dma_data) { - ret = -ENOMEM; - goto err_release_dev; - } - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - ret = -ENODEV; - goto err_release_data; - } - - ioarea = request_mem_region(mem->start, - (mem->end - mem->start) + 1, pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "Audio region already claimed\n"); - ret = -EBUSY; - goto err_release_data; - } - - pdata = pdev->dev.platform_data; - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) { - ret = -ENODEV; - goto err_release_region; - } - - clk_enable(dev->clk); - - dev->base = (void __iomem *)IO_ADDRESS(mem->start); - dev->op_mode = pdata->op_mode; - dev->tdm_slots = pdata->tdm_slots; - dev->num_serializer = pdata->num_serializer; - dev->serial_dir = pdata->serial_dir; - dev->codec_fmt = pdata->codec_fmt; - dev->version = pdata->version; - dev->txnumevt = pdata->txnumevt; - dev->rxnumevt = pdata->rxnumevt; - - dma_data[count].name = "I2S PCM Stereo out"; - dma_data[count].eventq_no = pdata->eventq_no; - dma_data[count].dma_addr = (dma_addr_t) (pdata->tx_dma_offset + - io_v2p(dev->base)); - dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK] = &dma_data[count]; - - /* first TX, then RX */ - res = platform_get_resource(pdev, IORESOURCE_DMA, 0); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - goto err_release_region; - } - - dma_data[count].channel = res->start; - count++; - dma_data[count].name = "I2S PCM Stereo in"; - dma_data[count].eventq_no = pdata->eventq_no; - dma_data[count].dma_addr = (dma_addr_t)(pdata->rx_dma_offset + - io_v2p(dev->base)); - dev->dma_params[SNDRV_PCM_STREAM_CAPTURE] = &dma_data[count]; - - res = platform_get_resource(pdev, IORESOURCE_DMA, 1); - if (!res) { - dev_err(&pdev->dev, "no DMA resource\n"); - goto err_release_region; - } - - dma_data[count].channel = res->start; - davinci_mcasp_dai[pdata->op_mode].private_data = dev; - davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; - ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); - - if (ret != 0) - goto err_release_region; - return 0; - -err_release_region: - release_mem_region(mem->start, (mem->end - mem->start) + 1); -err_release_data: - kfree(dma_data); -err_release_dev: - kfree(dev); - - return ret; -} - -static int davinci_mcasp_remove(struct platform_device *pdev) -{ - struct snd_platform_data *pdata = pdev->dev.platform_data; - struct davinci_pcm_dma_params *dma_data; - struct davinci_audio_dev *dev; - struct resource *mem; - - snd_soc_unregister_dai(&davinci_mcasp_dai[pdata->op_mode]); - dev = davinci_mcasp_dai[pdata->op_mode].private_data; - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, (mem->end - mem->start) + 1); - - dma_data = dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; - kfree(dma_data); - kfree(dev); - - return 0; -} - -static struct platform_driver davinci_mcasp_driver = { - .probe = davinci_mcasp_probe, - .remove = davinci_mcasp_remove, - .driver = { - .name = "davinci-mcasp", - .owner = THIS_MODULE, - }, -}; - -static int __init davinci_mcasp_init(void) -{ - return platform_driver_register(&davinci_mcasp_driver); -} -module_init(davinci_mcasp_init); - -static void __exit davinci_mcasp_exit(void) -{ - platform_driver_unregister(&davinci_mcasp_driver); -} -module_exit(davinci_mcasp_exit); - -MODULE_AUTHOR("Steve Chen"); -MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/davinci/davinci-mcasp.h b/trunk/sound/soc/davinci/davinci-mcasp.h deleted file mode 100644 index 554354c1cc2f..000000000000 --- a/trunk/sound/soc/davinci/davinci-mcasp.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * ALSA SoC McASP Audio Layer for TI DAVINCI processor - * - * MCASP related definitions - * - * Author: Nirmal Pandey , - * Suresh Rajashekara - * Steve Chen - * - * Copyright: (C) 2009 MontaVista Software, Inc., - * Copyright: (C) 2009 Texas Instruments, India - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef DAVINCI_MCASP_H -#define DAVINCI_MCASP_H - -#include -#include -#include "davinci-pcm.h" - -extern struct snd_soc_dai davinci_mcasp_dai[]; - -#define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 -#define DAVINCI_MCASP_I2S_DAI 0 -#define DAVINCI_MCASP_DIT_DAI 1 - -enum { - DAVINCI_AUDIO_WORD_8 = 0, - DAVINCI_AUDIO_WORD_12, - DAVINCI_AUDIO_WORD_16, - DAVINCI_AUDIO_WORD_20, - DAVINCI_AUDIO_WORD_24, - DAVINCI_AUDIO_WORD_32, - DAVINCI_AUDIO_WORD_28, /* This is only valid for McASP */ -}; - -struct davinci_audio_dev { - void __iomem *base; - int sample_rate; - struct clk *clk; - struct davinci_pcm_dma_params *dma_params[2]; - unsigned int codec_fmt; - - /* McASP specific data */ - int tdm_slots; - u8 op_mode; - u8 num_serializer; - u8 *serial_dir; - u8 version; - - /* McASP FIFO related */ - u8 txnumevt; - u8 rxnumevt; -}; - -#endif /* DAVINCI_MCASP_H */ diff --git a/trunk/sound/soc/davinci/davinci-pcm.c b/trunk/sound/soc/davinci/davinci-pcm.c index 091dacb78b4d..a05996588489 100644 --- a/trunk/sound/soc/davinci/davinci-pcm.c +++ b/trunk/sound/soc/davinci/davinci-pcm.c @@ -67,7 +67,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) dma_addr_t src, dst; unsigned short src_bidx, dst_bidx; unsigned int data_type; - unsigned short acnt; unsigned int count; period_size = snd_pcm_lib_period_bytes(substream); @@ -92,12 +91,11 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) dst_bidx = data_type; } - acnt = prtd->params->acnt; edma_set_src(lch, src, INCR, W8BIT); edma_set_dest(lch, dst, INCR, W8BIT); edma_set_src_index(lch, src_bidx, 0); edma_set_dest_index(lch, dst_bidx, 0); - edma_set_transfer_params(lch, acnt, count, 1, 0, ASYNC); + edma_set_transfer_params(lch, data_type, count, 1, 0, ASYNC); prtd->period++; if (unlikely(prtd->period >= runtime->periods)) @@ -208,7 +206,6 @@ static int davinci_pcm_prepare(struct snd_pcm_substream *substream) /* Copy self-linked parameter RAM entry into master channel */ edma_read_slot(prtd->slave_lch, &temp); edma_write_slot(prtd->master_lch, &temp); - davinci_pcm_enqueue_dma(substream); return 0; } @@ -246,11 +243,6 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream) int ret = 0; snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware); - /* ensure that buffer size is a multiple of period size */ - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - return ret; prtd = kzalloc(sizeof(struct davinci_runtime_data), GFP_KERNEL); if (prtd == NULL) diff --git a/trunk/sound/soc/davinci/davinci-pcm.h b/trunk/sound/soc/davinci/davinci-pcm.h index 63d96253c73a..62cb4eb07e34 100644 --- a/trunk/sound/soc/davinci/davinci-pcm.h +++ b/trunk/sound/soc/davinci/davinci-pcm.h @@ -12,20 +12,17 @@ #ifndef _DAVINCI_PCM_H #define _DAVINCI_PCM_H -#include -#include - - struct davinci_pcm_dma_params { - char *name; /* stream identifier */ - int channel; /* sync dma channel ID */ - unsigned short acnt; - dma_addr_t dma_addr; /* device physical address for DMA */ - enum dma_event_q eventq_no; /* event queue number */ - unsigned char data_type; /* xfer data type */ - unsigned char convert_mono_stereo; + char *name; /* stream identifier */ + int channel; /* sync dma channel ID */ + dma_addr_t dma_addr; /* device physical address for DMA */ + unsigned int data_type; /* xfer data type */ }; +struct evm_snd_platform_data { + int tx_dma_ch; + int rx_dma_ch; +}; extern struct snd_soc_platform davinci_soc_platform; diff --git a/trunk/sound/soc/fsl/mpc5200_dma.c b/trunk/sound/soc/fsl/mpc5200_dma.c index 9ff62e3a9b1d..f0a2d4071998 100644 --- a/trunk/sound/soc/fsl/mpc5200_dma.c +++ b/trunk/sound/soc/fsl/mpc5200_dma.c @@ -69,23 +69,6 @@ static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s) static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s) { - if (s->appl_ptr > s->runtime->control->appl_ptr) { - /* - * In this case s->runtime->control->appl_ptr has wrapped around. - * Play the data to the end of the boundary, then wrap our own - * appl_ptr back around. - */ - while (s->appl_ptr < s->runtime->boundary) { - if (bcom_queue_full(s->bcom_task)) - return; - - s->appl_ptr += s->period_size; - - psc_dma_bcom_enqueue_next_buffer(s); - } - s->appl_ptr -= s->runtime->boundary; - } - while (s->appl_ptr < s->runtime->control->appl_ptr) { if (bcom_queue_full(s->bcom_task)) diff --git a/trunk/sound/soc/fsl/mpc5200_psc_ac97.c b/trunk/sound/soc/fsl/mpc5200_psc_ac97.c index c4ae3e096bb9..7eb549985d49 100644 --- a/trunk/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/trunk/sound/soc/fsl/mpc5200_psc_ac97.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -113,7 +112,7 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97) out_8(®s->op1, MPC52xx_PSC_OP_RES); udelay(10); out_8(®s->op0, MPC52xx_PSC_OP_RES); - msleep(1); + udelay(50); psc_ac97_warm_reset(ac97); } diff --git a/trunk/sound/soc/imx/Kconfig b/trunk/sound/soc/imx/Kconfig deleted file mode 100644 index a700562e8692..000000000000 --- a/trunk/sound/soc/imx/Kconfig +++ /dev/null @@ -1,21 +0,0 @@ -config SND_MX1_MX2_SOC - tristate "SoC Audio for Freecale i.MX1x i.MX2x CPUs" - depends on ARCH_MX2 || ARCH_MX1 - select SND_PCM - help - Say Y or M if you want to add support for codecs attached to - the MX1 or MX2 SSI interface. - -config SND_MXC_SOC_SSI - tristate - -config SND_SOC_MX27VIS_WM8974 - tristate "SoC Audio support for MX27 - WM8974 Visstrim_sm10 board" - depends on SND_MX1_MX2_SOC && MACH_MX27 && MACH_IMX27_VISSTRIM_M10 - select SND_MXC_SOC_SSI - select SND_SOC_WM8974 - help - Say Y if you want to add support for SoC audio on Visstrim SM10 - board with WM8974. - - diff --git a/trunk/sound/soc/imx/Makefile b/trunk/sound/soc/imx/Makefile deleted file mode 100644 index c2ffd2c8df5a..000000000000 --- a/trunk/sound/soc/imx/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# i.MX Platform Support -snd-soc-mx1_mx2-objs := mx1_mx2-pcm.o -snd-soc-mxc-ssi-objs := mxc-ssi.o - -obj-$(CONFIG_SND_MX1_MX2_SOC) += snd-soc-mx1_mx2.o -obj-$(CONFIG_SND_MXC_SOC_SSI) += snd-soc-mxc-ssi.o - -# i.MX Machine Support -snd-soc-mx27vis-wm8974-objs := mx27vis_wm8974.o -obj-$(CONFIG_SND_SOC_MX27VIS_WM8974) += snd-soc-mx27vis-wm8974.o diff --git a/trunk/sound/soc/imx/mx1_mx2-pcm.c b/trunk/sound/soc/imx/mx1_mx2-pcm.c deleted file mode 100644 index b83866529397..000000000000 --- a/trunk/sound/soc/imx/mx1_mx2-pcm.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * mx1_mx2-pcm.c -- ALSA SoC interface for Freescale i.MX1x, i.MX2x CPUs - * - * Copyright 2009 Vista Silicon S.L. - * Author: Javier Martin - * javier.martin@vista-silicon.com - * - * Based on mxc-pcm.c by Liam Girdwood. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mx1_mx2-pcm.h" - - -static const struct snd_pcm_hardware mx1_mx2_pcm_hardware = { - .info = (SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .buffer_bytes_max = 32 * 1024, - .period_bytes_min = 64, - .period_bytes_max = 8 * 1024, - .periods_min = 2, - .periods_max = 255, - .fifo_size = 0, -}; - -struct mx1_mx2_runtime_data { - int dma_ch; - int active; - unsigned int period; - unsigned int periods; - int tx_spin; - spinlock_t dma_lock; - struct mx1_mx2_pcm_dma_params *dma_params; -}; - - -/** - * This function stops the current dma transfer for playback - * and clears the dma pointers. - * - * @param substream pointer to the structure of the current stream. - * - */ -static int audio_stop_dma(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mx1_mx2_runtime_data *prtd = runtime->private_data; - unsigned long flags; - - spin_lock_irqsave(&prtd->dma_lock, flags); - - pr_debug("%s\n", __func__); - - prtd->active = 0; - prtd->period = 0; - prtd->periods = 0; - - /* this stops the dma channel and clears the buffer ptrs */ - - imx_dma_disable(prtd->dma_ch); - - spin_unlock_irqrestore(&prtd->dma_lock, flags); - - return 0; -} - -/** - * This function is called whenever a new audio block needs to be - * transferred to the codec. The function receives the address and the size - * of the new block and start a new DMA transfer. - * - * @param substream pointer to the structure of the current stream. - * - */ -static int dma_new_period(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mx1_mx2_runtime_data *prtd = runtime->private_data; - unsigned int dma_size; - unsigned int offset; - int ret = 0; - dma_addr_t mem_addr; - unsigned int dev_addr; - - if (prtd->active) { - dma_size = frames_to_bytes(runtime, runtime->period_size); - offset = dma_size * prtd->period; - - pr_debug("%s: period (%d) out of (%d)\n", __func__, - prtd->period, - runtime->periods); - pr_debug("period_size %d frames\n offset %d bytes\n", - (unsigned int)runtime->period_size, - offset); - pr_debug("dma_size %d bytes\n", dma_size); - - snd_BUG_ON(dma_size > mx1_mx2_pcm_hardware.period_bytes_max); - - mem_addr = (dma_addr_t)(runtime->dma_addr + offset); - dev_addr = prtd->dma_params->per_address; - pr_debug("%s: mem_addr is %x\n dev_addr is %x\n", - __func__, mem_addr, dev_addr); - - ret = imx_dma_setup_single(prtd->dma_ch, mem_addr, - dma_size, dev_addr, - prtd->dma_params->transfer_type); - if (ret < 0) { - printk(KERN_ERR "Error %d configuring DMA\n", ret); - return ret; - } - imx_dma_enable(prtd->dma_ch); - - pr_debug("%s: transfer enabled\nmem_addr = %x\n", - __func__, (unsigned int) mem_addr); - pr_debug("dev_addr = %x\ndma_size = %d\n", - (unsigned int) dev_addr, dma_size); - - prtd->tx_spin = 1; /* FGA little trick to retrieve DMA pos */ - prtd->period++; - prtd->period %= runtime->periods; - } - return ret; -} - - -/** - * This is a callback which will be called - * when a TX transfer finishes. The call occurs - * in interrupt context. - * - * @param dat pointer to the structure of the current stream. - * - */ -static void audio_dma_irq(int channel, void *data) -{ - struct snd_pcm_substream *substream; - struct snd_pcm_runtime *runtime; - struct mx1_mx2_runtime_data *prtd; - unsigned int dma_size; - unsigned int previous_period; - unsigned int offset; - - substream = data; - runtime = substream->runtime; - prtd = runtime->private_data; - previous_period = prtd->periods; - dma_size = frames_to_bytes(runtime, runtime->period_size); - offset = dma_size * previous_period; - - prtd->tx_spin = 0; - prtd->periods++; - prtd->periods %= runtime->periods; - - pr_debug("%s: irq per %d offset %x\n", __func__, prtd->periods, offset); - - /* - * If we are getting a callback for an active stream then we inform - * the PCM middle layer we've finished a period - */ - if (prtd->active) - snd_pcm_period_elapsed(substream); - - /* - * Trig next DMA transfer - */ - dma_new_period(substream); -} - -/** - * This function configures the hardware to allow audio - * playback operations. It is called by ALSA framework. - * - * @param substream pointer to the structure of the current stream. - * - * @return 0 on success, -1 otherwise. - */ -static int -snd_mx1_mx2_prepare(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mx1_mx2_runtime_data *prtd = runtime->private_data; - - prtd->period = 0; - prtd->periods = 0; - - return 0; -} - -static int mx1_mx2_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); - if (ret < 0) { - printk(KERN_ERR "%s: Error %d failed to malloc pcm pages \n", - __func__, ret); - return ret; - } - - pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_addr 0x(%x)\n", - __func__, (unsigned int)runtime->dma_addr); - pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_area 0x(%x)\n", - __func__, (unsigned int)runtime->dma_area); - pr_debug("%s: snd_imx1_mx2_audio_hw_params runtime->dma_bytes 0x(%x)\n", - __func__, (unsigned int)runtime->dma_bytes); - - return ret; -} - -static int mx1_mx2_pcm_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mx1_mx2_runtime_data *prtd = runtime->private_data; - - imx_dma_free(prtd->dma_ch); - - snd_pcm_lib_free_pages(substream); - - return 0; -} - -static int mx1_mx2_pcm_trigger(struct snd_pcm_substream *substream, int cmd) -{ - struct mx1_mx2_runtime_data *prtd = substream->runtime->private_data; - int ret = 0; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - prtd->tx_spin = 0; - /* requested stream startup */ - prtd->active = 1; - pr_debug("%s: starting dma_new_period\n", __func__); - ret = dma_new_period(substream); - break; - case SNDRV_PCM_TRIGGER_STOP: - /* requested stream shutdown */ - pr_debug("%s: stopping dma transfer\n", __func__); - ret = audio_stop_dma(substream); - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static snd_pcm_uframes_t -mx1_mx2_pcm_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mx1_mx2_runtime_data *prtd = runtime->private_data; - unsigned int offset = 0; - - /* tx_spin value is used here to check if a transfer is active */ - if (prtd->tx_spin) { - offset = (runtime->period_size * (prtd->periods)) + - (runtime->period_size >> 1); - if (offset >= runtime->buffer_size) - offset = runtime->period_size >> 1; - } else { - offset = (runtime->period_size * (prtd->periods)); - if (offset >= runtime->buffer_size) - offset = 0; - } - pr_debug("%s: pointer offset %x\n", __func__, offset); - - return offset; -} - -static int mx1_mx2_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mx1_mx2_runtime_data *prtd; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct mx1_mx2_pcm_dma_params *dma_data = rtd->dai->cpu_dai->dma_data; - int ret; - - snd_soc_set_runtime_hwparams(substream, &mx1_mx2_pcm_hardware); - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - if (ret < 0) - return ret; - - prtd = kzalloc(sizeof(struct mx1_mx2_runtime_data), GFP_KERNEL); - if (prtd == NULL) { - ret = -ENOMEM; - goto out; - } - - runtime->private_data = prtd; - - if (!dma_data) - return -ENODEV; - - prtd->dma_params = dma_data; - - pr_debug("%s: Requesting dma channel (%s)\n", __func__, - prtd->dma_params->name); - prtd->dma_ch = imx_dma_request_by_prio(prtd->dma_params->name, - DMA_PRIO_HIGH); - if (prtd->dma_ch < 0) { - printk(KERN_ERR "Error %d requesting dma channel\n", ret); - return ret; - } - imx_dma_config_burstlen(prtd->dma_ch, - prtd->dma_params->watermark_level); - - ret = imx_dma_config_channel(prtd->dma_ch, - prtd->dma_params->per_config, - prtd->dma_params->mem_config, - prtd->dma_params->event_id, 0); - - if (ret) { - pr_debug(KERN_ERR "Error %d configuring dma channel %d\n", - ret, prtd->dma_ch); - return ret; - } - - pr_debug("%s: Setting tx dma callback function\n", __func__); - ret = imx_dma_setup_handlers(prtd->dma_ch, - audio_dma_irq, NULL, - (void *)substream); - if (ret < 0) { - printk(KERN_ERR "Error %d setting dma callback function\n", ret); - return ret; - } - return 0; - - out: - return ret; -} - -static int mx1_mx2_pcm_close(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct mx1_mx2_runtime_data *prtd = runtime->private_data; - - kfree(prtd); - - return 0; -} - -static int mx1_mx2_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - return dma_mmap_writecombine(substream->pcm->card->dev, vma, - runtime->dma_area, - runtime->dma_addr, - runtime->dma_bytes); -} - -static struct snd_pcm_ops mx1_mx2_pcm_ops = { - .open = mx1_mx2_pcm_open, - .close = mx1_mx2_pcm_close, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = mx1_mx2_pcm_hw_params, - .hw_free = mx1_mx2_pcm_hw_free, - .prepare = snd_mx1_mx2_prepare, - .trigger = mx1_mx2_pcm_trigger, - .pointer = mx1_mx2_pcm_pointer, - .mmap = mx1_mx2_pcm_mmap, -}; - -static u64 mx1_mx2_pcm_dmamask = 0xffffffff; - -static int mx1_mx2_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) -{ - struct snd_pcm_substream *substream = pcm->streams[stream].substream; - struct snd_dma_buffer *buf = &substream->dma_buffer; - size_t size = mx1_mx2_pcm_hardware.buffer_bytes_max; - buf->dev.type = SNDRV_DMA_TYPE_DEV; - buf->dev.dev = pcm->card->dev; - buf->private_data = NULL; - - /* Reserve uncached-buffered memory area for DMA */ - buf->area = dma_alloc_writecombine(pcm->card->dev, size, - &buf->addr, GFP_KERNEL); - - pr_debug("%s: preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", - __func__, (void *) buf->area, (void *) buf->addr, size); - - if (!buf->area) - return -ENOMEM; - - buf->bytes = size; - return 0; -} - -static void mx1_mx2_pcm_free_dma_buffers(struct snd_pcm *pcm) -{ - struct snd_pcm_substream *substream; - struct snd_dma_buffer *buf; - int stream; - - for (stream = 0; stream < 2; stream++) { - substream = pcm->streams[stream].substream; - if (!substream) - continue; - - buf = &substream->dma_buffer; - if (!buf->area) - continue; - - dma_free_writecombine(pcm->card->dev, buf->bytes, - buf->area, buf->addr); - buf->area = NULL; - } -} - -static int mx1_mx2_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, - struct snd_pcm *pcm) -{ - int ret = 0; - - if (!card->dev->dma_mask) - card->dev->dma_mask = &mx1_mx2_pcm_dmamask; - if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = 0xffffffff; - - if (dai->playback.channels_min) { - ret = mx1_mx2_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_PLAYBACK); - pr_debug("%s: preallocate playback buffer\n", __func__); - if (ret) - goto out; - } - - if (dai->capture.channels_min) { - ret = mx1_mx2_pcm_preallocate_dma_buffer(pcm, - SNDRV_PCM_STREAM_CAPTURE); - pr_debug("%s: preallocate capture buffer\n", __func__); - if (ret) - goto out; - } - out: - return ret; -} - -struct snd_soc_platform mx1_mx2_soc_platform = { - .name = "mx1_mx2-audio", - .pcm_ops = &mx1_mx2_pcm_ops, - .pcm_new = mx1_mx2_pcm_new, - .pcm_free = mx1_mx2_pcm_free_dma_buffers, -}; -EXPORT_SYMBOL_GPL(mx1_mx2_soc_platform); - -static int __init mx1_mx2_soc_platform_init(void) -{ - return snd_soc_register_platform(&mx1_mx2_soc_platform); -} -module_init(mx1_mx2_soc_platform_init); - -static void __exit mx1_mx2_soc_platform_exit(void) -{ - snd_soc_unregister_platform(&mx1_mx2_soc_platform); -} -module_exit(mx1_mx2_soc_platform_exit); - -MODULE_AUTHOR("Javier Martin, javier.martin@vista-silicon.com"); -MODULE_DESCRIPTION("Freescale i.MX2x, i.MX1x PCM DMA module"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/imx/mx1_mx2-pcm.h b/trunk/sound/soc/imx/mx1_mx2-pcm.h deleted file mode 100644 index 2e528106570b..000000000000 --- a/trunk/sound/soc/imx/mx1_mx2-pcm.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * mx1_mx2-pcm.h :- ASoC platform header for Freescale i.MX1x, i.MX2x - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _MX1_MX2_PCM_H -#define _MX1_MX2_PCM_H - -/* DMA information for mx1_mx2 platforms */ -struct mx1_mx2_pcm_dma_params { - char *name; /* stream identifier */ - unsigned int transfer_type; /* READ or WRITE DMA transfer */ - dma_addr_t per_address; /* physical address of SSI fifo */ - int event_id; /* fixed DMA number for SSI fifo */ - int watermark_level; /* SSI fifo watermark level */ - int per_config; /* DMA Config flags for peripheral */ - int mem_config; /* DMA Config flags for RAM */ - }; - -/* platform data */ -extern struct snd_soc_platform mx1_mx2_soc_platform; - -#endif diff --git a/trunk/sound/soc/imx/mx27vis_wm8974.c b/trunk/sound/soc/imx/mx27vis_wm8974.c deleted file mode 100644 index e4dcb539108a..000000000000 --- a/trunk/sound/soc/imx/mx27vis_wm8974.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * mx27vis_wm8974.c -- SoC audio for mx27vis - * - * Copyright 2009 Vista Silicon S.L. - * Author: Javier Martin - * javier.martin@vista-silicon.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "../codecs/wm8974.h" -#include "mx1_mx2-pcm.h" -#include "mxc-ssi.h" -#include -#include - -#define IGNORED_ARG 0 - - -static struct snd_soc_card mx27vis; - -/** - * This function connects SSI1 (HPCR1) as slave to - * SSI1 external signals (PPCR1) - * As slave, HPCR1 must set TFSDIR and TCLKDIR as inputs from - * port 4 - */ -void audmux_connect_1_4(void) -{ - pr_debug("AUDMUX: normal operation mode\n"); - /* Reset HPCR1 and PPCR1 */ - - DAM_HPCR1 = 0x00000000; - DAM_PPCR1 = 0x00000000; - - /* set to synchronous */ - DAM_HPCR1 |= AUDMUX_HPCR_SYN; - DAM_PPCR1 |= AUDMUX_PPCR_SYN; - - - /* set Rx sources 1 <--> 4 */ - DAM_HPCR1 |= AUDMUX_HPCR_RXDSEL(3); /* port 4 */ - DAM_PPCR1 |= AUDMUX_PPCR_RXDSEL(0); /* port 1 */ - - /* set Tx frame and Clock direction and source 4 --> 1 output */ - DAM_HPCR1 |= AUDMUX_HPCR_TFSDIR | AUDMUX_HPCR_TCLKDIR; - DAM_HPCR1 |= AUDMUX_HPCR_TFCSEL(3); /* TxDS and TxCclk from port 4 */ - - return; -} - -static int mx27vis_hifi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - unsigned int pll_out = 0, bclk = 0, fmt = 0, mclk = 0; - int ret = 0; - - /* - * The WM8974 is better at generating accurate audio clocks than the - * MX27 SSI controller, so we will use it as master when we can. - */ - switch (params_rate(params)) { - case 8000: - fmt = SND_SOC_DAIFMT_CBM_CFM; - mclk = WM8974_MCLKDIV_12; - pll_out = 24576000; - break; - case 16000: - fmt = SND_SOC_DAIFMT_CBM_CFM; - pll_out = 12288000; - break; - case 48000: - fmt = SND_SOC_DAIFMT_CBM_CFM; - bclk = WM8974_BCLKDIV_4; - pll_out = 12288000; - break; - case 96000: - fmt = SND_SOC_DAIFMT_CBM_CFM; - bclk = WM8974_BCLKDIV_2; - pll_out = 12288000; - break; - case 11025: - fmt = SND_SOC_DAIFMT_CBM_CFM; - bclk = WM8974_BCLKDIV_16; - pll_out = 11289600; - break; - case 22050: - fmt = SND_SOC_DAIFMT_CBM_CFM; - bclk = WM8974_BCLKDIV_8; - pll_out = 11289600; - break; - case 44100: - fmt = SND_SOC_DAIFMT_CBM_CFM; - bclk = WM8974_BCLKDIV_4; - mclk = WM8974_MCLKDIV_2; - pll_out = 11289600; - break; - case 88200: - fmt = SND_SOC_DAIFMT_CBM_CFM; - bclk = WM8974_BCLKDIV_2; - pll_out = 11289600; - break; - } - - /* set codec DAI configuration */ - ret = codec_dai->ops->set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF | - SND_SOC_DAIFMT_SYNC | fmt); - if (ret < 0) { - printk(KERN_ERR "Error from codec DAI configuration\n"); - return ret; - } - - /* set cpu DAI configuration */ - ret = cpu_dai->ops->set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_SYNC | fmt); - if (ret < 0) { - printk(KERN_ERR "Error from cpu DAI configuration\n"); - return ret; - } - - /* Put DC field of STCCR to 1 (not zero) */ - ret = cpu_dai->ops->set_tdm_slot(cpu_dai, 0, 2); - - /* set the SSI system clock as input */ - ret = cpu_dai->ops->set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "Error when setting system SSI clk\n"); - return ret; - } - - /* set codec BCLK division for sample rate */ - ret = codec_dai->ops->set_clkdiv(codec_dai, WM8974_BCLKDIV, bclk); - if (ret < 0) { - printk(KERN_ERR "Error when setting BCLK division\n"); - return ret; - } - - - /* codec PLL input is 25 MHz */ - ret = codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, - 25000000, pll_out); - if (ret < 0) { - printk(KERN_ERR "Error when setting PLL input\n"); - return ret; - } - - /*set codec MCLK division for sample rate */ - ret = codec_dai->ops->set_clkdiv(codec_dai, WM8974_MCLKDIV, mclk); - if (ret < 0) { - printk(KERN_ERR "Error when setting MCLK division\n"); - return ret; - } - - return 0; -} - -static int mx27vis_hifi_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - - /* disable the PLL */ - return codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, 0, 0); -} - -/* - * mx27vis WM8974 HiFi DAI opserations. - */ -static struct snd_soc_ops mx27vis_hifi_ops = { - .hw_params = mx27vis_hifi_hw_params, - .hw_free = mx27vis_hifi_hw_free, -}; - - -static int mx27vis_suspend(struct platform_device *pdev, pm_message_t state) -{ - return 0; -} - -static int mx27vis_resume(struct platform_device *pdev) -{ - return 0; -} - -static int mx27vis_probe(struct platform_device *pdev) -{ - int ret = 0; - - ret = get_ssi_clk(0, &pdev->dev); - - if (ret < 0) { - printk(KERN_ERR "%s: cant get ssi clock\n", __func__); - return ret; - } - - - return 0; -} - -static int mx27vis_remove(struct platform_device *pdev) -{ - put_ssi_clk(0); - return 0; -} - -static struct snd_soc_dai_link mx27vis_dai[] = { -{ /* Hifi Playback*/ - .name = "WM8974", - .stream_name = "WM8974 HiFi", - .cpu_dai = &imx_ssi_pcm_dai[0], - .codec_dai = &wm8974_dai, - .ops = &mx27vis_hifi_ops, -}, -}; - -static struct snd_soc_card mx27vis = { - .name = "mx27vis", - .platform = &mx1_mx2_soc_platform, - .probe = mx27vis_probe, - .remove = mx27vis_remove, - .suspend_pre = mx27vis_suspend, - .resume_post = mx27vis_resume, - .dai_link = mx27vis_dai, - .num_links = ARRAY_SIZE(mx27vis_dai), -}; - -static struct snd_soc_device mx27vis_snd_devdata = { - .card = &mx27vis, - .codec_dev = &soc_codec_dev_wm8974, -}; - -static struct platform_device *mx27vis_snd_device; - -/* Temporal definition of board specific behaviour */ -void gpio_ssi_active(int ssi_num) -{ - int ret = 0; - - unsigned int ssi1_pins[] = { - PC20_PF_SSI1_FS, - PC21_PF_SSI1_RXD, - PC22_PF_SSI1_TXD, - PC23_PF_SSI1_CLK, - }; - unsigned int ssi2_pins[] = { - PC24_PF_SSI2_FS, - PC25_PF_SSI2_RXD, - PC26_PF_SSI2_TXD, - PC27_PF_SSI2_CLK, - }; - if (ssi_num == 0) - ret = mxc_gpio_setup_multiple_pins(ssi1_pins, - ARRAY_SIZE(ssi1_pins), "USB OTG"); - else - ret = mxc_gpio_setup_multiple_pins(ssi2_pins, - ARRAY_SIZE(ssi2_pins), "USB OTG"); - if (ret) - printk(KERN_ERR "Error requesting ssi %x pins\n", ssi_num); -} - - -static int __init mx27vis_init(void) -{ - int ret; - - mx27vis_snd_device = platform_device_alloc("soc-audio", -1); - if (!mx27vis_snd_device) - return -ENOMEM; - - platform_set_drvdata(mx27vis_snd_device, &mx27vis_snd_devdata); - mx27vis_snd_devdata.dev = &mx27vis_snd_device->dev; - ret = platform_device_add(mx27vis_snd_device); - - if (ret) { - printk(KERN_ERR "ASoC: Platform device allocation failed\n"); - platform_device_put(mx27vis_snd_device); - } - - /* WM8974 uses SSI1 (HPCR1) via AUDMUX port 4 for audio (PPCR1) */ - gpio_ssi_active(0); - audmux_connect_1_4(); - - return ret; -} - -static void __exit mx27vis_exit(void) -{ - /* We should call some "ssi_gpio_inactive()" properly */ -} - -module_init(mx27vis_init); -module_exit(mx27vis_exit); - - -MODULE_AUTHOR("Javier Martin, javier.martin@vista-silicon.com"); -MODULE_DESCRIPTION("ALSA SoC WM8974 mx27vis"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/imx/mxc-ssi.c b/trunk/sound/soc/imx/mxc-ssi.c deleted file mode 100644 index 3806ff2c0cd4..000000000000 --- a/trunk/sound/soc/imx/mxc-ssi.c +++ /dev/null @@ -1,868 +0,0 @@ -/* - * mxc-ssi.c -- SSI driver for Freescale IMX - * - * Copyright 2006 Wolfson Microelectronics PLC. - * Author: Liam Girdwood - * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com - * - * Based on mxc-alsa-mc13783 (C) 2006 Freescale. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * TODO: - * Need to rework SSI register defs when new defs go into mainline. - * Add support for TDM and FIFO 1. - * Add support for i.mx3x DMA interface. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mxc-ssi.h" -#include "mx1_mx2-pcm.h" - -#define SSI1_PORT 0 -#define SSI2_PORT 1 - -static int ssi_active[2] = {0, 0}; - -/* DMA information for mx1_mx2 platforms */ -static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_out0 = { - .name = "SSI1 PCM Stereo out 0", - .transfer_type = DMA_MODE_WRITE, - .per_address = SSI1_BASE_ADDR + STX0, - .event_id = DMA_REQ_SSI1_TX0, - .watermark_level = TXFIFO_WATERMARK, - .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -}; - -static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_out1 = { - .name = "SSI1 PCM Stereo out 1", - .transfer_type = DMA_MODE_WRITE, - .per_address = SSI1_BASE_ADDR + STX1, - .event_id = DMA_REQ_SSI1_TX1, - .watermark_level = TXFIFO_WATERMARK, - .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -}; - -static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_in0 = { - .name = "SSI1 PCM Stereo in 0", - .transfer_type = DMA_MODE_READ, - .per_address = SSI1_BASE_ADDR + SRX0, - .event_id = DMA_REQ_SSI1_RX0, - .watermark_level = RXFIFO_WATERMARK, - .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -}; - -static struct mx1_mx2_pcm_dma_params imx_ssi1_pcm_stereo_in1 = { - .name = "SSI1 PCM Stereo in 1", - .transfer_type = DMA_MODE_READ, - .per_address = SSI1_BASE_ADDR + SRX1, - .event_id = DMA_REQ_SSI1_RX1, - .watermark_level = RXFIFO_WATERMARK, - .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -}; - -static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_out0 = { - .name = "SSI2 PCM Stereo out 0", - .transfer_type = DMA_MODE_WRITE, - .per_address = SSI2_BASE_ADDR + STX0, - .event_id = DMA_REQ_SSI2_TX0, - .watermark_level = TXFIFO_WATERMARK, - .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -}; - -static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_out1 = { - .name = "SSI2 PCM Stereo out 1", - .transfer_type = DMA_MODE_WRITE, - .per_address = SSI2_BASE_ADDR + STX1, - .event_id = DMA_REQ_SSI2_TX1, - .watermark_level = TXFIFO_WATERMARK, - .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -}; - -static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_in0 = { - .name = "SSI2 PCM Stereo in 0", - .transfer_type = DMA_MODE_READ, - .per_address = SSI2_BASE_ADDR + SRX0, - .event_id = DMA_REQ_SSI2_RX0, - .watermark_level = RXFIFO_WATERMARK, - .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -}; - -static struct mx1_mx2_pcm_dma_params imx_ssi2_pcm_stereo_in1 = { - .name = "SSI2 PCM Stereo in 1", - .transfer_type = DMA_MODE_READ, - .per_address = SSI2_BASE_ADDR + SRX1, - .event_id = DMA_REQ_SSI2_RX1, - .watermark_level = RXFIFO_WATERMARK, - .per_config = IMX_DMA_MEMSIZE_16 | IMX_DMA_TYPE_FIFO, - .mem_config = IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR, -}; - -static struct clk *ssi_clk0, *ssi_clk1; - -int get_ssi_clk(int ssi, struct device *dev) -{ - switch (ssi) { - case 0: - ssi_clk0 = clk_get(dev, "ssi1"); - if (IS_ERR(ssi_clk0)) - return PTR_ERR(ssi_clk0); - return 0; - case 1: - ssi_clk1 = clk_get(dev, "ssi2"); - if (IS_ERR(ssi_clk1)) - return PTR_ERR(ssi_clk1); - return 0; - default: - return -EINVAL; - } -} -EXPORT_SYMBOL(get_ssi_clk); - -void put_ssi_clk(int ssi) -{ - switch (ssi) { - case 0: - clk_put(ssi_clk0); - ssi_clk0 = NULL; - break; - case 1: - clk_put(ssi_clk1); - ssi_clk1 = NULL; - break; - } -} -EXPORT_SYMBOL(put_ssi_clk); - -/* - * SSI system clock configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, - int clk_id, unsigned int freq, int dir) -{ - u32 scr; - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - scr = SSI1_SCR; - pr_debug("%s: SCR for SSI1 is %x\n", __func__, scr); - } else { - scr = SSI2_SCR; - pr_debug("%s: SCR for SSI2 is %x\n", __func__, scr); - } - - if (scr & SSI_SCR_SSIEN) { - printk(KERN_WARNING "Warning ssi already enabled\n"); - return 0; - } - - switch (clk_id) { - case IMX_SSP_SYS_CLK: - if (dir == SND_SOC_CLOCK_OUT) { - scr |= SSI_SCR_SYS_CLK_EN; - pr_debug("%s: clk of is output\n", __func__); - } else { - scr &= ~SSI_SCR_SYS_CLK_EN; - pr_debug("%s: clk of is input\n", __func__); - } - break; - default: - return -EINVAL; - } - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - pr_debug("%s: writeback of SSI1_SCR\n", __func__); - SSI1_SCR = scr; - } else { - pr_debug("%s: writeback of SSI2_SCR\n", __func__); - SSI2_SCR = scr; - } - - return 0; -} - -/* - * SSI Clock dividers - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, - int div_id, int div) -{ - u32 stccr, srccr; - - pr_debug("%s\n", __func__); - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - if (SSI1_SCR & SSI_SCR_SSIEN) - return 0; - srccr = SSI1_STCCR; - stccr = SSI1_STCCR; - } else { - if (SSI2_SCR & SSI_SCR_SSIEN) - return 0; - srccr = SSI2_STCCR; - stccr = SSI2_STCCR; - } - - switch (div_id) { - case IMX_SSI_TX_DIV_2: - stccr &= ~SSI_STCCR_DIV2; - stccr |= div; - break; - case IMX_SSI_TX_DIV_PSR: - stccr &= ~SSI_STCCR_PSR; - stccr |= div; - break; - case IMX_SSI_TX_DIV_PM: - stccr &= ~0xff; - stccr |= SSI_STCCR_PM(div); - break; - case IMX_SSI_RX_DIV_2: - stccr &= ~SSI_STCCR_DIV2; - stccr |= div; - break; - case IMX_SSI_RX_DIV_PSR: - stccr &= ~SSI_STCCR_PSR; - stccr |= div; - break; - case IMX_SSI_RX_DIV_PM: - stccr &= ~0xff; - stccr |= SSI_STCCR_PM(div); - break; - default: - return -EINVAL; - } - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - SSI1_STCCR = stccr; - SSI1_SRCCR = srccr; - } else { - SSI2_STCCR = stccr; - SSI2_SRCCR = srccr; - } - return 0; -} - -/* - * SSI Network Mode or TDM slots configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - */ -static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, - unsigned int mask, int slots) -{ - u32 stmsk, srmsk, stccr; - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - if (SSI1_SCR & SSI_SCR_SSIEN) { - printk(KERN_WARNING "Warning ssi already enabled\n"); - return 0; - } - stccr = SSI1_STCCR; - } else { - if (SSI2_SCR & SSI_SCR_SSIEN) { - printk(KERN_WARNING "Warning ssi already enabled\n"); - return 0; - } - stccr = SSI2_STCCR; - } - - stmsk = srmsk = mask; - stccr &= ~SSI_STCCR_DC_MASK; - stccr |= SSI_STCCR_DC(slots - 1); - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - SSI1_STMSK = stmsk; - SSI1_SRMSK = srmsk; - SSI1_SRCCR = SSI1_STCCR = stccr; - } else { - SSI2_STMSK = stmsk; - SSI2_SRMSK = srmsk; - SSI2_SRCCR = SSI2_STCCR = stccr; - } - - return 0; -} - -/* - * SSI DAI format configuration. - * Should only be called when port is inactive (i.e. SSIEN = 0). - * Note: We don't use the I2S modes but instead manually configure the - * SSI for I2S. - */ -static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) -{ - u32 stcr = 0, srcr = 0, scr; - - /* - * This is done to avoid this function to modify - * previous set values in stcr - */ - stcr = SSI1_STCR; - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) - scr = SSI1_SCR & ~(SSI_SCR_SYN | SSI_SCR_NET); - else - scr = SSI2_SCR & ~(SSI_SCR_SYN | SSI_SCR_NET); - - if (scr & SSI_SCR_SSIEN) { - printk(KERN_WARNING "Warning ssi already enabled\n"); - return 0; - } - - /* DAI mode */ - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { - case SND_SOC_DAIFMT_I2S: - /* data on rising edge of bclk, frame low 1clk before data */ - stcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0; - srcr |= SSI_SRCR_RFSI | SSI_SRCR_REFS | SSI_SRCR_RXBIT0; - break; - case SND_SOC_DAIFMT_LEFT_J: - /* data on rising edge of bclk, frame high with data */ - stcr |= SSI_STCR_TXBIT0; - srcr |= SSI_SRCR_RXBIT0; - break; - case SND_SOC_DAIFMT_DSP_B: - /* data on rising edge of bclk, frame high with data */ - stcr |= SSI_STCR_TFSL; - srcr |= SSI_SRCR_RFSL; - break; - case SND_SOC_DAIFMT_DSP_A: - /* data on rising edge of bclk, frame high 1clk before data */ - stcr |= SSI_STCR_TFSL | SSI_STCR_TEFS; - srcr |= SSI_SRCR_RFSL | SSI_SRCR_REFS; - break; - } - - /* DAI clock inversion */ - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_IB_IF: - stcr |= SSI_STCR_TFSI; - stcr &= ~SSI_STCR_TSCKP; - srcr |= SSI_SRCR_RFSI; - srcr &= ~SSI_SRCR_RSCKP; - break; - case SND_SOC_DAIFMT_IB_NF: - stcr &= ~(SSI_STCR_TSCKP | SSI_STCR_TFSI); - srcr &= ~(SSI_SRCR_RSCKP | SSI_SRCR_RFSI); - break; - case SND_SOC_DAIFMT_NB_IF: - stcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP; - srcr |= SSI_SRCR_RFSI | SSI_SRCR_RSCKP; - break; - case SND_SOC_DAIFMT_NB_NF: - stcr &= ~SSI_STCR_TFSI; - stcr |= SSI_STCR_TSCKP; - srcr &= ~SSI_SRCR_RFSI; - srcr |= SSI_SRCR_RSCKP; - break; - } - - /* DAI clock master masks */ - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { - case SND_SOC_DAIFMT_CBS_CFS: - stcr |= SSI_STCR_TFDIR | SSI_STCR_TXDIR; - srcr |= SSI_SRCR_RFDIR | SSI_SRCR_RXDIR; - break; - case SND_SOC_DAIFMT_CBM_CFS: - stcr |= SSI_STCR_TFDIR; - srcr |= SSI_SRCR_RFDIR; - break; - case SND_SOC_DAIFMT_CBS_CFM: - stcr |= SSI_STCR_TXDIR; - srcr |= SSI_SRCR_RXDIR; - break; - } - - /* sync */ - if (!(fmt & SND_SOC_DAIFMT_ASYNC)) - scr |= SSI_SCR_SYN; - - /* tdm - only for stereo atm */ - if (fmt & SND_SOC_DAIFMT_TDM) - scr |= SSI_SCR_NET; - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - SSI1_STCR = stcr; - SSI1_SRCR = srcr; - SSI1_SCR = scr; - } else { - SSI2_STCR = stcr; - SSI2_SRCR = srcr; - SSI2_SCR = scr; - } - - return 0; -} - -static int imx_ssi_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - /* set up TX DMA params */ - switch (cpu_dai->id) { - case IMX_DAI_SSI0: - cpu_dai->dma_data = &imx_ssi1_pcm_stereo_out0; - break; - case IMX_DAI_SSI1: - cpu_dai->dma_data = &imx_ssi1_pcm_stereo_out1; - break; - case IMX_DAI_SSI2: - cpu_dai->dma_data = &imx_ssi2_pcm_stereo_out0; - break; - case IMX_DAI_SSI3: - cpu_dai->dma_data = &imx_ssi2_pcm_stereo_out1; - } - pr_debug("%s: (playback)\n", __func__); - } else { - /* set up RX DMA params */ - switch (cpu_dai->id) { - case IMX_DAI_SSI0: - cpu_dai->dma_data = &imx_ssi1_pcm_stereo_in0; - break; - case IMX_DAI_SSI1: - cpu_dai->dma_data = &imx_ssi1_pcm_stereo_in1; - break; - case IMX_DAI_SSI2: - cpu_dai->dma_data = &imx_ssi2_pcm_stereo_in0; - break; - case IMX_DAI_SSI3: - cpu_dai->dma_data = &imx_ssi2_pcm_stereo_in1; - } - pr_debug("%s: (capture)\n", __func__); - } - - /* - * we cant really change any SSI values after SSI is enabled - * need to fix in software for max flexibility - lrg - */ - if (cpu_dai->active) { - printk(KERN_WARNING "Warning ssi already enabled\n"); - return 0; - } - - /* reset the SSI port - Sect 45.4.4 */ - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - - if (!ssi_clk0) - return -EINVAL; - - if (ssi_active[SSI1_PORT]++) { - pr_debug("%s: exit before reset\n", __func__); - return 0; - } - - /* SSI1 Reset */ - SSI1_SCR = 0; - - SSI1_SFCSR = SSI_SFCSR_RFWM1(RXFIFO_WATERMARK) | - SSI_SFCSR_RFWM0(RXFIFO_WATERMARK) | - SSI_SFCSR_TFWM1(TXFIFO_WATERMARK) | - SSI_SFCSR_TFWM0(TXFIFO_WATERMARK); - } else { - - if (!ssi_clk1) - return -EINVAL; - - if (ssi_active[SSI2_PORT]++) { - pr_debug("%s: exit before reset\n", __func__); - return 0; - } - - /* SSI2 Reset */ - SSI2_SCR = 0; - - SSI2_SFCSR = SSI_SFCSR_RFWM1(RXFIFO_WATERMARK) | - SSI_SFCSR_RFWM0(RXFIFO_WATERMARK) | - SSI_SFCSR_TFWM1(TXFIFO_WATERMARK) | - SSI_SFCSR_TFWM0(TXFIFO_WATERMARK); - } - - return 0; -} - -int imx_ssi_hw_tx_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - u32 stccr, stcr, sier; - - pr_debug("%s\n", __func__); - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - stccr = SSI1_STCCR & ~SSI_STCCR_WL_MASK; - stcr = SSI1_STCR; - sier = SSI1_SIER; - } else { - stccr = SSI2_STCCR & ~SSI_STCCR_WL_MASK; - stcr = SSI2_STCR; - sier = SSI2_SIER; - } - - /* DAI data (word) size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - stccr |= SSI_STCCR_WL(16); - break; - case SNDRV_PCM_FORMAT_S20_3LE: - stccr |= SSI_STCCR_WL(20); - break; - case SNDRV_PCM_FORMAT_S24_LE: - stccr |= SSI_STCCR_WL(24); - break; - } - - /* enable interrupts */ - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) - stcr |= SSI_STCR_TFEN0; - else - stcr |= SSI_STCR_TFEN1; - sier |= SSI_SIER_TDMAE; - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - SSI1_STCR = stcr; - SSI1_STCCR = stccr; - SSI1_SIER = sier; - } else { - SSI2_STCR = stcr; - SSI2_STCCR = stccr; - SSI2_SIER = sier; - } - - return 0; -} - -int imx_ssi_hw_rx_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - u32 srccr, srcr, sier; - - pr_debug("%s\n", __func__); - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - srccr = SSI1_SRCCR & ~SSI_SRCCR_WL_MASK; - srcr = SSI1_SRCR; - sier = SSI1_SIER; - } else { - srccr = SSI2_SRCCR & ~SSI_SRCCR_WL_MASK; - srcr = SSI2_SRCR; - sier = SSI2_SIER; - } - - /* DAI data (word) size */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16_LE: - srccr |= SSI_SRCCR_WL(16); - break; - case SNDRV_PCM_FORMAT_S20_3LE: - srccr |= SSI_SRCCR_WL(20); - break; - case SNDRV_PCM_FORMAT_S24_LE: - srccr |= SSI_SRCCR_WL(24); - break; - } - - /* enable interrupts */ - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) - srcr |= SSI_SRCR_RFEN0; - else - srcr |= SSI_SRCR_RFEN1; - sier |= SSI_SIER_RDMAE; - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - SSI1_SRCR = srcr; - SSI1_SRCCR = srccr; - SSI1_SIER = sier; - } else { - SSI2_SRCR = srcr; - SSI2_SRCCR = srccr; - SSI2_SIER = sier; - } - - return 0; -} - -/* - * Should only be called when port is inactive (i.e. SSIEN = 0), - * although can be called multiple times by upper layers. - */ -int imx_ssi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - - int ret; - - /* cant change any parameters when SSI is running */ - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - if (SSI1_SCR & SSI_SCR_SSIEN) { - printk(KERN_WARNING "Warning ssi already enabled\n"); - return 0; - } - } else { - if (SSI2_SCR & SSI_SCR_SSIEN) { - printk(KERN_WARNING "Warning ssi already enabled\n"); - return 0; - } - } - - /* - * Configure both tx and rx params with the same settings. This is - * really a harware restriction because SSI must be disabled until - * we can change those values. If there is an active audio stream in - * one direction, enabling the other direction with different - * settings would mean disturbing the running one. - */ - ret = imx_ssi_hw_tx_params(substream, params); - if (ret < 0) - return ret; - return imx_ssi_hw_rx_params(substream, params); -} - -int imx_ssi_prepare(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - int ret; - - pr_debug("%s\n", __func__); - - /* Enable clks here to follow SSI recommended init sequence */ - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) { - ret = clk_enable(ssi_clk0); - if (ret < 0) - printk(KERN_ERR "Unable to enable ssi_clk0\n"); - } else { - ret = clk_enable(ssi_clk1); - if (ret < 0) - printk(KERN_ERR "Unable to enable ssi_clk1\n"); - } - - return 0; -} - -static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - u32 scr; - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) - scr = SSI1_SCR; - else - scr = SSI2_SCR; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - scr |= SSI_SCR_TE | SSI_SCR_SSIEN; - else - scr |= SSI_SCR_RE | SSI_SCR_SSIEN; - break; - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - scr &= ~SSI_SCR_TE; - else - scr &= ~SSI_SCR_RE; - break; - default: - return -EINVAL; - } - - if (cpu_dai->id == IMX_DAI_SSI0 || cpu_dai->id == IMX_DAI_SSI2) - SSI1_SCR = scr; - else - SSI2_SCR = scr; - - return 0; -} - -static void imx_ssi_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - - /* shutdown SSI if neither Tx or Rx is active */ - if (!cpu_dai->active) { - - if (cpu_dai->id == IMX_DAI_SSI0 || - cpu_dai->id == IMX_DAI_SSI2) { - - if (--ssi_active[SSI1_PORT] > 1) - return; - - SSI1_SCR = 0; - clk_disable(ssi_clk0); - } else { - if (--ssi_active[SSI2_PORT]) - return; - SSI2_SCR = 0; - clk_disable(ssi_clk1); - } - } -} - -#ifdef CONFIG_PM -static int imx_ssi_suspend(struct platform_device *dev, - struct snd_soc_dai *dai) -{ - return 0; -} - -static int imx_ssi_resume(struct platform_device *pdev, - struct snd_soc_dai *dai) -{ - return 0; -} - -#else -#define imx_ssi_suspend NULL -#define imx_ssi_resume NULL -#endif - -#define IMX_SSI_RATES \ - (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | \ - SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ - SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ - SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \ - SNDRV_PCM_RATE_96000) - -#define IMX_SSI_BITS \ - (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ - SNDRV_PCM_FMTBIT_S24_LE) - -static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = { - .startup = imx_ssi_startup, - .shutdown = imx_ssi_shutdown, - .trigger = imx_ssi_trigger, - .prepare = imx_ssi_prepare, - .hw_params = imx_ssi_hw_params, - .set_sysclk = imx_ssi_set_dai_sysclk, - .set_clkdiv = imx_ssi_set_dai_clkdiv, - .set_fmt = imx_ssi_set_dai_fmt, - .set_tdm_slot = imx_ssi_set_dai_tdm_slot, -}; - -struct snd_soc_dai imx_ssi_pcm_dai[] = { -{ - .name = "imx-i2s-1-0", - .id = IMX_DAI_SSI0, - .suspend = imx_ssi_suspend, - .resume = imx_ssi_resume, - .playback = { - .channels_min = 1, - .channels_max = 2, - .formats = IMX_SSI_BITS, - .rates = IMX_SSI_RATES,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .formats = IMX_SSI_BITS, - .rates = IMX_SSI_RATES,}, - .ops = &imx_ssi_pcm_dai_ops, -}, -{ - .name = "imx-i2s-2-0", - .id = IMX_DAI_SSI1, - .playback = { - .channels_min = 1, - .channels_max = 2, - .formats = IMX_SSI_BITS, - .rates = IMX_SSI_RATES,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .formats = IMX_SSI_BITS, - .rates = IMX_SSI_RATES,}, - .ops = &imx_ssi_pcm_dai_ops, -}, -{ - .name = "imx-i2s-1-1", - .id = IMX_DAI_SSI2, - .suspend = imx_ssi_suspend, - .resume = imx_ssi_resume, - .playback = { - .channels_min = 1, - .channels_max = 2, - .formats = IMX_SSI_BITS, - .rates = IMX_SSI_RATES,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .formats = IMX_SSI_BITS, - .rates = IMX_SSI_RATES,}, - .ops = &imx_ssi_pcm_dai_ops, -}, -{ - .name = "imx-i2s-2-1", - .id = IMX_DAI_SSI3, - .playback = { - .channels_min = 1, - .channels_max = 2, - .formats = IMX_SSI_BITS, - .rates = IMX_SSI_RATES,}, - .capture = { - .channels_min = 1, - .channels_max = 2, - .formats = IMX_SSI_BITS, - .rates = IMX_SSI_RATES,}, - .ops = &imx_ssi_pcm_dai_ops, -}, -}; -EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai); - -static int __init imx_ssi_init(void) -{ - return snd_soc_register_dais(imx_ssi_pcm_dai, - ARRAY_SIZE(imx_ssi_pcm_dai)); -} - -static void __exit imx_ssi_exit(void) -{ - snd_soc_unregister_dais(imx_ssi_pcm_dai, - ARRAY_SIZE(imx_ssi_pcm_dai)); -} - -module_init(imx_ssi_init); -module_exit(imx_ssi_exit); -MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com"); -MODULE_DESCRIPTION("i.MX ASoC I2S driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/imx/mxc-ssi.h b/trunk/sound/soc/imx/mxc-ssi.h deleted file mode 100644 index 12bbdc9c7ecd..000000000000 --- a/trunk/sound/soc/imx/mxc-ssi.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef _IMX_SSI_H -#define _IMX_SSI_H - -#include - -/* SSI regs definition - MOVE to /arch/arm/plat-mxc/include/mach/ when stable */ -#define SSI1_IO_BASE_ADDR IO_ADDRESS(SSI1_BASE_ADDR) -#define SSI2_IO_BASE_ADDR IO_ADDRESS(SSI2_BASE_ADDR) - -#define STX0 0x00 -#define STX1 0x04 -#define SRX0 0x08 -#define SRX1 0x0c -#define SCR 0x10 -#define SISR 0x14 -#define SIER 0x18 -#define STCR 0x1c -#define SRCR 0x20 -#define STCCR 0x24 -#define SRCCR 0x28 -#define SFCSR 0x2c -#define STR 0x30 -#define SOR 0x34 -#define SACNT 0x38 -#define SACADD 0x3c -#define SACDAT 0x40 -#define SATAG 0x44 -#define STMSK 0x48 -#define SRMSK 0x4c - -#define SSI1_STX0 (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STX0))) -#define SSI1_STX1 (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STX1))) -#define SSI1_SRX0 (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRX0))) -#define SSI1_SRX1 (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRX1))) -#define SSI1_SCR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SCR))) -#define SSI1_SISR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SISR))) -#define SSI1_SIER (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SIER))) -#define SSI1_STCR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STCR))) -#define SSI1_SRCR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRCR))) -#define SSI1_STCCR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STCCR))) -#define SSI1_SRCCR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRCCR))) -#define SSI1_SFCSR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SFCSR))) -#define SSI1_STR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STR))) -#define SSI1_SOR (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SOR))) -#define SSI1_SACNT (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SACNT))) -#define SSI1_SACADD (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SACADD))) -#define SSI1_SACDAT (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SACDAT))) -#define SSI1_SATAG (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SATAG))) -#define SSI1_STMSK (*((volatile u32 *)(SSI1_IO_BASE_ADDR + STMSK))) -#define SSI1_SRMSK (*((volatile u32 *)(SSI1_IO_BASE_ADDR + SRMSK))) - - -#define SSI2_STX0 (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STX0))) -#define SSI2_STX1 (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STX1))) -#define SSI2_SRX0 (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRX0))) -#define SSI2_SRX1 (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRX1))) -#define SSI2_SCR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SCR))) -#define SSI2_SISR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SISR))) -#define SSI2_SIER (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SIER))) -#define SSI2_STCR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STCR))) -#define SSI2_SRCR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRCR))) -#define SSI2_STCCR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STCCR))) -#define SSI2_SRCCR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRCCR))) -#define SSI2_SFCSR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SFCSR))) -#define SSI2_STR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STR))) -#define SSI2_SOR (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SOR))) -#define SSI2_SACNT (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SACNT))) -#define SSI2_SACADD (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SACADD))) -#define SSI2_SACDAT (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SACDAT))) -#define SSI2_SATAG (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SATAG))) -#define SSI2_STMSK (*((volatile u32 *)(SSI2_IO_BASE_ADDR + STMSK))) -#define SSI2_SRMSK (*((volatile u32 *)(SSI2_IO_BASE_ADDR + SRMSK))) - -#define SSI_SCR_CLK_IST (1 << 9) -#define SSI_SCR_TCH_EN (1 << 8) -#define SSI_SCR_SYS_CLK_EN (1 << 7) -#define SSI_SCR_I2S_MODE_NORM (0 << 5) -#define SSI_SCR_I2S_MODE_MSTR (1 << 5) -#define SSI_SCR_I2S_MODE_SLAVE (2 << 5) -#define SSI_SCR_SYN (1 << 4) -#define SSI_SCR_NET (1 << 3) -#define SSI_SCR_RE (1 << 2) -#define SSI_SCR_TE (1 << 1) -#define SSI_SCR_SSIEN (1 << 0) - -#define SSI_SISR_CMDAU (1 << 18) -#define SSI_SISR_CMDDU (1 << 17) -#define SSI_SISR_RXT (1 << 16) -#define SSI_SISR_RDR1 (1 << 15) -#define SSI_SISR_RDR0 (1 << 14) -#define SSI_SISR_TDE1 (1 << 13) -#define SSI_SISR_TDE0 (1 << 12) -#define SSI_SISR_ROE1 (1 << 11) -#define SSI_SISR_ROE0 (1 << 10) -#define SSI_SISR_TUE1 (1 << 9) -#define SSI_SISR_TUE0 (1 << 8) -#define SSI_SISR_TFS (1 << 7) -#define SSI_SISR_RFS (1 << 6) -#define SSI_SISR_TLS (1 << 5) -#define SSI_SISR_RLS (1 << 4) -#define SSI_SISR_RFF1 (1 << 3) -#define SSI_SISR_RFF0 (1 << 2) -#define SSI_SISR_TFE1 (1 << 1) -#define SSI_SISR_TFE0 (1 << 0) - -#define SSI_SIER_RDMAE (1 << 22) -#define SSI_SIER_RIE (1 << 21) -#define SSI_SIER_TDMAE (1 << 20) -#define SSI_SIER_TIE (1 << 19) -#define SSI_SIER_CMDAU_EN (1 << 18) -#define SSI_SIER_CMDDU_EN (1 << 17) -#define SSI_SIER_RXT_EN (1 << 16) -#define SSI_SIER_RDR1_EN (1 << 15) -#define SSI_SIER_RDR0_EN (1 << 14) -#define SSI_SIER_TDE1_EN (1 << 13) -#define SSI_SIER_TDE0_EN (1 << 12) -#define SSI_SIER_ROE1_EN (1 << 11) -#define SSI_SIER_ROE0_EN (1 << 10) -#define SSI_SIER_TUE1_EN (1 << 9) -#define SSI_SIER_TUE0_EN (1 << 8) -#define SSI_SIER_TFS_EN (1 << 7) -#define SSI_SIER_RFS_EN (1 << 6) -#define SSI_SIER_TLS_EN (1 << 5) -#define SSI_SIER_RLS_EN (1 << 4) -#define SSI_SIER_RFF1_EN (1 << 3) -#define SSI_SIER_RFF0_EN (1 << 2) -#define SSI_SIER_TFE1_EN (1 << 1) -#define SSI_SIER_TFE0_EN (1 << 0) - -#define SSI_STCR_TXBIT0 (1 << 9) -#define SSI_STCR_TFEN1 (1 << 8) -#define SSI_STCR_TFEN0 (1 << 7) -#define SSI_STCR_TFDIR (1 << 6) -#define SSI_STCR_TXDIR (1 << 5) -#define SSI_STCR_TSHFD (1 << 4) -#define SSI_STCR_TSCKP (1 << 3) -#define SSI_STCR_TFSI (1 << 2) -#define SSI_STCR_TFSL (1 << 1) -#define SSI_STCR_TEFS (1 << 0) - -#define SSI_SRCR_RXBIT0 (1 << 9) -#define SSI_SRCR_RFEN1 (1 << 8) -#define SSI_SRCR_RFEN0 (1 << 7) -#define SSI_SRCR_RFDIR (1 << 6) -#define SSI_SRCR_RXDIR (1 << 5) -#define SSI_SRCR_RSHFD (1 << 4) -#define SSI_SRCR_RSCKP (1 << 3) -#define SSI_SRCR_RFSI (1 << 2) -#define SSI_SRCR_RFSL (1 << 1) -#define SSI_SRCR_REFS (1 << 0) - -#define SSI_STCCR_DIV2 (1 << 18) -#define SSI_STCCR_PSR (1 << 15) -#define SSI_STCCR_WL(x) ((((x) - 2) >> 1) << 13) -#define SSI_STCCR_DC(x) (((x) & 0x1f) << 8) -#define SSI_STCCR_PM(x) (((x) & 0xff) << 0) -#define SSI_STCCR_WL_MASK (0xf << 13) -#define SSI_STCCR_DC_MASK (0x1f << 8) -#define SSI_STCCR_PM_MASK (0xff << 0) - -#define SSI_SRCCR_DIV2 (1 << 18) -#define SSI_SRCCR_PSR (1 << 15) -#define SSI_SRCCR_WL(x) ((((x) - 2) >> 1) << 13) -#define SSI_SRCCR_DC(x) (((x) & 0x1f) << 8) -#define SSI_SRCCR_PM(x) (((x) & 0xff) << 0) -#define SSI_SRCCR_WL_MASK (0xf << 13) -#define SSI_SRCCR_DC_MASK (0x1f << 8) -#define SSI_SRCCR_PM_MASK (0xff << 0) - - -#define SSI_SFCSR_RFCNT1(x) (((x) & 0xf) << 28) -#define SSI_SFCSR_TFCNT1(x) (((x) & 0xf) << 24) -#define SSI_SFCSR_RFWM1(x) (((x) & 0xf) << 20) -#define SSI_SFCSR_TFWM1(x) (((x) & 0xf) << 16) -#define SSI_SFCSR_RFCNT0(x) (((x) & 0xf) << 12) -#define SSI_SFCSR_TFCNT0(x) (((x) & 0xf) << 8) -#define SSI_SFCSR_RFWM0(x) (((x) & 0xf) << 4) -#define SSI_SFCSR_TFWM0(x) (((x) & 0xf) << 0) - -#define SSI_STR_TEST (1 << 15) -#define SSI_STR_RCK2TCK (1 << 14) -#define SSI_STR_RFS2TFS (1 << 13) -#define SSI_STR_RXSTATE(x) (((x) & 0xf) << 8) -#define SSI_STR_TXD2RXD (1 << 7) -#define SSI_STR_TCK2RCK (1 << 6) -#define SSI_STR_TFS2RFS (1 << 5) -#define SSI_STR_TXSTATE(x) (((x) & 0xf) << 0) - -#define SSI_SOR_CLKOFF (1 << 6) -#define SSI_SOR_RX_CLR (1 << 5) -#define SSI_SOR_TX_CLR (1 << 4) -#define SSI_SOR_INIT (1 << 3) -#define SSI_SOR_WAIT(x) (((x) & 0x3) << 1) -#define SSI_SOR_SYNRST (1 << 0) - -#define SSI_SACNT_FRDIV(x) (((x) & 0x3f) << 5) -#define SSI_SACNT_WR (x << 4) -#define SSI_SACNT_RD (x << 3) -#define SSI_SACNT_TIF (x << 2) -#define SSI_SACNT_FV (x << 1) -#define SSI_SACNT_AC97EN (x << 0) - -/* Watermarks for FIFO's */ -#define TXFIFO_WATERMARK 0x4 -#define RXFIFO_WATERMARK 0x4 - -/* i.MX DAI SSP ID's */ -#define IMX_DAI_SSI0 0 /* SSI1 FIFO 0 */ -#define IMX_DAI_SSI1 1 /* SSI1 FIFO 1 */ -#define IMX_DAI_SSI2 2 /* SSI2 FIFO 0 */ -#define IMX_DAI_SSI3 3 /* SSI2 FIFO 1 */ - -/* SSI clock sources */ -#define IMX_SSP_SYS_CLK 0 - -/* SSI audio dividers */ -#define IMX_SSI_TX_DIV_2 0 -#define IMX_SSI_TX_DIV_PSR 1 -#define IMX_SSI_TX_DIV_PM 2 -#define IMX_SSI_RX_DIV_2 3 -#define IMX_SSI_RX_DIV_PSR 4 -#define IMX_SSI_RX_DIV_PM 5 - - -/* SSI Div 2 */ -#define IMX_SSI_DIV_2_OFF (~SSI_STCCR_DIV2) -#define IMX_SSI_DIV_2_ON SSI_STCCR_DIV2 - -extern struct snd_soc_dai imx_ssi_pcm_dai[4]; -extern int get_ssi_clk(int ssi, struct device *dev); -extern void put_ssi_clk(int ssi); -#endif diff --git a/trunk/sound/soc/omap/Kconfig b/trunk/sound/soc/omap/Kconfig index 2dee9839be86..b771238662b6 100644 --- a/trunk/sound/soc/omap/Kconfig +++ b/trunk/sound/soc/omap/Kconfig @@ -15,14 +15,6 @@ config SND_OMAP_SOC_N810 help Say Y if you want to add support for SoC audio on Nokia N810. -config SND_OMAP_SOC_AMS_DELTA - tristate "SoC Audio support for Amstrad E3 (Delta) videophone" - depends on SND_OMAP_SOC && MACH_AMS_DELTA - select SND_OMAP_SOC_MCBSP - select SND_SOC_CX20442 - help - Say Y if you want to add support for SoC audio on Amstrad Delta. - config SND_OMAP_SOC_OSK5912 tristate "SoC Audio support for omap osk5912" depends on SND_OMAP_SOC && MACH_OMAP_OSK && I2C @@ -80,11 +72,4 @@ config SND_OMAP_SOC_OMAP3_BEAGLE help Say Y if you want to add support for SoC audio on the Beagleboard. -config SND_OMAP_SOC_ZOOM2 - tristate "SoC Audio support for Zoom2" - depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 - select SND_OMAP_SOC_MCBSP - select SND_SOC_TWL4030 - help - Say Y if you want to add support for Soc audio on Zoom2 board. diff --git a/trunk/sound/soc/omap/Makefile b/trunk/sound/soc/omap/Makefile index 02d69471dcb5..a37f49862389 100644 --- a/trunk/sound/soc/omap/Makefile +++ b/trunk/sound/soc/omap/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o # OMAP Machine Support snd-soc-n810-objs := n810.o -snd-soc-ams-delta-objs := ams-delta.o snd-soc-osk5912-objs := osk5912.o snd-soc-overo-objs := overo.o snd-soc-omap2evm-objs := omap2evm.o @@ -15,10 +14,8 @@ snd-soc-omap3evm-objs := omap3evm.o snd-soc-sdp3430-objs := sdp3430.o snd-soc-omap3pandora-objs := omap3pandora.o snd-soc-omap3beagle-objs := omap3beagle.o -snd-soc-zoom2-objs := zoom2.o obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o -obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o @@ -26,4 +23,3 @@ obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o -obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o diff --git a/trunk/sound/soc/omap/ams-delta.c b/trunk/sound/soc/omap/ams-delta.c deleted file mode 100644 index 5a5166ac7279..000000000000 --- a/trunk/sound/soc/omap/ams-delta.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * ams-delta.c -- SoC audio for Amstrad E3 (Delta) videophone - * - * Copyright (C) 2009 Janusz Krzysztofik - * - * Initially based on sound/soc/omap/osk5912.x - * Copyright (C) 2008 Mistral Solutions - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include - -#include -#include - -#include - -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" -#include "../codecs/cx20442.h" - - -/* Board specific DAPM widgets */ - const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { - /* Handset */ - SND_SOC_DAPM_MIC("Mouthpiece", NULL), - SND_SOC_DAPM_HP("Earpiece", NULL), - /* Handsfree/Speakerphone */ - SND_SOC_DAPM_MIC("Microphone", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -/* How they are connected to codec pins */ -static const struct snd_soc_dapm_route ams_delta_audio_map[] = { - {"TELIN", NULL, "Mouthpiece"}, - {"Earpiece", NULL, "TELOUT"}, - - {"MIC", NULL, "Microphone"}, - {"Speaker", NULL, "SPKOUT"}, -}; - -/* - * Controls, functional after the modem line discipline is activated. - */ - -/* Virtual switch: audio input/output constellations */ -static const char *ams_delta_audio_mode[] = - {"Mixed", "Handset", "Handsfree", "Speakerphone"}; - -/* Selection <-> pin translation */ -#define AMS_DELTA_MOUTHPIECE 0 -#define AMS_DELTA_EARPIECE 1 -#define AMS_DELTA_MICROPHONE 2 -#define AMS_DELTA_SPEAKER 3 -#define AMS_DELTA_AGC 4 - -#define AMS_DELTA_MIXED ((1 << AMS_DELTA_EARPIECE) | \ - (1 << AMS_DELTA_MICROPHONE)) -#define AMS_DELTA_HANDSET ((1 << AMS_DELTA_MOUTHPIECE) | \ - (1 << AMS_DELTA_EARPIECE)) -#define AMS_DELTA_HANDSFREE ((1 << AMS_DELTA_MICROPHONE) | \ - (1 << AMS_DELTA_SPEAKER)) -#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC)) - -unsigned short ams_delta_audio_mode_pins[] = { - AMS_DELTA_MIXED, - AMS_DELTA_HANDSET, - AMS_DELTA_HANDSFREE, - AMS_DELTA_SPEAKERPHONE, -}; - -static unsigned short ams_delta_audio_agc; - -static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - struct soc_enum *control = (struct soc_enum *)kcontrol->private_value; - unsigned short pins; - int pin, changed = 0; - - /* Refuse any mode changes if we are not able to control the codec. */ - if (!codec->control_data) - return -EUNATCH; - - if (ucontrol->value.enumerated.item[0] >= control->max) - return -EINVAL; - - mutex_lock(&codec->mutex); - - /* Translate selection to bitmap */ - pins = ams_delta_audio_mode_pins[ucontrol->value.enumerated.item[0]]; - - /* Setup pins after corresponding bits if changed */ - pin = !!(pins & (1 << AMS_DELTA_MOUTHPIECE)); - if (pin != snd_soc_dapm_get_pin_status(codec, "Mouthpiece")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "Mouthpiece"); - else - snd_soc_dapm_disable_pin(codec, "Mouthpiece"); - } - pin = !!(pins & (1 << AMS_DELTA_EARPIECE)); - if (pin != snd_soc_dapm_get_pin_status(codec, "Earpiece")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "Earpiece"); - else - snd_soc_dapm_disable_pin(codec, "Earpiece"); - } - pin = !!(pins & (1 << AMS_DELTA_MICROPHONE)); - if (pin != snd_soc_dapm_get_pin_status(codec, "Microphone")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "Microphone"); - else - snd_soc_dapm_disable_pin(codec, "Microphone"); - } - pin = !!(pins & (1 << AMS_DELTA_SPEAKER)); - if (pin != snd_soc_dapm_get_pin_status(codec, "Speaker")) { - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "Speaker"); - else - snd_soc_dapm_disable_pin(codec, "Speaker"); - } - pin = !!(pins & (1 << AMS_DELTA_AGC)); - if (pin != ams_delta_audio_agc) { - ams_delta_audio_agc = pin; - changed = 1; - if (pin) - snd_soc_dapm_enable_pin(codec, "AGCIN"); - else - snd_soc_dapm_disable_pin(codec, "AGCIN"); - } - if (changed) - snd_soc_dapm_sync(codec); - - mutex_unlock(&codec->mutex); - - return changed; -} - -static int ams_delta_get_audio_mode(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned short pins, mode; - - pins = ((snd_soc_dapm_get_pin_status(codec, "Mouthpiece") << - AMS_DELTA_MOUTHPIECE) | - (snd_soc_dapm_get_pin_status(codec, "Earpiece") << - AMS_DELTA_EARPIECE)); - if (pins) - pins |= (snd_soc_dapm_get_pin_status(codec, "Microphone") << - AMS_DELTA_MICROPHONE); - else - pins = ((snd_soc_dapm_get_pin_status(codec, "Microphone") << - AMS_DELTA_MICROPHONE) | - (snd_soc_dapm_get_pin_status(codec, "Speaker") << - AMS_DELTA_SPEAKER) | - (ams_delta_audio_agc << AMS_DELTA_AGC)); - - for (mode = 0; mode < ARRAY_SIZE(ams_delta_audio_mode); mode++) - if (pins == ams_delta_audio_mode_pins[mode]) - break; - - if (mode >= ARRAY_SIZE(ams_delta_audio_mode)) - return -EINVAL; - - ucontrol->value.enumerated.item[0] = mode; - - return 0; -} - -static const struct soc_enum ams_delta_audio_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ams_delta_audio_mode), - ams_delta_audio_mode), -}; - -static const struct snd_kcontrol_new ams_delta_audio_controls[] = { - SOC_ENUM_EXT("Audio Mode", ams_delta_audio_enum[0], - ams_delta_get_audio_mode, ams_delta_set_audio_mode), -}; - -/* Hook switch */ -static struct snd_soc_jack ams_delta_hook_switch; -static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = { - { - .gpio = 4, - .name = "hook_switch", - .report = SND_JACK_HEADSET, - .invert = 1, - .debounce_time = 150, - } -}; - -/* After we are able to control the codec over the modem, - * the hook switch can be used for dynamic DAPM reconfiguration. */ -static struct snd_soc_jack_pin ams_delta_hook_switch_pins[] = { - /* Handset */ - { - .pin = "Mouthpiece", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Earpiece", - .mask = SND_JACK_HEADPHONE, - }, - /* Handsfree */ - { - .pin = "Microphone", - .mask = SND_JACK_MICROPHONE, - .invert = 1, - }, - { - .pin = "Speaker", - .mask = SND_JACK_HEADPHONE, - .invert = 1, - }, -}; - - -/* - * Modem line discipline, required for making above controls functional. - * Activated from userspace with ldattach, possibly invoked from udev rule. - */ - -/* To actually apply any modem controlled configuration changes to the codec, - * we must connect codec DAI pins to the modem for a moment. Be carefull not - * to interfere with our digital mute function that shares the same hardware. */ -static struct timer_list cx81801_timer; -static bool cx81801_cmd_pending; -static bool ams_delta_muted; -static DEFINE_SPINLOCK(ams_delta_lock); - -static void cx81801_timeout(unsigned long data) -{ - int muted; - - spin_lock(&ams_delta_lock); - cx81801_cmd_pending = 0; - muted = ams_delta_muted; - spin_unlock(&ams_delta_lock); - - /* Reconnect the codec DAI back from the modem to the CPU DAI - * only if digital mute still off */ - if (!muted) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0); -} - -/* Line discipline .open() */ -static int cx81801_open(struct tty_struct *tty) -{ - return v253_ops.open(tty); -} - -/* Line discipline .close() */ -static void cx81801_close(struct tty_struct *tty) -{ - struct snd_soc_codec *codec = tty->disc_data; - - del_timer_sync(&cx81801_timer); - - v253_ops.close(tty); - - /* Prevent the hook switch from further changing the DAPM pins */ - INIT_LIST_HEAD(&ams_delta_hook_switch.pins); - - /* Revert back to default audio input/output constellation */ - snd_soc_dapm_disable_pin(codec, "Mouthpiece"); - snd_soc_dapm_enable_pin(codec, "Earpiece"); - snd_soc_dapm_enable_pin(codec, "Microphone"); - snd_soc_dapm_disable_pin(codec, "Speaker"); - snd_soc_dapm_disable_pin(codec, "AGCIN"); - snd_soc_dapm_sync(codec); -} - -/* Line discipline .hangup() */ -static int cx81801_hangup(struct tty_struct *tty) -{ - cx81801_close(tty); - return 0; -} - -/* Line discipline .recieve_buf() */ -static void cx81801_receive(struct tty_struct *tty, - const unsigned char *cp, char *fp, int count) -{ - struct snd_soc_codec *codec = tty->disc_data; - const unsigned char *c; - int apply, ret; - - if (!codec->control_data) { - /* First modem response, complete setup procedure */ - - /* Initialize timer used for config pulse generation */ - setup_timer(&cx81801_timer, cx81801_timeout, 0); - - v253_ops.receive_buf(tty, cp, fp, count); - - /* Link hook switch to DAPM pins */ - ret = snd_soc_jack_add_pins(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_pins), - ams_delta_hook_switch_pins); - if (ret) - dev_warn(codec->socdev->card->dev, - "Failed to link hook switch to DAPM pins, " - "will continue with hook switch unlinked.\n"); - - return; - } - - v253_ops.receive_buf(tty, cp, fp, count); - - for (c = &cp[count - 1]; c >= cp; c--) { - if (*c != '\r') - continue; - /* Complete modem response received, apply config to codec */ - - spin_lock_bh(&ams_delta_lock); - mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150)); - apply = !ams_delta_muted && !cx81801_cmd_pending; - cx81801_cmd_pending = 1; - spin_unlock_bh(&ams_delta_lock); - - /* Apply config pulse by connecting the codec to the modem - * if not already done */ - if (apply) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, - AMS_DELTA_LATCH2_MODEM_CODEC); - break; - } -} - -/* Line discipline .write_wakeup() */ -static void cx81801_wakeup(struct tty_struct *tty) -{ - v253_ops.write_wakeup(tty); -} - -static struct tty_ldisc_ops cx81801_ops = { - .magic = TTY_LDISC_MAGIC, - .name = "cx81801", - .owner = THIS_MODULE, - .open = cx81801_open, - .close = cx81801_close, - .hangup = cx81801_hangup, - .receive_buf = cx81801_receive, - .write_wakeup = cx81801_wakeup, -}; - - -/* - * Even if not very usefull, the sound card can still work without any of the - * above functonality activated. You can still control its audio input/output - * constellation and speakerphone gain from userspace by issueing AT commands - * over the modem port. - */ - -static int ams_delta_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - - /* Set cpu DAI configuration */ - return snd_soc_dai_set_fmt(rtd->dai->cpu_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); -} - -static struct snd_soc_ops ams_delta_ops = { - .hw_params = ams_delta_hw_params, -}; - - -/* Board specific codec bias level control */ -static int ams_delta_set_bias_level(struct snd_soc_card *card, - enum snd_soc_bias_level level) -{ - struct snd_soc_codec *codec = card->codec; - - switch (level) { - case SND_SOC_BIAS_ON: - case SND_SOC_BIAS_PREPARE: - case SND_SOC_BIAS_STANDBY: - if (codec->bias_level == SND_SOC_BIAS_OFF) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET, - AMS_DELTA_LATCH2_MODEM_NRESET); - break; - case SND_SOC_BIAS_OFF: - if (codec->bias_level != SND_SOC_BIAS_OFF) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET, - 0); - } - codec->bias_level = level; - - return 0; -} - -/* Digital mute implemented using modem/CPU multiplexer. - * Shares hardware with codec config pulse generation */ -static bool ams_delta_muted = 1; - -static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute) -{ - int apply; - - if (ams_delta_muted == mute) - return 0; - - spin_lock_bh(&ams_delta_lock); - ams_delta_muted = mute; - apply = !cx81801_cmd_pending; - spin_unlock_bh(&ams_delta_lock); - - if (apply) - ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, - mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0); - return 0; -} - -/* Our codec DAI probably doesn't have its own .ops structure */ -static struct snd_soc_dai_ops ams_delta_dai_ops = { - .digital_mute = ams_delta_digital_mute, -}; - -/* Will be used if the codec ever has its own digital_mute function */ -static int ams_delta_startup(struct snd_pcm_substream *substream) -{ - return ams_delta_digital_mute(NULL, 0); -} - -static void ams_delta_shutdown(struct snd_pcm_substream *substream) -{ - ams_delta_digital_mute(NULL, 1); -} - - -/* - * Card initialization - */ - -static int ams_delta_cx20442_init(struct snd_soc_codec *codec) -{ - struct snd_soc_dai *codec_dai = codec->dai; - struct snd_soc_card *card = codec->socdev->card; - int ret; - /* Codec is ready, now add/activate board specific controls */ - - /* Set up digital mute if not provided by the codec */ - if (!codec_dai->ops) { - codec_dai->ops = &ams_delta_dai_ops; - } else if (!codec_dai->ops->digital_mute) { - codec_dai->ops->digital_mute = ams_delta_digital_mute; - } else { - ams_delta_ops.startup = ams_delta_startup; - ams_delta_ops.shutdown = ams_delta_shutdown; - } - - /* Set codec bias level */ - ams_delta_set_bias_level(card, SND_SOC_BIAS_STANDBY); - - /* Add hook switch - can be used to control the codec from userspace - * even if line discipline fails */ - ret = snd_soc_jack_new(card, "hook_switch", - SND_JACK_HEADSET, &ams_delta_hook_switch); - if (ret) - dev_warn(card->dev, - "Failed to allocate resources for hook switch, " - "will continue without one.\n"); - else { - ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_gpios), - ams_delta_hook_switch_gpios); - if (ret) - dev_warn(card->dev, - "Failed to set up hook switch GPIO line, " - "will continue with hook switch inactive.\n"); - } - - /* Register optional line discipline for over the modem control */ - ret = tty_register_ldisc(N_V253, &cx81801_ops); - if (ret) { - dev_warn(card->dev, - "Failed to register line discipline, " - "will continue without any controls.\n"); - return 0; - } - - /* Add board specific DAPM widgets and routes */ - ret = snd_soc_dapm_new_controls(codec, ams_delta_dapm_widgets, - ARRAY_SIZE(ams_delta_dapm_widgets)); - if (ret) { - dev_warn(card->dev, - "Failed to register DAPM controls, " - "will continue without any.\n"); - return 0; - } - - ret = snd_soc_dapm_add_routes(codec, ams_delta_audio_map, - ARRAY_SIZE(ams_delta_audio_map)); - if (ret) { - dev_warn(card->dev, - "Failed to set up DAPM routes, " - "will continue with codec default map.\n"); - return 0; - } - - /* Set up initial pin constellation */ - snd_soc_dapm_disable_pin(codec, "Mouthpiece"); - snd_soc_dapm_enable_pin(codec, "Earpiece"); - snd_soc_dapm_enable_pin(codec, "Microphone"); - snd_soc_dapm_disable_pin(codec, "Speaker"); - snd_soc_dapm_disable_pin(codec, "AGCIN"); - snd_soc_dapm_disable_pin(codec, "AGCOUT"); - snd_soc_dapm_sync(codec); - - /* Add virtual switch */ - ret = snd_soc_add_controls(codec, ams_delta_audio_controls, - ARRAY_SIZE(ams_delta_audio_controls)); - if (ret) - dev_warn(card->dev, - "Failed to register audio mode control, " - "will continue without it.\n"); - - return 0; -} - -/* DAI glue - connects codec <--> CPU */ -static struct snd_soc_dai_link ams_delta_dai_link = { - .name = "CX20442", - .stream_name = "CX20442", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &cx20442_dai, - .init = ams_delta_cx20442_init, - .ops = &ams_delta_ops, -}; - -/* Audio card driver */ -static struct snd_soc_card ams_delta_audio_card = { - .name = "AMS_DELTA", - .platform = &omap_soc_platform, - .dai_link = &ams_delta_dai_link, - .num_links = 1, - .set_bias_level = ams_delta_set_bias_level, -}; - -/* Audio subsystem */ -static struct snd_soc_device ams_delta_snd_soc_device = { - .card = &ams_delta_audio_card, - .codec_dev = &cx20442_codec_dev, -}; - -/* Module init/exit */ -static struct platform_device *ams_delta_audio_platform_device; -static struct platform_device *cx20442_platform_device; - -static int __init ams_delta_module_init(void) -{ - int ret; - - if (!(machine_is_ams_delta())) - return -ENODEV; - - ams_delta_audio_platform_device = - platform_device_alloc("soc-audio", -1); - if (!ams_delta_audio_platform_device) - return -ENOMEM; - - platform_set_drvdata(ams_delta_audio_platform_device, - &ams_delta_snd_soc_device); - ams_delta_snd_soc_device.dev = &ams_delta_audio_platform_device->dev; - *(unsigned int *)ams_delta_dai_link.cpu_dai->private_data = OMAP_MCBSP1; - - ret = platform_device_add(ams_delta_audio_platform_device); - if (ret) - goto err; - - /* - * Codec platform device could be registered from elsewhere (board?), - * but I do it here as it makes sense only if used with the card. - */ - cx20442_platform_device = platform_device_register_simple("cx20442", - -1, NULL, 0); - return 0; -err: - platform_device_put(ams_delta_audio_platform_device); - return ret; -} -module_init(ams_delta_module_init); - -static void __exit ams_delta_module_exit(void) -{ - struct snd_soc_codec *codec; - struct tty_struct *tty; - - if (ams_delta_audio_card.codec) { - codec = ams_delta_audio_card.codec; - - if (codec->control_data) { - tty = codec->control_data; - - tty_hangup(tty); - } - } - - if (tty_unregister_ldisc(N_V253) != 0) - dev_warn(&ams_delta_audio_platform_device->dev, - "failed to unregister V253 line discipline\n"); - - snd_soc_jack_free_gpios(&ams_delta_hook_switch, - ARRAY_SIZE(ams_delta_hook_switch_gpios), - ams_delta_hook_switch_gpios); - - /* Keep modem power on */ - ams_delta_set_bias_level(&ams_delta_audio_card, SND_SOC_BIAS_STANDBY); - - platform_device_unregister(cx20442_platform_device); - platform_device_unregister(ams_delta_audio_platform_device); -} -module_exit(ams_delta_module_exit); - -MODULE_AUTHOR("Janusz Krzysztofik "); -MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/omap/n810.c b/trunk/sound/soc/omap/n810.c index 0a505938e42b..b60b1dfbc435 100644 --- a/trunk/sound/soc/omap/n810.c +++ b/trunk/sound/soc/omap/n810.c @@ -22,7 +22,6 @@ */ #include -#include #include #include #include @@ -323,6 +322,8 @@ static struct snd_soc_card snd_soc_n810 = { /* Audio private data */ static struct aic3x_setup_data n810_aic33_setup = { + .i2c_bus = 2, + .i2c_address = 0x18, .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, }; @@ -336,13 +337,6 @@ static struct snd_soc_device n810_snd_devdata = { static struct platform_device *n810_snd_device; -/* temporary i2c device creation until this can be moved into the machine - * support file. -*/ -static struct i2c_board_info i2c_device[] = { - { I2C_BOARD_INFO("tlv320aic3x", 0x1b), } -}; - static int __init n810_soc_init(void) { int err; @@ -351,8 +345,6 @@ static int __init n810_soc_init(void) if (!(machine_is_nokia_n810() || machine_is_nokia_n810_wimax())) return -ENODEV; - i2c_register_board_info(1, i2c_device, ARRAY_SIZE(i2c_device)); - n810_snd_device = platform_device_alloc("soc-audio", -1); if (!n810_snd_device) return -ENOMEM; diff --git a/trunk/sound/soc/omap/omap-mcbsp.c b/trunk/sound/soc/omap/omap-mcbsp.c index 3341f49402ca..a5d46a7b196a 100644 --- a/trunk/sound/soc/omap/omap-mcbsp.c +++ b/trunk/sound/soc/omap/omap-mcbsp.c @@ -139,68 +139,28 @@ static const unsigned long omap34xx_mcbsp_port[][2] = { static const unsigned long omap34xx_mcbsp_port[][2] = {}; #endif -static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); - int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id); - int samples; - - /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ - if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) - samples = snd_pcm_lib_period_bytes(substream) >> 1; - else - samples = 1; - - /* Configure McBSP internal buffer usage */ - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, samples - 1); - else - omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, samples - 1); -} - static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); - int bus_id = mcbsp_data->bus_id; int err = 0; - if (!cpu_dai->active) - err = omap_mcbsp_request(bus_id); - - if (cpu_is_omap343x()) { - int dma_op_mode = omap_mcbsp_get_dma_op_mode(bus_id); - int max_period; - + if (cpu_is_omap343x() && mcbsp_data->bus_id == 1) { /* * McBSP2 in OMAP3 has 1024 * 32-bit internal audio buffer. * Set constraint for minimum buffer size to the same than FIFO * size in order to avoid underruns in playback startup because * HW is keeping the DMA request active until FIFO is filled. */ - if (bus_id == 1) - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - 4096, UINT_MAX); - - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - max_period = omap_mcbsp_get_max_tx_threshold(bus_id); - else - max_period = omap_mcbsp_get_max_rx_threshold(bus_id); - - max_period++; - max_period <<= 1; - - if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) - snd_pcm_hw_constraint_minmax(substream->runtime, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - 32, max_period); + snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4096, UINT_MAX); } + if (!cpu_dai->active) + err = omap_mcbsp_request(mcbsp_data->bus_id); + return err; } @@ -223,21 +183,21 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); - int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); + int err = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - mcbsp_data->active++; - omap_mcbsp_start(mcbsp_data->bus_id, play, !play); + if (!mcbsp_data->active++) + omap_mcbsp_start(mcbsp_data->bus_id); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - omap_mcbsp_stop(mcbsp_data->bus_id, play, !play); - mcbsp_data->active--; + if (!--mcbsp_data->active) + omap_mcbsp_stop(mcbsp_data->bus_id); break; default: err = -EINVAL; @@ -255,7 +215,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; - int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; + int wlen, channels, wpf; unsigned long port; unsigned int format; @@ -271,12 +231,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, } else if (cpu_is_omap343x()) { dma = omap24xx_dma_reqs[bus_id][substream->stream]; port = omap34xx_mcbsp_port[bus_id][substream->stream]; - omap_mcbsp_dai_dma_params[id][substream->stream].set_threshold = - omap_mcbsp_set_threshold; - /* TODO: Currently, MODE_ELEMENT == MODE_FRAME */ - if (omap_mcbsp_get_dma_op_mode(bus_id) == - MCBSP_DMA_MODE_THRESHOLD) - sync_mode = OMAP_DMA_SYNC_FRAME; } else { return -ENODEV; } @@ -284,7 +238,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, substream->stream ? "Audio Capture" : "Audio Playback"; omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; - omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; cpu_dai->dma_data = &omap_mcbsp_dai_dma_params[id][substream->stream]; if (mcbsp_data->configured) { @@ -368,14 +321,11 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, /* Generic McBSP register settings */ regs->spcr2 |= XINTM(3) | FREE; regs->spcr1 |= RINTM(3); - /* RFIG and XFIG are not defined in 34xx */ - if (!cpu_is_omap34xx()) { - regs->rcr2 |= RFIG; - regs->xcr2 |= XFIG; - } + regs->rcr2 |= RFIG; + regs->xcr2 |= XFIG; if (cpu_is_omap2430() || cpu_is_omap34xx()) { - regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; - regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; + regs->xccr = DXENDLY(1) | XDMAEN; + regs->rccr = RFULL_CYCLE | RDMAEN; } switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { @@ -512,40 +462,6 @@ static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data, return 0; } -static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data, - int clk_id) -{ - int sel_bit, set = 0; - u16 reg = OMAP2_CONTROL_DEVCONF0; - - if (cpu_class_is_omap1()) - return -EINVAL; /* TODO: Can this be implemented for OMAP1? */ - if (mcbsp_data->bus_id != 0) - return -EINVAL; - - switch (clk_id) { - case OMAP_MCBSP_CLKR_SRC_CLKX: - set = 1; - case OMAP_MCBSP_CLKR_SRC_CLKR: - sel_bit = 3; - break; - case OMAP_MCBSP_FSR_SRC_FSX: - set = 1; - case OMAP_MCBSP_FSR_SRC_FSR: - sel_bit = 4; - break; - default: - return -EINVAL; - } - - if (set) - omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg); - else - omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg); - - return 0; -} - static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) @@ -568,13 +484,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, case OMAP_MCBSP_SYSCLK_CLKR_EXT: regs->pcr0 |= SCLKME; break; - - case OMAP_MCBSP_CLKR_SRC_CLKR: - case OMAP_MCBSP_CLKR_SRC_CLKX: - case OMAP_MCBSP_FSR_SRC_FSR: - case OMAP_MCBSP_FSR_SRC_FSX: - err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id); - break; default: err = -ENODEV; } diff --git a/trunk/sound/soc/omap/omap-mcbsp.h b/trunk/sound/soc/omap/omap-mcbsp.h index 647d2f981ab0..c8147aace813 100644 --- a/trunk/sound/soc/omap/omap-mcbsp.h +++ b/trunk/sound/soc/omap/omap-mcbsp.h @@ -32,10 +32,6 @@ enum omap_mcbsp_clksrg_clk { OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */ - OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */ - OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */ - OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */ }; /* McBSP dividers */ diff --git a/trunk/sound/soc/omap/omap-pcm.c b/trunk/sound/soc/omap/omap-pcm.c index 5735945788bf..84a1950880eb 100644 --- a/trunk/sound/soc/omap/omap-pcm.c +++ b/trunk/sound/soc/omap/omap-pcm.c @@ -59,31 +59,16 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data) struct omap_runtime_data *prtd = runtime->private_data; unsigned long flags; - if ((cpu_is_omap1510()) && - (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) { + if (cpu_is_omap1510()) { /* - * OMAP1510 doesn't fully support DMA progress counter - * and there is no software emulation implemented yet, - * so have to maintain our own playback progress counter - * that can be used by omap_pcm_pointer() instead. + * OMAP1510 doesn't support DMA chaining so have to restart + * the transfer after all periods are transferred */ spin_lock_irqsave(&prtd->lock, flags); - if ((stat == OMAP_DMA_LAST_IRQ) && - (prtd->period_index == runtime->periods - 1)) { - /* we are in sync, do nothing */ - spin_unlock_irqrestore(&prtd->lock, flags); - return; - } if (prtd->period_index >= 0) { - if (stat & OMAP_DMA_BLOCK_IRQ) { - /* end of buffer reached, loop back */ - prtd->period_index = 0; - } else if (stat & OMAP_DMA_LAST_IRQ) { - /* update the counter for the last period */ - prtd->period_index = runtime->periods - 1; - } else if (++prtd->period_index >= runtime->periods) { - /* end of buffer missed? loop back */ + if (++prtd->period_index == runtime->periods) { prtd->period_index = 0; + omap_start_dma(prtd->dma_ch); } } spin_unlock_irqrestore(&prtd->lock, flags); @@ -115,7 +100,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, prtd->dma_data = dma_data; err = omap_request_dma(dma_data->dma_req, dma_data->name, omap_pcm_dma_irq, substream, &prtd->dma_ch); - if (!err) { + if (!err && !cpu_is_omap1510()) { /* * Link channel with itself so DMA doesn't need any * reprogramming while looping the buffer @@ -134,7 +119,8 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream) if (prtd->dma_data == NULL) return 0; - omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch); + if (!cpu_is_omap1510()) + omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch); omap_free_dma(prtd->dma_ch); prtd->dma_data = NULL; @@ -162,7 +148,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) */ dma_params.data_type = OMAP_DMA_DATA_TYPE_S16; dma_params.trigger = dma_data->dma_req; - dma_params.sync_mode = dma_data->sync_mode; + dma_params.sync_mode = OMAP_DMA_SYNC_ELEMENT; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; @@ -188,15 +174,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) dma_params.frame_count = runtime->periods; omap_set_dma_params(prtd->dma_ch, &dma_params); - if ((cpu_is_omap1510()) && - (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) - omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | - OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); - else - omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); - - omap_set_dma_src_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16); - omap_set_dma_dest_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16); + omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); return 0; } @@ -205,7 +183,6 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; struct omap_runtime_data *prtd = runtime->private_data; - struct omap_pcm_dma_data *dma_data = prtd->dma_data; unsigned long flags; int ret = 0; @@ -215,10 +192,6 @@ static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->period_index = 0; - /* Configure McBSP internal buffer usage */ - if (dma_data->set_threshold) - dma_data->set_threshold(substream); - omap_start_dma(prtd->dma_ch); break; @@ -315,7 +288,7 @@ static struct snd_pcm_ops omap_pcm_ops = { .mmap = omap_pcm_mmap, }; -static u64 omap_pcm_dmamask = DMA_BIT_MASK(64); +static u64 omap_pcm_dmamask = DMA_BIT_MASK(32); static int omap_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) @@ -357,7 +330,7 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm) } } -static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, +int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { int ret = 0; @@ -365,7 +338,7 @@ static int omap_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, if (!card->dev->dma_mask) card->dev->dma_mask = &omap_pcm_dmamask; if (!card->dev->coherent_dma_mask) - card->dev->coherent_dma_mask = DMA_BIT_MASK(64); + card->dev->coherent_dma_mask = DMA_BIT_MASK(32); if (dai->playback.channels_min) { ret = omap_pcm_preallocate_dma_buffer(pcm, diff --git a/trunk/sound/soc/omap/omap-pcm.h b/trunk/sound/soc/omap/omap-pcm.h index 38a821dd4118..8d9d26916b05 100644 --- a/trunk/sound/soc/omap/omap-pcm.h +++ b/trunk/sound/soc/omap/omap-pcm.h @@ -29,8 +29,6 @@ struct omap_pcm_dma_data { char *name; /* stream identifier */ int dma_req; /* DMA request line */ unsigned long port_addr; /* transmit/receive register */ - int sync_mode; /* DMA sync mode */ - void (*set_threshold)(struct snd_pcm_substream *substream); }; extern struct snd_soc_platform omap_soc_platform; diff --git a/trunk/sound/soc/omap/sdp3430.c b/trunk/sound/soc/omap/sdp3430.c index 4a3f62d1f295..b719e5db4f57 100644 --- a/trunk/sound/soc/omap/sdp3430.c +++ b/trunk/sound/soc/omap/sdp3430.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -40,11 +39,6 @@ #include "omap-pcm.h" #include "../codecs/twl4030.h" -/* TWL4030 PMBR1 Register */ -#define TWL4030_INTBR_PMBR1 0x0D -/* TWL4030 PMBR1 Register GPIO6 mux bit */ -#define TWL4030_GPIO6_PWM0_MUTE(value) (value << 2) - static struct snd_soc_card snd_soc_sdp3430; static int sdp3430_hw_params(struct snd_pcm_substream *substream, @@ -102,7 +96,7 @@ static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); + SND_SOC_DAIFMT_CBS_CFM); if (ret) { printk(KERN_ERR "can't set codec DAI configuration\n"); return ret; @@ -286,7 +280,6 @@ static struct snd_soc_card snd_soc_sdp3430 = { static struct twl4030_setup_data twl4030_setup = { .ramp_delay_value = 3, .sysclk = 26000, - .hs_extmute = 1, }; /* Audio subsystem */ @@ -301,7 +294,6 @@ static struct platform_device *sdp3430_snd_device; static int __init sdp3430_soc_init(void) { int ret; - u8 pin_mux; if (!machine_is_omap_3430sdp()) { pr_debug("Not SDP3430!\n"); @@ -320,14 +312,6 @@ static int __init sdp3430_soc_init(void) *(unsigned int *)sdp3430_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ *(unsigned int *)sdp3430_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ - /* Set TWL4030 GPIO6 as EXTMUTE signal */ - twl4030_i2c_read_u8(TWL4030_MODULE_INTBR, &pin_mux, - TWL4030_INTBR_PMBR1); - pin_mux &= ~TWL4030_GPIO6_PWM0_MUTE(0x03); - pin_mux |= TWL4030_GPIO6_PWM0_MUTE(0x02); - twl4030_i2c_write_u8(TWL4030_MODULE_INTBR, pin_mux, - TWL4030_INTBR_PMBR1); - ret = platform_device_add(sdp3430_snd_device); if (ret) goto err1; diff --git a/trunk/sound/soc/omap/zoom2.c b/trunk/sound/soc/omap/zoom2.c deleted file mode 100644 index f90b45f56220..000000000000 --- a/trunk/sound/soc/omap/zoom2.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * zoom2.c -- SoC audio for Zoom2 - * - * Author: Misael Lopez Cruz - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "omap-mcbsp.h" -#include "omap-pcm.h" -#include "../codecs/twl4030.h" - -#define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15) -#define ZOOM2_HEADSET_EXTMUTE_GPIO 153 - -static int zoom2_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - int ret; - - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) { - printk(KERN_ERR "can't set codec DAI configuration\n"); - return ret; - } - - /* Set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) { - printk(KERN_ERR "can't set cpu DAI configuration\n"); - return ret; - } - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops zoom2_ops = { - .hw_params = zoom2_hw_params, -}; - -static int zoom2_hw_voice_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - int ret; - - /* Set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret) { - printk(KERN_ERR "can't set codec DAI configuration\n"); - return ret; - } - - /* Set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_DSP_A | - SND_SOC_DAIFMT_IB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) { - printk(KERN_ERR "can't set cpu DAI configuration\n"); - return ret; - } - - /* Set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, - SND_SOC_CLOCK_IN); - if (ret < 0) { - printk(KERN_ERR "can't set codec system clock\n"); - return ret; - } - - return 0; -} - -static struct snd_soc_ops zoom2_voice_ops = { - .hw_params = zoom2_hw_voice_params, -}; - -/* Zoom2 machine DAPM */ -static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = { - SND_SOC_DAPM_MIC("Ext Mic", NULL), - SND_SOC_DAPM_SPK("Ext Spk", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_HP("Headset Stereophone", NULL), - SND_SOC_DAPM_LINE("Aux In", NULL), -}; - -static const struct snd_soc_dapm_route audio_map[] = { - /* External Mics: MAINMIC, SUBMIC with bias*/ - {"MAINMIC", NULL, "Mic Bias 1"}, - {"SUBMIC", NULL, "Mic Bias 2"}, - {"Mic Bias 1", NULL, "Ext Mic"}, - {"Mic Bias 2", NULL, "Ext Mic"}, - - /* External Speakers: HFL, HFR */ - {"Ext Spk", NULL, "HFL"}, - {"Ext Spk", NULL, "HFR"}, - - /* Headset Stereophone: HSOL, HSOR */ - {"Headset Stereophone", NULL, "HSOL"}, - {"Headset Stereophone", NULL, "HSOR"}, - - /* Headset Mic: HSMIC with bias */ - {"HSMIC", NULL, "Headset Mic Bias"}, - {"Headset Mic Bias", NULL, "Headset Mic"}, - - /* Aux In: AUXL, AUXR */ - {"Aux In", NULL, "AUXL"}, - {"Aux In", NULL, "AUXR"}, -}; - -static int zoom2_twl4030_init(struct snd_soc_codec *codec) -{ - int ret; - - /* Add Zoom2 specific widgets */ - ret = snd_soc_dapm_new_controls(codec, zoom2_twl4030_dapm_widgets, - ARRAY_SIZE(zoom2_twl4030_dapm_widgets)); - if (ret) - return ret; - - /* Set up Zoom2 specific audio path audio_map */ - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - - /* Zoom2 connected pins */ - snd_soc_dapm_enable_pin(codec, "Ext Mic"); - snd_soc_dapm_enable_pin(codec, "Ext Spk"); - snd_soc_dapm_enable_pin(codec, "Headset Mic"); - snd_soc_dapm_enable_pin(codec, "Headset Stereophone"); - snd_soc_dapm_enable_pin(codec, "Aux In"); - - /* TWL4030 not connected pins */ - snd_soc_dapm_nc_pin(codec, "CARKITMIC"); - snd_soc_dapm_nc_pin(codec, "DIGIMIC0"); - snd_soc_dapm_nc_pin(codec, "DIGIMIC1"); - - snd_soc_dapm_nc_pin(codec, "OUTL"); - snd_soc_dapm_nc_pin(codec, "OUTR"); - snd_soc_dapm_nc_pin(codec, "EARPIECE"); - snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); - snd_soc_dapm_nc_pin(codec, "PREDRIVER"); - snd_soc_dapm_nc_pin(codec, "CARKITL"); - snd_soc_dapm_nc_pin(codec, "CARKITR"); - - ret = snd_soc_dapm_sync(codec); - - return ret; -} - -static int zoom2_twl4030_voice_init(struct snd_soc_codec *codec) -{ - unsigned short reg; - - /* Enable voice interface */ - reg = codec->read(codec, TWL4030_REG_VOICE_IF); - reg |= TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN; - codec->write(codec, TWL4030_REG_VOICE_IF, reg); - - return 0; -} - -/* Digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link zoom2_dai[] = { - { - .name = "TWL4030 I2S", - .stream_name = "TWL4030 Audio", - .cpu_dai = &omap_mcbsp_dai[0], - .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI], - .init = zoom2_twl4030_init, - .ops = &zoom2_ops, - }, - { - .name = "TWL4030 PCM", - .stream_name = "TWL4030 Voice", - .cpu_dai = &omap_mcbsp_dai[1], - .codec_dai = &twl4030_dai[TWL4030_DAI_VOICE], - .init = zoom2_twl4030_voice_init, - .ops = &zoom2_voice_ops, - }, -}; - -/* Audio machine driver */ -static struct snd_soc_card snd_soc_zoom2 = { - .name = "Zoom2", - .platform = &omap_soc_platform, - .dai_link = zoom2_dai, - .num_links = ARRAY_SIZE(zoom2_dai), -}; - -/* EXTMUTE callback function */ -void zoom2_set_hs_extmute(int mute) -{ - gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); -} - -/* twl4030 setup */ -static struct twl4030_setup_data twl4030_setup = { - .ramp_delay_value = 3, /* 161 ms */ - .sysclk = 26000, - .hs_extmute = 1, - .set_hs_extmute = zoom2_set_hs_extmute, -}; - -/* Audio subsystem */ -static struct snd_soc_device zoom2_snd_devdata = { - .card = &snd_soc_zoom2, - .codec_dev = &soc_codec_dev_twl4030, - .codec_data = &twl4030_setup, -}; - -static struct platform_device *zoom2_snd_device; - -static int __init zoom2_soc_init(void) -{ - int ret; - - if (!machine_is_omap_zoom2()) { - pr_debug("Not Zoom2!\n"); - return -ENODEV; - } - printk(KERN_INFO "Zoom2 SoC init\n"); - - zoom2_snd_device = platform_device_alloc("soc-audio", -1); - if (!zoom2_snd_device) { - printk(KERN_ERR "Platform device allocation failed\n"); - return -ENOMEM; - } - - platform_set_drvdata(zoom2_snd_device, &zoom2_snd_devdata); - zoom2_snd_devdata.dev = &zoom2_snd_device->dev; - *(unsigned int *)zoom2_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ - *(unsigned int *)zoom2_dai[1].cpu_dai->private_data = 2; /* McBSP3 */ - - ret = platform_device_add(zoom2_snd_device); - if (ret) - goto err1; - - BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0); - gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0); - - BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0); - gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0); - - return 0; - -err1: - printk(KERN_ERR "Unable to add platform device\n"); - platform_device_put(zoom2_snd_device); - - return ret; -} -module_init(zoom2_soc_init); - -static void __exit zoom2_soc_exit(void) -{ - gpio_free(ZOOM2_HEADSET_MUX_GPIO); - gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO); - - platform_device_unregister(zoom2_snd_device); -} -module_exit(zoom2_soc_exit); - -MODULE_AUTHOR("Misael Lopez Cruz "); -MODULE_DESCRIPTION("ALSA SoC Zoom2"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/sound/soc/pxa/magician.c b/trunk/sound/soc/pxa/magician.c index 9f7c61e23daf..326955dea36c 100644 --- a/trunk/sound/soc/pxa/magician.c +++ b/trunk/sound/soc/pxa/magician.c @@ -20,14 +20,12 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include @@ -190,7 +188,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 0, 1, width); + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 1, 1); if (ret < 0) return ret; @@ -449,47 +447,34 @@ static struct snd_soc_card snd_soc_card_magician = { .platform = &pxa2xx_soc_platform, }; +/* magician audio private data */ +static struct uda1380_setup_data magician_uda1380_setup = { + .i2c_address = 0x18, + .dac_clk = UDA1380_DAC_CLK_WSPLL, +}; + /* magician audio subsystem */ static struct snd_soc_device magician_snd_devdata = { .card = &snd_soc_card_magician, .codec_dev = &soc_codec_dev_uda1380, + .codec_data = &magician_uda1380_setup, }; static struct platform_device *magician_snd_device; -/* - * FIXME: move into magician board file once merged into the pxa tree - */ -static struct uda1380_platform_data uda1380_info = { - .gpio_power = EGPIO_MAGICIAN_CODEC_POWER, - .gpio_reset = EGPIO_MAGICIAN_CODEC_RESET, - .dac_clk = UDA1380_DAC_CLK_WSPLL, -}; - -static struct i2c_board_info i2c_board_info[] = { - { - I2C_BOARD_INFO("uda1380", 0x18), - .platform_data = &uda1380_info, - }, -}; - static int __init magician_init(void) { int ret; - struct i2c_adapter *adapter; - struct i2c_client *client; if (!machine_is_magician()) return -ENODEV; - adapter = i2c_get_adapter(0); - if (!adapter) - return -ENODEV; - client = i2c_new_device(adapter, i2c_board_info); - i2c_put_adapter(adapter); - if (!client) - return -ENODEV; - + ret = gpio_request(EGPIO_MAGICIAN_CODEC_POWER, "CODEC_POWER"); + if (ret) + goto err_request_power; + ret = gpio_request(EGPIO_MAGICIAN_CODEC_RESET, "CODEC_RESET"); + if (ret) + goto err_request_reset; ret = gpio_request(EGPIO_MAGICIAN_SPK_POWER, "SPK_POWER"); if (ret) goto err_request_spk; @@ -506,8 +491,14 @@ static int __init magician_init(void) if (ret) goto err_request_in_sel1; + gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 1); gpio_set_value(EGPIO_MAGICIAN_IN_SEL0, 0); + /* we may need to have the clock running here - pH5 */ + gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 1); + udelay(5); + gpio_set_value(EGPIO_MAGICIAN_CODEC_RESET, 0); + magician_snd_device = platform_device_alloc("soc-audio", -1); if (!magician_snd_device) { ret = -ENOMEM; @@ -535,6 +526,10 @@ static int __init magician_init(void) err_request_ep: gpio_free(EGPIO_MAGICIAN_SPK_POWER); err_request_spk: + gpio_free(EGPIO_MAGICIAN_CODEC_RESET); +err_request_reset: + gpio_free(EGPIO_MAGICIAN_CODEC_POWER); +err_request_power: return ret; } @@ -545,12 +540,15 @@ static void __exit magician_exit(void) gpio_set_value(EGPIO_MAGICIAN_SPK_POWER, 0); gpio_set_value(EGPIO_MAGICIAN_EP_POWER, 0); gpio_set_value(EGPIO_MAGICIAN_MIC_POWER, 0); + gpio_set_value(EGPIO_MAGICIAN_CODEC_POWER, 0); gpio_free(EGPIO_MAGICIAN_IN_SEL1); gpio_free(EGPIO_MAGICIAN_IN_SEL0); gpio_free(EGPIO_MAGICIAN_MIC_POWER); gpio_free(EGPIO_MAGICIAN_EP_POWER); gpio_free(EGPIO_MAGICIAN_SPK_POWER); + gpio_free(EGPIO_MAGICIAN_CODEC_RESET); + gpio_free(EGPIO_MAGICIAN_CODEC_POWER); } module_init(magician_init); diff --git a/trunk/sound/soc/pxa/palm27x.c b/trunk/sound/soc/pxa/palm27x.c index 1f96e3227be5..e6102fda0a7f 100644 --- a/trunk/sound/soc/pxa/palm27x.c +++ b/trunk/sound/soc/pxa/palm27x.c @@ -17,12 +17,13 @@ #include #include #include +#include +#include #include #include #include #include -#include #include #include @@ -32,31 +33,90 @@ #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" -static struct snd_soc_jack hs_jack; +static int palm27x_jack_func = 1; +static int palm27x_spk_func = 1; +static int palm27x_ep_gpio = -1; -/* Headphones jack detection DAPM pins */ -static struct snd_soc_jack_pin hs_jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, -}; +static void palm27x_ext_control(struct snd_soc_codec *codec) +{ + if (!palm27x_spk_func) + snd_soc_dapm_enable_pin(codec, "Speaker"); + else + snd_soc_dapm_disable_pin(codec, "Speaker"); -/* Headphones jack detection gpios */ -static struct snd_soc_jack_gpio hs_jack_gpios[] = { - [0] = { - /* gpio is set on per-platform basis */ - .name = "hp-gpio", - .report = SND_JACK_HEADPHONE, - .debounce_time = 200, - }, + if (!palm27x_jack_func) + snd_soc_dapm_enable_pin(codec, "Headphone Jack"); + else + snd_soc_dapm_disable_pin(codec, "Headphone Jack"); + + snd_soc_dapm_sync(codec); +} + +static int palm27x_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_codec *codec = rtd->socdev->card->codec; + + /* check the jack status at stream startup */ + palm27x_ext_control(codec); + return 0; +} + +static struct snd_soc_ops palm27x_ops = { + .startup = palm27x_startup, }; -/* Palm27x machine dapm widgets */ +static irqreturn_t palm27x_interrupt(int irq, void *v) +{ + palm27x_spk_func = gpio_get_value(palm27x_ep_gpio); + palm27x_jack_func = !palm27x_spk_func; + return IRQ_HANDLED; +} + +static int palm27x_get_jack(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = palm27x_jack_func; + return 0; +} + +static int palm27x_set_jack(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (palm27x_jack_func == ucontrol->value.integer.value[0]) + return 0; + + palm27x_jack_func = ucontrol->value.integer.value[0]; + palm27x_ext_control(codec); + return 1; +} + +static int palm27x_get_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = palm27x_spk_func; + return 0; +} + +static int palm27x_set_spk(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + + if (palm27x_spk_func == ucontrol->value.integer.value[0]) + return 0; + + palm27x_spk_func = ucontrol->value.integer.value[0]; + palm27x_ext_control(codec); + return 1; +} + +/* PalmTX machine dapm widgets */ static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_SPK("Ext. Speaker", NULL), - SND_SOC_DAPM_MIC("Ext. Microphone", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), }; /* PalmTX audio map */ @@ -66,66 +126,46 @@ static const struct snd_soc_dapm_route audio_map[] = { {"Headphone Jack", NULL, "HPOUTR"}, /* ext speaker connected to ROUT2, LOUT2 */ - {"Ext. Speaker", NULL, "LOUT2"}, - {"Ext. Speaker", NULL, "ROUT2"}, + {"Speaker", NULL, "LOUT2"}, + {"Speaker", NULL, "ROUT2"}, +}; - /* mic connected to MIC1 */ - {"Ext. Microphone", NULL, "MIC1"}, +static const char *jack_function[] = {"Headphone", "Off"}; +static const char *spk_function[] = {"On", "Off"}; +static const struct soc_enum palm27x_enum[] = { + SOC_ENUM_SINGLE_EXT(2, jack_function), + SOC_ENUM_SINGLE_EXT(2, spk_function), }; -static struct snd_soc_card palm27x_asoc; +static const struct snd_kcontrol_new palm27x_controls[] = { + SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack, + palm27x_set_jack), + SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk, + palm27x_set_spk), +}; static int palm27x_ac97_init(struct snd_soc_codec *codec) { int err; - /* add palm27x specific widgets */ - err = snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, - ARRAY_SIZE(palm27x_dapm_widgets)); - if (err) - return err; - - /* set up palm27x specific audio path audio_map */ - err = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - if (err) - return err; - - /* connected pins */ - if (machine_is_palmld()) - snd_soc_dapm_enable_pin(codec, "MIC1"); - snd_soc_dapm_enable_pin(codec, "HPOUTL"); - snd_soc_dapm_enable_pin(codec, "HPOUTR"); - snd_soc_dapm_enable_pin(codec, "LOUT2"); - snd_soc_dapm_enable_pin(codec, "ROUT2"); - - /* not connected pins */ snd_soc_dapm_nc_pin(codec, "OUT3"); snd_soc_dapm_nc_pin(codec, "MONOOUT"); - snd_soc_dapm_nc_pin(codec, "LINEINL"); - snd_soc_dapm_nc_pin(codec, "LINEINR"); - snd_soc_dapm_nc_pin(codec, "PCBEEP"); - snd_soc_dapm_nc_pin(codec, "PHONE"); - snd_soc_dapm_nc_pin(codec, "MIC2"); - - err = snd_soc_dapm_sync(codec); - if (err) - return err; - /* Jack detection API stuff */ - err = snd_soc_jack_new(&palm27x_asoc, "Headphone Jack", - SND_JACK_HEADPHONE, &hs_jack); - if (err) + /* add palm27x specific controls */ + err = snd_soc_add_controls(codec, palm27x_controls, + ARRAY_SIZE(palm27x_controls)); + if (err < 0) return err; - err = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins), - hs_jack_pins); - if (err) - return err; + /* add palm27x specific widgets */ + snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, + ARRAY_SIZE(palm27x_dapm_widgets)); - err = snd_soc_jack_add_gpios(&hs_jack, ARRAY_SIZE(hs_jack_gpios), - hs_jack_gpios); + /* set up palm27x specific audio path audio_map */ + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - return err; + snd_soc_dapm_sync(codec); + return 0; } static struct snd_soc_dai_link palm27x_dai[] = { @@ -135,12 +175,14 @@ static struct snd_soc_dai_link palm27x_dai[] = { .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], .init = palm27x_ac97_init, + .ops = &palm27x_ops, }, { .name = "AC97 Aux", .stream_name = "AC97 Aux", .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], + .ops = &palm27x_ops, }, }; @@ -166,17 +208,27 @@ static int palm27x_asoc_probe(struct platform_device *pdev) machine_is_palmld() || machine_is_palmte2())) return -ENODEV; - if (!pdev->dev.platform_data) { - dev_err(&pdev->dev, "please supply platform_data\n"); - return -ENODEV; - } - - hs_jack_gpios[0].gpio = ((struct palm27x_asoc_info *) + if (pdev->dev.platform_data) + palm27x_ep_gpio = ((struct palm27x_asoc_info *) (pdev->dev.platform_data))->jack_gpio; + ret = gpio_request(palm27x_ep_gpio, "Headphone Jack"); + if (ret) + return ret; + ret = gpio_direction_input(palm27x_ep_gpio); + if (ret) + goto err_alloc; + + if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "Headphone jack", NULL)) + goto err_alloc; + palm27x_snd_device = platform_device_alloc("soc-audio", -1); - if (!palm27x_snd_device) - return -ENOMEM; + if (!palm27x_snd_device) { + ret = -ENOMEM; + goto err_dev; + } platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); palm27x_snd_devdata.dev = &palm27x_snd_device->dev; @@ -189,12 +241,18 @@ static int palm27x_asoc_probe(struct platform_device *pdev) put_device: platform_device_put(palm27x_snd_device); +err_dev: + free_irq(gpio_to_irq(palm27x_ep_gpio), NULL); +err_alloc: + gpio_free(palm27x_ep_gpio); return ret; } static int __devexit palm27x_asoc_remove(struct platform_device *pdev) { + free_irq(gpio_to_irq(palm27x_ep_gpio), NULL); + gpio_free(palm27x_ep_gpio); platform_device_unregister(palm27x_snd_device); return 0; } diff --git a/trunk/sound/soc/pxa/pxa-ssp.c b/trunk/sound/soc/pxa/pxa-ssp.c index 5b9ed6464789..19c45409d94c 100644 --- a/trunk/sound/soc/pxa/pxa-ssp.c +++ b/trunk/sound/soc/pxa/pxa-ssp.c @@ -375,34 +375,21 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, * Set the active slots in TDM/Network mode */ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, - unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) + unsigned int mask, int slots) { struct ssp_priv *priv = cpu_dai->private_data; struct ssp_device *ssp = priv->dev.ssp; u32 sscr0; - sscr0 = ssp_read_reg(ssp, SSCR0); - sscr0 &= ~(SSCR0_MOD | SSCR0_SlotsPerFrm(8) | SSCR0_EDSS | SSCR0_DSS); - - /* set slot width */ - if (slot_width > 16) - sscr0 |= SSCR0_EDSS | SSCR0_DataSize(slot_width - 16); - else - sscr0 |= SSCR0_DataSize(slot_width); - - if (slots > 1) { - /* enable network mode */ - sscr0 |= SSCR0_MOD; + sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7); - /* set number of active slots */ - sscr0 |= SSCR0_SlotsPerFrm(slots); - - /* set active slot mask */ - ssp_write_reg(ssp, SSTSA, tx_mask); - ssp_write_reg(ssp, SSRSA, rx_mask); - } + /* set number of active slots */ + sscr0 |= SSCR0_SlotsPerFrm(slots); ssp_write_reg(ssp, SSCR0, sscr0); + /* set active slot mask */ + ssp_write_reg(ssp, SSTSA, mask); + ssp_write_reg(ssp, SSRSA, mask); return 0; } @@ -470,27 +457,31 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, return -EINVAL; } - switch (fmt & SND_SOC_DAIFMT_INV_MASK) { - case SND_SOC_DAIFMT_NB_NF: - sspsp |= SSPSP_SFRMP; - break; - case SND_SOC_DAIFMT_NB_IF: - break; - case SND_SOC_DAIFMT_IB_IF: - sspsp |= SSPSP_SCMODE(2); - break; - case SND_SOC_DAIFMT_IB_NF: - sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP; - break; - default: - return -EINVAL; - } + ssp_write_reg(ssp, SSCR0, sscr0); + ssp_write_reg(ssp, SSCR1, sscr1); + ssp_write_reg(ssp, SSPSP, sspsp); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: sscr0 |= SSCR0_PSP; sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; + /* See hw_params() */ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + sspsp |= SSPSP_SFRMP; + break; + case SND_SOC_DAIFMT_NB_IF: + break; + case SND_SOC_DAIFMT_IB_IF: + sspsp |= SSPSP_SCMODE(2); + break; + case SND_SOC_DAIFMT_IB_NF: + sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP; + break; + default: + return -EINVAL; + } break; case SND_SOC_DAIFMT_DSP_A: @@ -498,6 +489,22 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_DSP_B: sscr0 |= SSCR0_MOD | SSCR0_PSP; sscr1 |= SSCR1_TRAIL | SSCR1_RWOT; + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + sspsp |= SSPSP_SFRMP; + break; + case SND_SOC_DAIFMT_NB_IF: + break; + case SND_SOC_DAIFMT_IB_IF: + sspsp |= SSPSP_SCMODE(2); + break; + case SND_SOC_DAIFMT_IB_NF: + sspsp |= SSPSP_SCMODE(2) | SSPSP_SFRMP; + break; + default: + return -EINVAL; + } break; default: diff --git a/trunk/sound/soc/pxa/pxa2xx-ac97.c b/trunk/sound/soc/pxa/pxa2xx-ac97.c index e9ae7b3a7e00..d9c94d71fa61 100644 --- a/trunk/sound/soc/pxa/pxa2xx-ac97.c +++ b/trunk/sound/soc/pxa/pxa2xx-ac97.c @@ -22,7 +22,6 @@ #include #include #include -#include #include "pxa2xx-pcm.h" #include "pxa2xx-ac97.h" @@ -242,18 +241,9 @@ EXPORT_SYMBOL_GPL(soc_ac97_ops); static int __devinit pxa2xx_ac97_dev_probe(struct platform_device *pdev) { int i; - pxa2xx_audio_ops_t *pdata = pdev->dev.platform_data; - if (pdev->id >= 0) { - dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); - return -ENXIO; - } - - for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) { + for (i = 0; i < ARRAY_SIZE(pxa_ac97_dai); i++) pxa_ac97_dai[i].dev = &pdev->dev; - if (pdata && pdata->codec_pdata[0]) - pxa_ac97_dai[i].ac97_pdata = pdata->codec_pdata[0]; - } /* Punt most of the init to the SoC probe; we may need the machine * driver to do interesting things with the clocking to get us up diff --git a/trunk/sound/soc/s3c24xx/Kconfig b/trunk/sound/soc/s3c24xx/Kconfig index 923428fc1adb..df494d1e346f 100644 --- a/trunk/sound/soc/s3c24xx/Kconfig +++ b/trunk/sound/soc/s3c24xx/Kconfig @@ -1,7 +1,6 @@ config SND_S3C24XX_SOC tristate "SoC Audio for the Samsung S3CXXXX chips" - depends on ARCH_S3C2410 || ARCH_S3C64XX - select S3C64XX_DMA if ARCH_S3C64XX + depends on ARCH_S3C2410 help Say Y or M if you want to add support for codecs attached to the S3C24XX AC97 or I2S interfaces. You will also need to @@ -39,15 +38,6 @@ config SND_S3C24XX_SOC_NEO1973_WM8753 Say Y if you want to add support for SoC audio on smdk2440 with the WM8753. -config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753 - tristate "Audio support for the Openmoko Neo FreeRunner (GTA02)" - depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02 - select SND_S3C24XX_SOC_I2S - select SND_SOC_WM8753 - help - This driver provides audio support for the Openmoko Neo FreeRunner - smartphone. - config SND_S3C24XX_SOC_JIVE_WM8750 tristate "SoC I2S Audio support for Jive" depends on SND_S3C24XX_SOC && MACH_JIVE @@ -67,7 +57,7 @@ config SND_S3C24XX_SOC_SMDK2443_WM9710 config SND_S3C24XX_SOC_LN2440SBC_ALC650 tristate "SoC AC97 Audio support for LN2440SBC - ALC650" - depends on SND_S3C24XX_SOC && ARCH_S3C2410 + depends on SND_S3C24XX_SOC select SND_S3C2443_SOC_AC97 select SND_SOC_AC97_CODEC help @@ -76,26 +66,7 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650 config SND_S3C24XX_SOC_S3C24XX_UDA134X tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" - depends on SND_S3C24XX_SOC && ARCH_S3C2410 + depends on SND_S3C24XX_SOC select SND_S3C24XX_SOC_I2S select SND_SOC_L3 select SND_SOC_UDA134X - -config SND_S3C24XX_SOC_SIMTEC - tristate - help - Internal node for common S3C24XX/Simtec suppor - -config SND_S3C24XX_SOC_SIMTEC_TLV320AIC23 - tristate "SoC I2S Audio support for TLV320AIC23 on Simtec boards" - depends on SND_S3C24XX_SOC && ARCH_S3C2410 - select SND_S3C24XX_SOC_I2S - select SND_SOC_TLV320AIC23 - select SND_S3C24XX_SOC_SIMTEC - -config SND_S3C24XX_SOC_SIMTEC_HERMES - tristate "SoC I2S Audio support for Simtec Hermes board" - depends on SND_S3C24XX_SOC && ARCH_S3C2410 - select SND_S3C24XX_SOC_I2S - select SND_SOC_TLV320AIC3X - select SND_S3C24XX_SOC_SIMTEC diff --git a/trunk/sound/soc/s3c24xx/Makefile b/trunk/sound/soc/s3c24xx/Makefile index 99f5a7dd3fc6..07a93a2ebe5f 100644 --- a/trunk/sound/soc/s3c24xx/Makefile +++ b/trunk/sound/soc/s3c24xx/Makefile @@ -16,21 +16,12 @@ obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o # S3C24XX Machine Support snd-soc-jive-wm8750-objs := jive_wm8750.o snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o -snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o -snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o -snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o -snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o -obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o -obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o -obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o -obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o - diff --git a/trunk/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/trunk/sound/soc/s3c24xx/neo1973_gta02_wm8753.c deleted file mode 100644 index 0c52e36ddd87..000000000000 --- a/trunk/sound/soc/s3c24xx/neo1973_gta02_wm8753.c +++ /dev/null @@ -1,498 +0,0 @@ -/* - * neo1973_gta02_wm8753.c -- SoC audio for Openmoko Freerunner(GTA02) - * - * Copyright 2007 Openmoko Inc - * Author: Graeme Gregory - * Copyright 2007 Wolfson Microelectronics PLC. - * Author: Graeme Gregory - * Copyright 2009 Wolfson Microelectronics - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include -#include -#include -#include "../codecs/wm8753.h" -#include "s3c24xx-pcm.h" -#include "s3c24xx-i2s.h" - -static struct snd_soc_card neo1973_gta02; - -static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - unsigned int pll_out = 0, bclk = 0; - int ret = 0; - unsigned long iis_clkrate; - - iis_clkrate = s3c24xx_i2s_get_clockrate(); - - switch (params_rate(params)) { - case 8000: - case 16000: - pll_out = 12288000; - break; - case 48000: - bclk = WM8753_BCLK_DIV_4; - pll_out = 12288000; - break; - case 96000: - bclk = WM8753_BCLK_DIV_2; - pll_out = 12288000; - break; - case 11025: - bclk = WM8753_BCLK_DIV_16; - pll_out = 11289600; - break; - case 22050: - bclk = WM8753_BCLK_DIV_8; - pll_out = 11289600; - break; - case 44100: - bclk = WM8753_BCLK_DIV_4; - pll_out = 11289600; - break; - case 88200: - bclk = WM8753_BCLK_DIV_2; - pll_out = 11289600; - break; - } - - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set cpu DAI configuration */ - ret = snd_soc_dai_set_fmt(cpu_dai, - SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret < 0) - return ret; - - /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out, - SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - /* set MCLK division for sample rate */ - ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, - S3C2410_IISMOD_32FS); - if (ret < 0) - return ret; - - /* set codec BCLK division for sample rate */ - ret = snd_soc_dai_set_clkdiv(codec_dai, - WM8753_BCLKDIV, bclk); - if (ret < 0) - return ret; - - /* set prescaler division for sample rate */ - ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, - S3C24XX_PRESCALE(4, 4)); - if (ret < 0) - return ret; - - /* codec PLL input is PCLK/4 */ - ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, - iis_clkrate / 4, pll_out); - if (ret < 0) - return ret; - - return 0; -} - -static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - - /* disable the PLL */ - return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); -} - -/* - * Neo1973 WM8753 HiFi DAI opserations. - */ -static struct snd_soc_ops neo1973_gta02_hifi_ops = { - .hw_params = neo1973_gta02_hifi_hw_params, - .hw_free = neo1973_gta02_hifi_hw_free, -}; - -static int neo1973_gta02_voice_hw_params( - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - unsigned int pcmdiv = 0; - int ret = 0; - unsigned long iis_clkrate; - - iis_clkrate = s3c24xx_i2s_get_clockrate(); - - if (params_rate(params) != 8000) - return -EINVAL; - if (params_channels(params) != 1) - return -EINVAL; - - pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ - - /* todo: gg check mode (DSP_B) against CSR datasheet */ - /* set codec DAI configuration */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); - if (ret < 0) - return ret; - - /* set the codec system clock for DAC and ADC */ - ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK, - 12288000, SND_SOC_CLOCK_IN); - if (ret < 0) - return ret; - - /* set codec PCM division for sample rate */ - ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, - pcmdiv); - if (ret < 0) - return ret; - - /* configue and enable PLL for 12.288MHz output */ - ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, - iis_clkrate / 4, 12288000); - if (ret < 0) - return ret; - - return 0; -} - -static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - - /* disable the PLL */ - return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); -} - -static struct snd_soc_ops neo1973_gta02_voice_ops = { - .hw_params = neo1973_gta02_voice_hw_params, - .hw_free = neo1973_gta02_voice_hw_free, -}; - -#define LM4853_AMP 1 -#define LM4853_SPK 2 - -static u8 lm4853_state; - -/* This has no effect, it exists only to maintain compatibility with - * existing ALSA state files. - */ -static int lm4853_set_state(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int val = ucontrol->value.integer.value[0]; - - if (val) - lm4853_state |= LM4853_AMP; - else - lm4853_state &= ~LM4853_AMP; - - return 0; -} - -static int lm4853_get_state(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP; - - return 0; -} - -static int lm4853_set_spk(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int val = ucontrol->value.integer.value[0]; - - if (val) { - lm4853_state |= LM4853_SPK; - gpio_set_value(GTA02_GPIO_HP_IN, 0); - } else { - lm4853_state &= ~LM4853_SPK; - gpio_set_value(GTA02_GPIO_HP_IN, 1); - } - - return 0; -} - -static int lm4853_get_spk(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1; - - return 0; -} - -static int lm4853_event(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *k, - int event) -{ - gpio_set_value(GTA02_GPIO_AMP_SHUT, SND_SOC_DAPM_EVENT_OFF(value)); - - return 0; -} - -static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { - SND_SOC_DAPM_SPK("Stereo Out", lm4853_event), - SND_SOC_DAPM_LINE("GSM Line Out", NULL), - SND_SOC_DAPM_LINE("GSM Line In", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("Handset Mic", NULL), - SND_SOC_DAPM_SPK("Handset Spk", NULL), -}; - - -/* example machine audio_mapnections */ -static const struct snd_soc_dapm_route audio_map[] = { - - /* Connections to the lm4853 amp */ - {"Stereo Out", NULL, "LOUT1"}, - {"Stereo Out", NULL, "ROUT1"}, - - /* Connections to the GSM Module */ - {"GSM Line Out", NULL, "MONO1"}, - {"GSM Line Out", NULL, "MONO2"}, - {"RXP", NULL, "GSM Line In"}, - {"RXN", NULL, "GSM Line In"}, - - /* Connections to Headset */ - {"MIC1", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Headset Mic"}, - - /* Call Mic */ - {"MIC2", NULL, "Mic Bias"}, - {"MIC2N", NULL, "Mic Bias"}, - {"Mic Bias", NULL, "Handset Mic"}, - - /* Call Speaker */ - {"Handset Spk", NULL, "LOUT2"}, - {"Handset Spk", NULL, "ROUT2"}, - - /* Connect the ALC pins */ - {"ACIN", NULL, "ACOP"}, -}; - -static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = { - SOC_DAPM_PIN_SWITCH("Stereo Out"), - SOC_DAPM_PIN_SWITCH("GSM Line Out"), - SOC_DAPM_PIN_SWITCH("GSM Line In"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Handset Mic"), - SOC_DAPM_PIN_SWITCH("Handset Spk"), - - /* This has no effect, it exists only to maintain compatibility with - * existing ALSA state files. - */ - SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0, - lm4853_get_state, - lm4853_set_state), - SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0, - lm4853_get_spk, - lm4853_set_spk), -}; - -/* - * This is an example machine initialisation for a wm8753 connected to a - * neo1973 GTA02. - */ -static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec) -{ - int err; - - /* set up NC codec pins */ - snd_soc_dapm_nc_pin(codec, "OUT3"); - snd_soc_dapm_nc_pin(codec, "OUT4"); - snd_soc_dapm_nc_pin(codec, "LINE1"); - snd_soc_dapm_nc_pin(codec, "LINE2"); - - /* Add neo1973 gta02 specific widgets */ - snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets, - ARRAY_SIZE(wm8753_dapm_widgets)); - - /* add neo1973 gta02 specific controls */ - err = snd_soc_add_controls(codec, wm8753_neo1973_gta02_controls, - ARRAY_SIZE(wm8753_neo1973_gta02_controls)); - - if (err < 0) - return err; - - /* set up neo1973 gta02 specific audio path audio_map */ - snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); - - /* set endpoints to default off mode */ - snd_soc_dapm_disable_pin(codec, "Stereo Out"); - snd_soc_dapm_disable_pin(codec, "GSM Line Out"); - snd_soc_dapm_disable_pin(codec, "GSM Line In"); - snd_soc_dapm_disable_pin(codec, "Headset Mic"); - snd_soc_dapm_disable_pin(codec, "Handset Mic"); - snd_soc_dapm_disable_pin(codec, "Handset Spk"); - - snd_soc_dapm_sync(codec); - - return 0; -} - -/* - * BT Codec DAI - */ -static struct snd_soc_dai bt_dai = { - .name = "Bluetooth", - .id = 0, - .playback = { - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, - .capture = { - .channels_min = 1, - .channels_max = 1, - .rates = SNDRV_PCM_RATE_8000, - .formats = SNDRV_PCM_FMTBIT_S16_LE,}, -}; - -static struct snd_soc_dai_link neo1973_gta02_dai[] = { -{ /* Hifi Playback - for similatious use with voice below */ - .name = "WM8753", - .stream_name = "WM8753 HiFi", - .cpu_dai = &s3c24xx_i2s_dai, - .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], - .init = neo1973_gta02_wm8753_init, - .ops = &neo1973_gta02_hifi_ops, -}, -{ /* Voice via BT */ - .name = "Bluetooth", - .stream_name = "Voice", - .cpu_dai = &bt_dai, - .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], - .ops = &neo1973_gta02_voice_ops, -}, -}; - -static struct snd_soc_card neo1973_gta02 = { - .name = "neo1973-gta02", - .platform = &s3c24xx_soc_platform, - .dai_link = neo1973_gta02_dai, - .num_links = ARRAY_SIZE(neo1973_gta02_dai), -}; - -static struct snd_soc_device neo1973_gta02_snd_devdata = { - .card = &neo1973_gta02, - .codec_dev = &soc_codec_dev_wm8753, -}; - -static struct platform_device *neo1973_gta02_snd_device; - -static int __init neo1973_gta02_init(void) -{ - int ret; - - if (!machine_is_neo1973_gta02()) { - printk(KERN_INFO - "Only GTA02 is supported by this ASoC driver\n"); - return -ENODEV; - } - - /* register bluetooth DAI here */ - ret = snd_soc_register_dai(&bt_dai); - if (ret) - return ret; - - neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1); - if (!neo1973_gta02_snd_device) - return -ENOMEM; - - platform_set_drvdata(neo1973_gta02_snd_device, - &neo1973_gta02_snd_devdata); - neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev; - ret = platform_device_add(neo1973_gta02_snd_device); - - if (ret) { - platform_device_put(neo1973_gta02_snd_device); - return ret; - } - - /* Initialise GPIOs used by amp */ - ret = gpio_request(GTA02_GPIO_HP_IN, "GTA02_HP_IN"); - if (ret) { - pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_HP_IN); - goto err_unregister_device; - } - - ret = gpio_direction_output(GTA02_GPIO_AMP_HP_IN, 1); - if (ret) { - pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_HP_IN); - goto err_free_gpio_hp_in; - } - - ret = gpio_request(GTA02_GPIO_AMP_SHUT, "GTA02_AMP_SHUT"); - if (ret) { - pr_err("gta02_wm8753: Failed to register GPIO %d\n", GTA02_GPIO_AMP_SHUT); - goto err_free_gpio_hp_in; - } - - ret = gpio_direction_output(GTA02_GPIO_AMP_SHUT, 1); - if (ret) { - pr_err("gta02_wm8753: Failed to configure GPIO %d\n", GTA02_GPIO_AMP_SHUT); - goto err_free_gpio_amp_shut; - } - - return 0; - -err_free_gpio_amp_shut: - gpio_free(GTA02_GPIO_AMP_SHUT); -err_free_gpio_hp_in: - gpio_free(GTA02_GPIO_HP_IN); -err_unregister_device: - platform_device_unregister(neo1973_gta02_snd_device); - return ret; -} -module_init(neo1973_gta02_init); - -static void __exit neo1973_gta02_exit(void) -{ - snd_soc_unregister_dai(&bt_dai); - platform_device_unregister(neo1973_gta02_snd_device); - gpio_free(GTA02_GPIO_HP_IN); - gpio_free(GTA02_GPIO_AMP_SHUT); -} -module_exit(neo1973_gta02_exit); - -/* Module information */ -MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org"); -MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/s3c24xx/s3c-i2s-v2.c b/trunk/sound/soc/s3c24xx/s3c-i2s-v2.c index aa7af0b8d421..1a283170ca92 100644 --- a/trunk/sound/soc/s3c24xx/s3c-i2s-v2.c +++ b/trunk/sound/soc/s3c24xx/s3c-i2s-v2.c @@ -36,7 +36,6 @@ #include #include "s3c-i2s-v2.h" -#include "s3c24xx-pcm.h" #undef S3C_IIS_V2_SUPPORTED @@ -358,19 +357,19 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, #endif #ifdef CONFIG_PLAT_S3C64XX - iismod &= ~(S3C64XX_IISMOD_BLC_MASK | S3C2412_IISMOD_BCLK_MASK); + iismod &= ~0x606; /* Sample size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: /* 8 bit sample, 16fs BCLK */ - iismod |= (S3C64XX_IISMOD_BLC_8BIT | S3C2412_IISMOD_BCLK_16FS); + iismod |= 0x2004; break; case SNDRV_PCM_FORMAT_S16_LE: /* 16 bit sample, 32fs BCLK */ break; case SNDRV_PCM_FORMAT_S24_LE: /* 24 bit sample, 48fs BCLK */ - iismod |= (S3C64XX_IISMOD_BLC_24BIT | S3C2412_IISMOD_BCLK_48FS); + iismod |= 0x4002; break; } #endif @@ -388,8 +387,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); unsigned long irqs; int ret = 0; - int channel = ((struct s3c24xx_pcm_dma_params *) - rtd->dai->cpu_dai->dma_data)->channel; pr_debug("Entered %s\n", __func__); @@ -419,14 +416,6 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, s3c2412_snd_txctrl(i2s, 1); local_irq_restore(irqs); - - /* - * Load the next buffer to DMA to meet the reqirement - * of the auto reload mechanism of S3C24XX. - * This call won't bother S3C64XX. - */ - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); - break; case SNDRV_PCM_TRIGGER_STOP: diff --git a/trunk/sound/soc/s3c24xx/s3c2443-ac97.c b/trunk/sound/soc/s3c24xx/s3c2443-ac97.c index fc1beb0930b9..3f03d5ddfacd 100644 --- a/trunk/sound/soc/s3c24xx/s3c2443-ac97.c +++ b/trunk/sound/soc/s3c24xx/s3c2443-ac97.c @@ -47,7 +47,7 @@ static struct s3c24xx_ac97_info s3c24xx_ac97; static DECLARE_COMPLETION(ac97_completion); static u32 codec_ready; -static DEFINE_MUTEX(ac97_mutex); +static DECLARE_MUTEX(ac97_mutex); static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97, unsigned short reg) @@ -56,7 +56,7 @@ static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97, u32 ac_codec_cmd; u32 stat, addr, data; - mutex_lock(&ac97_mutex); + down(&ac97_mutex); codec_ready = S3C_AC97_GLBSTAT_CODECREADY; ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); @@ -79,7 +79,7 @@ static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97, printk(KERN_ERR "s3c24xx-ac97: req addr = %02x," " rep addr = %02x\n", reg, addr); - mutex_unlock(&ac97_mutex); + up(&ac97_mutex); return (unsigned short)data; } @@ -90,7 +90,7 @@ static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg, u32 ac_glbctrl; u32 ac_codec_cmd; - mutex_lock(&ac97_mutex); + down(&ac97_mutex); codec_ready = S3C_AC97_GLBSTAT_CODECREADY; ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); @@ -109,7 +109,7 @@ static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg, ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); - mutex_unlock(&ac97_mutex); + up(&ac97_mutex); } @@ -290,9 +290,6 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { u32 ac_glbctrl; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - int channel = ((struct s3c24xx_pcm_dma_params *) - rtd->dai->cpu_dai->dma_data)->channel; ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); switch (cmd) { @@ -315,8 +312,6 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd, } writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); - return 0; } @@ -339,9 +334,6 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { u32 ac_glbctrl; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - int channel = ((struct s3c24xx_pcm_dma_params *) - rtd->dai->cpu_dai->dma_data)->channel; ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); switch (cmd) { @@ -357,8 +349,6 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, } writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); - return 0; } diff --git a/trunk/sound/soc/s3c24xx/s3c24xx-i2s.c b/trunk/sound/soc/s3c24xx/s3c24xx-i2s.c index 40e2c4790f0d..556e35f0ab73 100644 --- a/trunk/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/trunk/sound/soc/s3c24xx/s3c24xx-i2s.c @@ -279,9 +279,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; - int channel = ((struct s3c24xx_pcm_dma_params *) - rtd->dai->cpu_dai->dma_data)->channel; pr_debug("Entered %s\n", __func__); @@ -299,8 +296,6 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, s3c24xx_snd_rxctrl(1); else s3c24xx_snd_txctrl(1); - - s3c2410_dma_ctrl(channel, S3C2410_DMAOP_STARTED); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: diff --git a/trunk/sound/soc/s3c24xx/s3c24xx-pcm.c b/trunk/sound/soc/s3c24xx/s3c24xx-pcm.c index 5cbbdc80fde3..eecfa5eba06b 100644 --- a/trunk/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/trunk/sound/soc/s3c24xx/s3c24xx-pcm.c @@ -255,6 +255,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->state |= ST_RUNNING; s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START); + s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STARTED); break; case SNDRV_PCM_TRIGGER_STOP: @@ -317,7 +318,6 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream) pr_debug("Entered %s\n", __func__); - snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL); diff --git a/trunk/sound/soc/s3c24xx/s3c24xx_simtec.c b/trunk/sound/soc/s3c24xx/s3c24xx_simtec.c deleted file mode 100644 index 1966e0d5652d..000000000000 --- a/trunk/sound/soc/s3c24xx/s3c24xx_simtec.c +++ /dev/null @@ -1,394 +0,0 @@ -/* sound/soc/s3c24xx/s3c24xx_simtec.c - * - * Copyright 2009 Simtec Electronics - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "s3c24xx-pcm.h" -#include "s3c24xx-i2s.h" -#include "s3c24xx_simtec.h" - -static struct s3c24xx_audio_simtec_pdata *pdata; -static struct clk *xtal_clk; - -static int spk_gain; -static int spk_unmute; - -/** - * speaker_gain_get - read the speaker gain setting. - * @kcontrol: The control for the speaker gain. - * @ucontrol: The value that needs to be updated. - * - * Read the value for the AMP gain control. - */ -static int speaker_gain_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = spk_gain; - return 0; -} - -/** - * speaker_gain_set - set the value of the speaker amp gain - * @value: The value to write. - */ -static void speaker_gain_set(int value) -{ - gpio_set_value_cansleep(pdata->amp_gain[0], value & 1); - gpio_set_value_cansleep(pdata->amp_gain[1], value >> 1); -} - -/** - * speaker_gain_put - set the speaker gain setting. - * @kcontrol: The control for the speaker gain. - * @ucontrol: The value that needs to be set. - * - * Set the value of the speaker gain from the specified - * @ucontrol setting. - * - * Note, if the speaker amp is muted, then we do not set a gain value - * as at-least one of the ICs that is fitted will try and power up even - * if the main control is set to off. - */ -static int speaker_gain_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int value = ucontrol->value.integer.value[0]; - - spk_gain = value; - - if (!spk_unmute) - speaker_gain_set(value); - - return 0; -} - -static const struct snd_kcontrol_new amp_gain_controls[] = { - SOC_SINGLE_EXT("Speaker Gain", 0, 0, 3, 0, - speaker_gain_get, speaker_gain_put), -}; - -/** - * spk_unmute_state - set the unmute state of the speaker - * @to: zero to unmute, non-zero to ununmute. - */ -static void spk_unmute_state(int to) -{ - pr_debug("%s: to=%d\n", __func__, to); - - spk_unmute = to; - gpio_set_value(pdata->amp_gpio, to); - - /* if we're umuting, also re-set the gain */ - if (to && pdata->amp_gain[0] > 0) - speaker_gain_set(spk_gain); -} - -/** - * speaker_unmute_get - read the speaker unmute setting. - * @kcontrol: The control for the speaker gain. - * @ucontrol: The value that needs to be updated. - * - * Read the value for the AMP gain control. - */ -static int speaker_unmute_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - ucontrol->value.integer.value[0] = spk_unmute; - return 0; -} - -/** - * speaker_unmute_put - set the speaker unmute setting. - * @kcontrol: The control for the speaker gain. - * @ucontrol: The value that needs to be set. - * - * Set the value of the speaker gain from the specified - * @ucontrol setting. - */ -static int speaker_unmute_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - spk_unmute_state(ucontrol->value.integer.value[0]); - return 0; -} - -/* This is added as a manual control as the speaker amps create clicks - * when their power state is changed, which are far more noticeable than - * anything produced by the CODEC itself. - */ -static const struct snd_kcontrol_new amp_unmute_controls[] = { - SOC_SINGLE_EXT("Speaker Switch", 0, 0, 1, 0, - speaker_unmute_get, speaker_unmute_put), -}; - -void simtec_audio_init(struct snd_soc_codec *codec) -{ - if (pdata->amp_gpio > 0) { - pr_debug("%s: adding amp routes\n", __func__); - - snd_soc_add_controls(codec, amp_unmute_controls, - ARRAY_SIZE(amp_unmute_controls)); - } - - if (pdata->amp_gain[0] > 0) { - pr_debug("%s: adding amp controls\n", __func__); - snd_soc_add_controls(codec, amp_gain_controls, - ARRAY_SIZE(amp_gain_controls)); - } -} -EXPORT_SYMBOL_GPL(simtec_audio_init); - -#define CODEC_CLOCK 12000000 - -/** - * simtec_hw_params - update hardware parameters - * @substream: The audio substream instance. - * @params: The parameters requested. - * - * Update the codec data routing and configuration settings - * from the supplied data. - */ -static int simtec_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; - struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; - int ret; - - /* Set the CODEC as the bus clock master, I2S */ - ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret) { - pr_err("%s: failed set cpu dai format\n", __func__); - return ret; - } - - /* Set the CODEC as the bus clock master */ - ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBM_CFM); - if (ret) { - pr_err("%s: failed set codec dai format\n", __func__); - return ret; - } - - ret = snd_soc_dai_set_sysclk(codec_dai, 0, - CODEC_CLOCK, SND_SOC_CLOCK_IN); - if (ret) { - pr_err( "%s: failed setting codec sysclk\n", __func__); - return ret; - } - - if (pdata->use_mpllin) { - ret = snd_soc_dai_set_sysclk(cpu_dai, S3C24XX_CLKSRC_MPLL, - 0, SND_SOC_CLOCK_OUT); - - if (ret) { - pr_err("%s: failed to set MPLLin as clksrc\n", - __func__); - return ret; - } - } - - if (pdata->output_cdclk) { - int cdclk_scale; - - cdclk_scale = clk_get_rate(xtal_clk) / CODEC_CLOCK; - cdclk_scale--; - - ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, - cdclk_scale); - } - - return 0; -} - -static int simtec_call_startup(struct s3c24xx_audio_simtec_pdata *pd) -{ - /* call any board supplied startup code, this currently only - * covers the bast/vr1000 which have a CPLD in the way of the - * LRCLK */ - if (pd->startup) - pd->startup(); - - return 0; -} - -static struct snd_soc_ops simtec_snd_ops = { - .hw_params = simtec_hw_params, -}; - -/** - * attach_gpio_amp - get and configure the necessary gpios - * @dev: The device we're probing. - * @pd: The platform data supplied by the board. - * - * If there is a GPIO based amplifier attached to the board, claim - * the necessary GPIO lines for it, and set default values. - */ -static int attach_gpio_amp(struct device *dev, - struct s3c24xx_audio_simtec_pdata *pd) -{ - int ret; - - /* attach gpio amp gain (if any) */ - if (pdata->amp_gain[0] > 0) { - ret = gpio_request(pd->amp_gain[0], "gpio-amp-gain0"); - if (ret) { - dev_err(dev, "cannot get amp gpio gain0\n"); - return ret; - } - - ret = gpio_request(pd->amp_gain[1], "gpio-amp-gain1"); - if (ret) { - dev_err(dev, "cannot get amp gpio gain1\n"); - gpio_free(pdata->amp_gain[0]); - return ret; - } - - gpio_direction_output(pd->amp_gain[0], 0); - gpio_direction_output(pd->amp_gain[1], 0); - } - - /* note, curently we assume GPA0 isn't valid amp */ - if (pdata->amp_gpio > 0) { - ret = gpio_request(pd->amp_gpio, "gpio-amp"); - if (ret) { - dev_err(dev, "cannot get amp gpio %d (%d)\n", - pd->amp_gpio, ret); - goto err_amp; - } - - /* set the amp off at startup */ - spk_unmute_state(0); - } - - return 0; - -err_amp: - if (pd->amp_gain[0] > 0) { - gpio_free(pd->amp_gain[0]); - gpio_free(pd->amp_gain[1]); - } - - return ret; -} - -static void detach_gpio_amp(struct s3c24xx_audio_simtec_pdata *pd) -{ - if (pd->amp_gain[0] > 0) { - gpio_free(pd->amp_gain[0]); - gpio_free(pd->amp_gain[1]); - } - - if (pd->amp_gpio > 0) - gpio_free(pd->amp_gpio); -} - -#ifdef CONFIG_PM -int simtec_audio_resume(struct device *dev) -{ - simtec_call_startup(pdata); - return 0; -} - -struct dev_pm_ops simtec_audio_pmops = { - .resume = simtec_audio_resume, -}; -EXPORT_SYMBOL_GPL(simtec_audio_pmops); -#endif - -int __devinit simtec_audio_core_probe(struct platform_device *pdev, - struct snd_soc_device *socdev) -{ - struct platform_device *snd_dev; - int ret; - - socdev->card->dai_link->ops = &simtec_snd_ops; - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "no platform data supplied\n"); - return -EINVAL; - } - - simtec_call_startup(pdata); - - xtal_clk = clk_get(&pdev->dev, "xtal"); - if (IS_ERR(xtal_clk)) { - dev_err(&pdev->dev, "could not get clkout0\n"); - return -EINVAL; - } - - dev_info(&pdev->dev, "xtal rate is %ld\n", clk_get_rate(xtal_clk)); - - ret = attach_gpio_amp(&pdev->dev, pdata); - if (ret) - goto err_clk; - - snd_dev = platform_device_alloc("soc-audio", -1); - if (!snd_dev) { - dev_err(&pdev->dev, "failed to alloc soc-audio devicec\n"); - ret = -ENOMEM; - goto err_gpio; - } - - platform_set_drvdata(snd_dev, socdev); - socdev->dev = &snd_dev->dev; - - ret = platform_device_add(snd_dev); - if (ret) { - dev_err(&pdev->dev, "failed to add soc-audio dev\n"); - goto err_pdev; - } - - platform_set_drvdata(pdev, snd_dev); - return 0; - -err_pdev: - platform_device_put(snd_dev); - -err_gpio: - detach_gpio_amp(pdata); - -err_clk: - clk_put(xtal_clk); - return ret; -} -EXPORT_SYMBOL_GPL(simtec_audio_core_probe); - -int __devexit simtec_audio_remove(struct platform_device *pdev) -{ - struct platform_device *snd_dev = platform_get_drvdata(pdev); - - platform_device_unregister(snd_dev); - - detach_gpio_amp(pdata); - clk_put(xtal_clk); - return 0; -} -EXPORT_SYMBOL_GPL(simtec_audio_remove); - -MODULE_AUTHOR("Ben Dooks "); -MODULE_DESCRIPTION("ALSA SoC Simtec Audio common support"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/s3c24xx/s3c24xx_simtec.h b/trunk/sound/soc/s3c24xx/s3c24xx_simtec.h deleted file mode 100644 index 2714203af161..000000000000 --- a/trunk/sound/soc/s3c24xx/s3c24xx_simtec.h +++ /dev/null @@ -1,22 +0,0 @@ -/* sound/soc/s3c24xx/s3c24xx_simtec.h - * - * Copyright 2009 Simtec Electronics - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -extern void simtec_audio_init(struct snd_soc_codec *codec); - -extern int simtec_audio_core_probe(struct platform_device *pdev, - struct snd_soc_device *socdev); - -extern int simtec_audio_remove(struct platform_device *pdev); - -#ifdef CONFIG_PM -extern struct dev_pm_ops simtec_audio_pmops; -#define simtec_audio_pm &simtec_audio_pmops -#else -#define simtec_audio_pm NULL -#endif diff --git a/trunk/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/trunk/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c deleted file mode 100644 index 8346bd96eaf5..000000000000 --- a/trunk/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c +++ /dev/null @@ -1,153 +0,0 @@ -/* sound/soc/s3c24xx/s3c24xx_simtec_hermes.c - * - * Copyright 2009 Simtec Electronics - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "s3c24xx-pcm.h" -#include "s3c24xx-i2s.h" -#include "s3c24xx_simtec.h" - -#include "../codecs/tlv320aic3x.h" - -static const struct snd_soc_dapm_widget dapm_widgets[] = { - SND_SOC_DAPM_LINE("GSM Out", NULL), - SND_SOC_DAPM_LINE("GSM In", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_LINE("ZV", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), -}; - -static const struct snd_soc_dapm_route base_map[] = { - /* Headphone connected to HP{L,R}OUT and HP{L,R}COM */ - - { "Headphone Jack", NULL, "HPLOUT" }, - { "Headphone Jack", NULL, "HPLCOM" }, - { "Headphone Jack", NULL, "HPROUT" }, - { "Headphone Jack", NULL, "HPRCOM" }, - - /* ZV connected to Line1 */ - - { "LINE1L", NULL, "ZV" }, - { "LINE1R", NULL, "ZV" }, - - /* Line In connected to Line2 */ - - { "LINE2L", NULL, "Line In" }, - { "LINE2R", NULL, "Line In" }, - - /* Microphone connected to MIC3R and MIC_BIAS */ - - { "MIC3L", NULL, "Mic Jack" }, - - /* GSM connected to MONO_LOUT and MIC3L (in) */ - - { "GSM Out", NULL, "MONO_LOUT" }, - { "MIC3L", NULL, "GSM In" }, - - /* Speaker is connected to LINEOUT{LN,LP,RN,RP}, however we are - * not using the DAPM to power it up and down as there it makes - * a click when powering up. */ -}; - -/** - * simtec_hermes_init - initialise and add controls - * @codec; The codec instance to attach to. - * - * Attach our controls and configure the necessary codec - * mappings for our sound card instance. -*/ -static int simtec_hermes_init(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, dapm_widgets, - ARRAY_SIZE(dapm_widgets)); - - snd_soc_dapm_add_routes(codec, base_map, ARRAY_SIZE(base_map)); - - snd_soc_dapm_enable_pin(codec, "Headphone Jack"); - snd_soc_dapm_enable_pin(codec, "Line In"); - snd_soc_dapm_enable_pin(codec, "Line Out"); - snd_soc_dapm_enable_pin(codec, "Mic Jack"); - - simtec_audio_init(codec); - snd_soc_dapm_sync(codec); - - return 0; -} - -static struct aic3x_setup_data codec_setup = { -}; - -static struct snd_soc_dai_link simtec_dai_aic33 = { - .name = "tlv320aic33", - .stream_name = "TLV320AIC33", - .cpu_dai = &s3c24xx_i2s_dai, - .codec_dai = &aic3x_dai, - .init = simtec_hermes_init, -}; - -/* simtec audio machine driver */ -static struct snd_soc_card snd_soc_machine_simtec_aic33 = { - .name = "Simtec-Hermes", - .platform = &s3c24xx_soc_platform, - .dai_link = &simtec_dai_aic33, - .num_links = 1, -}; - -/* simtec audio subsystem */ -static struct snd_soc_device simtec_snd_devdata_aic33 = { - .card = &snd_soc_machine_simtec_aic33, - .codec_dev = &soc_codec_dev_aic3x, - .codec_data = &codec_setup, -}; - -static int __devinit simtec_audio_hermes_probe(struct platform_device *pd) -{ - dev_info(&pd->dev, "probing....\n"); - return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic33); -} - -static struct platform_driver simtec_audio_hermes_platdrv = { - .driver = { - .owner = THIS_MODULE, - .name = "s3c24xx-simtec-hermes-snd", - .pm = simtec_audio_pm, - }, - .probe = simtec_audio_hermes_probe, - .remove = __devexit_p(simtec_audio_remove), -}; - -MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd"); - -static int __init simtec_hermes_modinit(void) -{ - return platform_driver_register(&simtec_audio_hermes_platdrv); -} - -static void __exit simtec_hermes_modexit(void) -{ - platform_driver_unregister(&simtec_audio_hermes_platdrv); -} - -module_init(simtec_hermes_modinit); -module_exit(simtec_hermes_modexit); - -MODULE_AUTHOR("Ben Dooks "); -MODULE_DESCRIPTION("ALSA SoC Simtec Audio support"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/trunk/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c deleted file mode 100644 index 25797e096175..000000000000 --- a/trunk/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c +++ /dev/null @@ -1,137 +0,0 @@ -/* sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c - * - * Copyright 2009 Simtec Electronics - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. -*/ - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "s3c24xx-pcm.h" -#include "s3c24xx-i2s.h" -#include "s3c24xx_simtec.h" - -#include "../codecs/tlv320aic23.h" - -/* supported machines: - * - * Machine Connections AMP - * ------- ----------- --- - * BAST MIC, HPOUT, LOUT, LIN TPA2001D1 (HPOUTL,R) (gain hardwired) - * VR1000 HPOUT, LIN None - * VR2000 LIN, LOUT, MIC, HP LM4871 (HPOUTL,R) - * DePicture LIN, LOUT, MIC, HP LM4871 (HPOUTL,R) - * Anubis LIN, LOUT, MIC, HP TPA2001D1 (HPOUTL,R) - */ - -static const struct snd_soc_dapm_widget dapm_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_LINE("Line In", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_MIC("Mic Jack", NULL), -}; - -static const struct snd_soc_dapm_route base_map[] = { - { "Headphone Jack", NULL, "LHPOUT"}, - { "Headphone Jack", NULL, "RHPOUT"}, - - { "Line Out", NULL, "LOUT" }, - { "Line Out", NULL, "ROUT" }, - - { "LLINEIN", NULL, "Line In"}, - { "RLINEIN", NULL, "Line In"}, - - { "MICIN", NULL, "Mic Jack"}, -}; - -/** - * simtec_tlv320aic23_init - initialise and add controls - * @codec; The codec instance to attach to. - * - * Attach our controls and configure the necessary codec - * mappings for our sound card instance. -*/ -static int simtec_tlv320aic23_init(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, dapm_widgets, - ARRAY_SIZE(dapm_widgets)); - - snd_soc_dapm_add_routes(codec, base_map, ARRAY_SIZE(base_map)); - - snd_soc_dapm_enable_pin(codec, "Headphone Jack"); - snd_soc_dapm_enable_pin(codec, "Line In"); - snd_soc_dapm_enable_pin(codec, "Line Out"); - snd_soc_dapm_enable_pin(codec, "Mic Jack"); - - simtec_audio_init(codec); - snd_soc_dapm_sync(codec); - - return 0; -} - -static struct snd_soc_dai_link simtec_dai_aic23 = { - .name = "tlv320aic23", - .stream_name = "TLV320AIC23", - .cpu_dai = &s3c24xx_i2s_dai, - .codec_dai = &tlv320aic23_dai, - .init = simtec_tlv320aic23_init, -}; - -/* simtec audio machine driver */ -static struct snd_soc_card snd_soc_machine_simtec_aic23 = { - .name = "Simtec", - .platform = &s3c24xx_soc_platform, - .dai_link = &simtec_dai_aic23, - .num_links = 1, -}; - -/* simtec audio subsystem */ -static struct snd_soc_device simtec_snd_devdata_aic23 = { - .card = &snd_soc_machine_simtec_aic23, - .codec_dev = &soc_codec_dev_tlv320aic23, -}; - -static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd) -{ - return simtec_audio_core_probe(pd, &simtec_snd_devdata_aic23); -} - -static struct platform_driver simtec_audio_tlv320aic23_platdrv = { - .driver = { - .owner = THIS_MODULE, - .name = "s3c24xx-simtec-tlv320aic23", - .pm = simtec_audio_pm, - }, - .probe = simtec_audio_tlv320aic23_probe, - .remove = __devexit_p(simtec_audio_remove), -}; - -MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23"); - -static int __init simtec_tlv320aic23_modinit(void) -{ - return platform_driver_register(&simtec_audio_tlv320aic23_platdrv); -} - -static void __exit simtec_tlv320aic23_modexit(void) -{ - platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv); -} - -module_init(simtec_tlv320aic23_modinit); -module_exit(simtec_tlv320aic23_modexit); - -MODULE_AUTHOR("Ben Dooks "); -MODULE_DESCRIPTION("ALSA SoC Simtec Audio support"); -MODULE_LICENSE("GPL"); diff --git a/trunk/sound/soc/s6000/s6105-ipcam.c b/trunk/sound/soc/s6000/s6105-ipcam.c index c1b40ac22c05..b5f95f9781c1 100644 --- a/trunk/sound/soc/s6000/s6105-ipcam.c +++ b/trunk/sound/soc/s6000/s6105-ipcam.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -190,6 +189,8 @@ static struct snd_soc_card snd_soc_card_s6105 = { /* s6105 audio private data */ static struct aic3x_setup_data s6105_aic3x_setup = { + .i2c_bus = 0, + .i2c_address = 0x18, }; /* s6105 audio subsystem */ @@ -210,19 +211,10 @@ static struct s6000_snd_platform_data __initdata s6105_snd_data = { static struct platform_device *s6105_snd_device; -/* temporary i2c device creation until this can be moved into the machine - * support file. -*/ -static struct i2c_board_info i2c_device[] = { - { I2C_BOARD_INFO("tlv320aic33", 0x18), } -}; - static int __init s6105_init(void) { int ret; - i2c_register_board_info(0, i2c_device, ARRAY_SIZE(i2c_device)); - s6105_snd_device = platform_device_alloc("soc-audio", -1); if (!s6105_snd_device) return -ENOMEM; diff --git a/trunk/sound/soc/sh/Kconfig b/trunk/sound/soc/sh/Kconfig index 9154b4363db3..54bd604012af 100644 --- a/trunk/sound/soc/sh/Kconfig +++ b/trunk/sound/soc/sh/Kconfig @@ -20,12 +20,7 @@ config SND_SOC_SH4_HAC config SND_SOC_SH4_SSI tristate -config SND_SOC_SH4_FSI - tristate "SH4 FSI support" - depends on CPU_SUBTYPE_SH7724 - select SH_DMA - help - This option enables FSI sound support + ## ## Boards @@ -40,12 +35,4 @@ config SND_SH7760_AC97 This option enables generic sound support for the first AC97 unit of the SH7760. -config SND_FSI_AK4642 - bool "FSI-AK4642 sound support" - depends on SND_SOC_SH4_FSI - select SND_SOC_AK4642 - help - This option enables generic sound support for the - FSI - AK4642 unit - endmenu diff --git a/trunk/sound/soc/sh/Makefile b/trunk/sound/soc/sh/Makefile index a6997872f24e..a8e8ab81cc6a 100644 --- a/trunk/sound/soc/sh/Makefile +++ b/trunk/sound/soc/sh/Makefile @@ -5,14 +5,10 @@ obj-$(CONFIG_SND_SOC_PCM_SH7760) += snd-soc-dma-sh7760.o ## audio units found on some SH-4 snd-soc-hac-objs := hac.o snd-soc-ssi-objs := ssi.o -snd-soc-fsi-objs := fsi.o obj-$(CONFIG_SND_SOC_SH4_HAC) += snd-soc-hac.o obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o -obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o ## boards snd-soc-sh7760-ac97-objs := sh7760-ac97.o -snd-soc-fsi-ak4642-objs := fsi-ak4642.o obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o -obj-$(CONFIG_SND_FSI_AK4642) += snd-soc-fsi-ak4642.o diff --git a/trunk/sound/soc/sh/fsi-ak4642.c b/trunk/sound/soc/sh/fsi-ak4642.c deleted file mode 100644 index c7af09729c6e..000000000000 --- a/trunk/sound/soc/sh/fsi-ak4642.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * FSI-AK464x sound support for ms7724se - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include <../sound/soc/codecs/ak4642.h> - -static struct snd_soc_dai_link fsi_dai_link = { - .name = "AK4642", - .stream_name = "AK4642", - .cpu_dai = &fsi_soc_dai[0], /* fsi */ - .codec_dai = &ak4642_dai, - .ops = NULL, -}; - -static struct snd_soc_card fsi_soc_card = { - .name = "FSI", - .platform = &fsi_soc_platform, - .dai_link = &fsi_dai_link, - .num_links = 1, -}; - -static struct snd_soc_device fsi_snd_devdata = { - .card = &fsi_soc_card, - .codec_dev = &soc_codec_dev_ak4642, -}; - -#define AK4642_BUS 0 -#define AK4642_ADR 0x12 -static int ak4642_add_i2c_device(void) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter; - struct i2c_client *client; - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = AK4642_ADR; - strlcpy(info.type, "ak4642", I2C_NAME_SIZE); - - adapter = i2c_get_adapter(AK4642_BUS); - if (!adapter) { - printk(KERN_DEBUG "can't get i2c adapter\n"); - return -ENODEV; - } - - client = i2c_new_device(adapter, &info); - i2c_put_adapter(adapter); - if (!client) { - printk(KERN_DEBUG "can't add i2c device\n"); - return -ENODEV; - } - - return 0; -} - -static struct platform_device *fsi_snd_device; - -static int __init fsi_ak4642_init(void) -{ - int ret = -ENOMEM; - - ak4642_add_i2c_device(); - - fsi_snd_device = platform_device_alloc("soc-audio", -1); - if (!fsi_snd_device) - goto out; - - platform_set_drvdata(fsi_snd_device, - &fsi_snd_devdata); - fsi_snd_devdata.dev = &fsi_snd_device->dev; - ret = platform_device_add(fsi_snd_device); - - if (ret) - platform_device_put(fsi_snd_device); - -out: - return ret; -} - -static void __exit fsi_ak4642_exit(void) -{ - platform_device_unregister(fsi_snd_device); -} - -module_init(fsi_ak4642_init); -module_exit(fsi_ak4642_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card"); -MODULE_AUTHOR("Kuninori Morimoto "); diff --git a/trunk/sound/soc/sh/fsi.c b/trunk/sound/soc/sh/fsi.c deleted file mode 100644 index 44123248b630..000000000000 --- a/trunk/sound/soc/sh/fsi.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * Fifo-attached Serial Interface (FSI) support for SH7724 - * - * Copyright (C) 2009 Renesas Solutions Corp. - * Kuninori Morimoto - * - * Based on ssi.c - * Copyright (c) 2007 Manuel Lauss - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DO_FMT 0x0000 -#define DOFF_CTL 0x0004 -#define DOFF_ST 0x0008 -#define DI_FMT 0x000C -#define DIFF_CTL 0x0010 -#define DIFF_ST 0x0014 -#define CKG1 0x0018 -#define CKG2 0x001C -#define DIDT 0x0020 -#define DODT 0x0024 -#define MUTE_ST 0x0028 -#define REG_END MUTE_ST - -#define INT_ST 0x0200 -#define IEMSK 0x0204 -#define IMSK 0x0208 -#define MUTE 0x020C -#define CLK_RST 0x0210 -#define SOFT_RST 0x0214 -#define MREG_START INT_ST -#define MREG_END SOFT_RST - -/* DO_FMT */ -/* DI_FMT */ -#define CR_FMT(param) ((param) << 4) -# define CR_MONO 0x0 -# define CR_MONO_D 0x1 -# define CR_PCM 0x2 -# define CR_I2S 0x3 -# define CR_TDM 0x4 -# define CR_TDM_D 0x5 - -/* DOFF_CTL */ -/* DIFF_CTL */ -#define IRQ_HALF 0x00100000 -#define FIFO_CLR 0x00000001 - -/* DOFF_ST */ -#define ERR_OVER 0x00000010 -#define ERR_UNDER 0x00000001 - -/* CLK_RST */ -#define B_CLK 0x00000010 -#define A_CLK 0x00000001 - -/* INT_ST */ -#define INT_B_IN (1 << 12) -#define INT_B_OUT (1 << 8) -#define INT_A_IN (1 << 4) -#define INT_A_OUT (1 << 0) - -#define FSI_RATES SNDRV_PCM_RATE_8000_96000 - -#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) - -/************************************************************************ - - - struct - - -************************************************************************/ -struct fsi_priv { - void __iomem *base; - struct snd_pcm_substream *substream; - - int fifo_max; - int chan; - int dma_chan; - - int byte_offset; - int period_len; - int buffer_len; - int periods; -}; - -struct fsi_master { - void __iomem *base; - int irq; - struct clk *clk; - struct fsi_priv fsia; - struct fsi_priv fsib; - struct sh_fsi_platform_info *info; -}; - -static struct fsi_master *master; - -/************************************************************************ - - - basic read write function - - -************************************************************************/ -static int __fsi_reg_write(u32 reg, u32 data) -{ - /* valid data area is 24bit */ - data &= 0x00ffffff; - - return ctrl_outl(data, reg); -} - -static u32 __fsi_reg_read(u32 reg) -{ - return ctrl_inl(reg); -} - -static int __fsi_reg_mask_set(u32 reg, u32 mask, u32 data) -{ - u32 val = __fsi_reg_read(reg); - - val &= ~mask; - val |= data & mask; - - return __fsi_reg_write(reg, val); -} - -static int fsi_reg_write(struct fsi_priv *fsi, u32 reg, u32 data) -{ - if (reg > REG_END) - return -1; - - return __fsi_reg_write((u32)(fsi->base + reg), data); -} - -static u32 fsi_reg_read(struct fsi_priv *fsi, u32 reg) -{ - if (reg > REG_END) - return 0; - - return __fsi_reg_read((u32)(fsi->base + reg)); -} - -static int fsi_reg_mask_set(struct fsi_priv *fsi, u32 reg, u32 mask, u32 data) -{ - if (reg > REG_END) - return -1; - - return __fsi_reg_mask_set((u32)(fsi->base + reg), mask, data); -} - -static int fsi_master_write(u32 reg, u32 data) -{ - if ((reg < MREG_START) || - (reg > MREG_END)) - return -1; - - return __fsi_reg_write((u32)(master->base + reg), data); -} - -static u32 fsi_master_read(u32 reg) -{ - if ((reg < MREG_START) || - (reg > MREG_END)) - return 0; - - return __fsi_reg_read((u32)(master->base + reg)); -} - -static int fsi_master_mask_set(u32 reg, u32 mask, u32 data) -{ - if ((reg < MREG_START) || - (reg > MREG_END)) - return -1; - - return __fsi_reg_mask_set((u32)(master->base + reg), mask, data); -} - -/************************************************************************ - - - basic function - - -************************************************************************/ -static struct fsi_priv *fsi_get(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd; - struct fsi_priv *fsi = NULL; - - if (!substream || !master) - return NULL; - - rtd = substream->private_data; - switch (rtd->dai->cpu_dai->id) { - case 0: - fsi = &master->fsia; - break; - case 1: - fsi = &master->fsib; - break; - } - - return fsi; -} - -static int fsi_is_port_a(struct fsi_priv *fsi) -{ - /* return - * 1 : port a - * 0 : port b - */ - - if (fsi == &master->fsia) - return 1; - - return 0; -} - -static u32 fsi_get_info_flags(struct fsi_priv *fsi) -{ - int is_porta = fsi_is_port_a(fsi); - - return is_porta ? master->info->porta_flags : - master->info->portb_flags; -} - -static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play) -{ - u32 mode; - u32 flags = fsi_get_info_flags(fsi); - - mode = is_play ? SH_FSI_OUT_SLAVE_MODE : SH_FSI_IN_SLAVE_MODE; - - /* return - * 1 : master mode - * 0 : slave mode - */ - - return (mode & flags) != mode; -} - -static u32 fsi_port_ab_io_bit(struct fsi_priv *fsi, int is_play) -{ - int is_porta = fsi_is_port_a(fsi); - u32 data; - - if (is_porta) - data = is_play ? (1 << 0) : (1 << 4); - else - data = is_play ? (1 << 8) : (1 << 12); - - return data; -} - -static void fsi_stream_push(struct fsi_priv *fsi, - struct snd_pcm_substream *substream, - u32 buffer_len, - u32 period_len) -{ - fsi->substream = substream; - fsi->buffer_len = buffer_len; - fsi->period_len = period_len; - fsi->byte_offset = 0; - fsi->periods = 0; -} - -static void fsi_stream_pop(struct fsi_priv *fsi) -{ - fsi->substream = NULL; - fsi->buffer_len = 0; - fsi->period_len = 0; - fsi->byte_offset = 0; - fsi->periods = 0; -} - -static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play) -{ - u32 status; - u32 reg = is_play ? DOFF_ST : DIFF_ST; - int residue; - - status = fsi_reg_read(fsi, reg); - residue = 0x1ff & (status >> 8); - residue *= fsi->chan; - - return residue; -} - -static int fsi_get_residue(struct fsi_priv *fsi, int is_play) -{ - int residue; - int width; - struct snd_pcm_runtime *runtime; - - runtime = fsi->substream->runtime; - - /* get 1 channel data width */ - width = frames_to_bytes(runtime, 1) / fsi->chan; - - if (2 == width) - residue = fsi_get_fifo_residue(fsi, is_play); - else - residue = get_dma_residue(fsi->dma_chan); - - return residue; -} - -/************************************************************************ - - - basic dma function - - -************************************************************************/ -#define PORTA_DMA 0 -#define PORTB_DMA 1 - -static int fsi_get_dma_chan(void) -{ - if (0 != request_dma(PORTA_DMA, "fsia")) - return -EIO; - - if (0 != request_dma(PORTB_DMA, "fsib")) { - free_dma(PORTA_DMA); - return -EIO; - } - - master->fsia.dma_chan = PORTA_DMA; - master->fsib.dma_chan = PORTB_DMA; - - return 0; -} - -static void fsi_free_dma_chan(void) -{ - dma_wait_for_completion(PORTA_DMA); - dma_wait_for_completion(PORTB_DMA); - free_dma(PORTA_DMA); - free_dma(PORTB_DMA); - - master->fsia.dma_chan = -1; - master->fsib.dma_chan = -1; -} - -/************************************************************************ - - - ctrl function - - -************************************************************************/ -static void fsi_irq_enable(struct fsi_priv *fsi, int is_play) -{ - u32 data = fsi_port_ab_io_bit(fsi, is_play); - - fsi_master_mask_set(IMSK, data, data); - fsi_master_mask_set(IEMSK, data, data); -} - -static void fsi_irq_disable(struct fsi_priv *fsi, int is_play) -{ - u32 data = fsi_port_ab_io_bit(fsi, is_play); - - fsi_master_mask_set(IMSK, data, 0); - fsi_master_mask_set(IEMSK, data, 0); -} - -static void fsi_clk_ctrl(struct fsi_priv *fsi, int enable) -{ - u32 val = fsi_is_port_a(fsi) ? (1 << 0) : (1 << 4); - - if (enable) - fsi_master_mask_set(CLK_RST, val, val); - else - fsi_master_mask_set(CLK_RST, val, 0); -} - -static void fsi_irq_init(struct fsi_priv *fsi, int is_play) -{ - u32 data; - u32 ctrl; - - data = fsi_port_ab_io_bit(fsi, is_play); - ctrl = is_play ? DOFF_CTL : DIFF_CTL; - - /* set IMSK */ - fsi_irq_disable(fsi, is_play); - - /* set interrupt generation factor */ - fsi_reg_write(fsi, ctrl, IRQ_HALF); - - /* clear FIFO */ - fsi_reg_mask_set(fsi, ctrl, FIFO_CLR, FIFO_CLR); - - /* clear interrupt factor */ - fsi_master_mask_set(INT_ST, data, 0); -} - -static void fsi_soft_all_reset(void) -{ - u32 status = fsi_master_read(SOFT_RST); - - /* port AB reset */ - status &= 0x000000ff; - fsi_master_write(SOFT_RST, status); - mdelay(10); - - /* soft reset */ - status &= 0x000000f0; - fsi_master_write(SOFT_RST, status); - status |= 0x00000001; - fsi_master_write(SOFT_RST, status); - mdelay(10); -} - -static void fsi_16data_push(struct fsi_priv *fsi, - struct snd_pcm_runtime *runtime, - int send) -{ - u16 *dma_start; - u32 snd; - int i; - - /* get dma start position for FSI */ - dma_start = (u16 *)runtime->dma_area; - dma_start += fsi->byte_offset / 2; - - /* - * soft dma - * FSI can not use DMA when 16bpp - */ - for (i = 0; i < send; i++) { - snd = (u32)dma_start[i]; - fsi_reg_write(fsi, DODT, snd << 8); - } -} - -static void fsi_32data_push(struct fsi_priv *fsi, - struct snd_pcm_runtime *runtime, - int send) -{ - u32 *dma_start; - - /* get dma start position for FSI */ - dma_start = (u32 *)runtime->dma_area; - dma_start += fsi->byte_offset / 4; - - dma_wait_for_completion(fsi->dma_chan); - dma_configure_channel(fsi->dma_chan, (SM_INC|0x400|TS_32|TM_BUR)); - dma_write(fsi->dma_chan, (u32)dma_start, - (u32)(fsi->base + DODT), send * 4); -} - -/* playback interrupt */ -static int fsi_data_push(struct fsi_priv *fsi) -{ - struct snd_pcm_runtime *runtime; - struct snd_pcm_substream *substream = NULL; - int send; - int fifo_free; - int width; - - if (!fsi || - !fsi->substream || - !fsi->substream->runtime) - return -EINVAL; - - runtime = fsi->substream->runtime; - - /* FSI FIFO has limit. - * So, this driver can not send periods data at a time - */ - if (fsi->byte_offset >= - fsi->period_len * (fsi->periods + 1)) { - - substream = fsi->substream; - fsi->periods = (fsi->periods + 1) % runtime->periods; - - if (0 == fsi->periods) - fsi->byte_offset = 0; - } - - /* get 1 channel data width */ - width = frames_to_bytes(runtime, 1) / fsi->chan; - - /* get send size for alsa */ - send = (fsi->buffer_len - fsi->byte_offset) / width; - - /* get FIFO free size */ - fifo_free = (fsi->fifo_max * fsi->chan) - fsi_get_fifo_residue(fsi, 1); - - /* size check */ - if (fifo_free < send) - send = fifo_free; - - if (2 == width) - fsi_16data_push(fsi, runtime, send); - else if (4 == width) - fsi_32data_push(fsi, runtime, send); - else - return -EINVAL; - - fsi->byte_offset += send * width; - - fsi_irq_enable(fsi, 1); - - if (substream) - snd_pcm_period_elapsed(substream); - - return 0; -} - -static irqreturn_t fsi_interrupt(int irq, void *data) -{ - u32 status = fsi_master_read(SOFT_RST) & ~0x00000010; - u32 int_st = fsi_master_read(INT_ST); - - /* clear irq status */ - fsi_master_write(SOFT_RST, status); - fsi_master_write(SOFT_RST, status | 0x00000010); - - if (int_st & INT_A_OUT) - fsi_data_push(&master->fsia); - if (int_st & INT_B_OUT) - fsi_data_push(&master->fsib); - - fsi_master_write(INT_ST, 0x0000000); - - return IRQ_HANDLED; -} - -/************************************************************************ - - - dai ops - - -************************************************************************/ -static int fsi_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct fsi_priv *fsi = fsi_get(substream); - const char *msg; - u32 flags = fsi_get_info_flags(fsi); - u32 fmt; - u32 reg; - u32 data; - int is_play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - int is_master; - int ret = 0; - - clk_enable(master->clk); - - /* CKG1 */ - data = is_play ? (1 << 0) : (1 << 4); - is_master = fsi_is_master_mode(fsi, is_play); - if (is_master) - fsi_reg_mask_set(fsi, CKG1, data, data); - else - fsi_reg_mask_set(fsi, CKG1, data, 0); - - /* clock inversion (CKG2) */ - data = 0; - switch (SH_FSI_INVERSION_MASK & flags) { - case SH_FSI_LRM_INV: - data = 1 << 12; - break; - case SH_FSI_BRM_INV: - data = 1 << 8; - break; - case SH_FSI_LRS_INV: - data = 1 << 4; - break; - case SH_FSI_BRS_INV: - data = 1 << 0; - break; - } - fsi_reg_write(fsi, CKG2, data); - - /* do fmt, di fmt */ - data = 0; - reg = is_play ? DO_FMT : DI_FMT; - fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); - switch (fmt) { - case SH_FSI_FMT_MONO: - msg = "MONO"; - data = CR_FMT(CR_MONO); - fsi->chan = 1; - break; - case SH_FSI_FMT_MONO_DELAY: - msg = "MONO Delay"; - data = CR_FMT(CR_MONO_D); - fsi->chan = 1; - break; - case SH_FSI_FMT_PCM: - msg = "PCM"; - data = CR_FMT(CR_PCM); - fsi->chan = 2; - break; - case SH_FSI_FMT_I2S: - msg = "I2S"; - data = CR_FMT(CR_I2S); - fsi->chan = 2; - break; - case SH_FSI_FMT_TDM: - msg = "TDM"; - data = CR_FMT(CR_TDM) | (fsi->chan - 1); - fsi->chan = is_play ? - SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); - break; - case SH_FSI_FMT_TDM_DELAY: - msg = "TDM Delay"; - data = CR_FMT(CR_TDM_D) | (fsi->chan - 1); - fsi->chan = is_play ? - SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); - break; - default: - dev_err(dai->dev, "unknown format.\n"); - return -EINVAL; - } - - switch (fsi->chan) { - case 1: - fsi->fifo_max = 256; - break; - case 2: - fsi->fifo_max = 128; - break; - case 3: - case 4: - fsi->fifo_max = 64; - break; - case 5: - case 6: - case 7: - case 8: - fsi->fifo_max = 32; - break; - default: - dev_err(dai->dev, "channel size error.\n"); - return -EINVAL; - } - - fsi_reg_write(fsi, reg, data); - dev_dbg(dai->dev, "use %s format (%d channel) use %d DMAC\n", - msg, fsi->chan, fsi->dma_chan); - - /* - * clear clk reset if master mode - */ - if (is_master) - fsi_clk_ctrl(fsi, 1); - - /* irq setting */ - fsi_irq_init(fsi, is_play); - - return ret; -} - -static void fsi_dai_shutdown(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) -{ - struct fsi_priv *fsi = fsi_get(substream); - int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - - fsi_irq_disable(fsi, is_play); - fsi_clk_ctrl(fsi, 0); - - clk_disable(master->clk); -} - -static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, - struct snd_soc_dai *dai) -{ - struct fsi_priv *fsi = fsi_get(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - int ret = 0; - - /* capture not supported */ - if (!is_play) - return -ENODEV; - - switch (cmd) { - case SNDRV_PCM_TRIGGER_START: - fsi_stream_push(fsi, substream, - frames_to_bytes(runtime, runtime->buffer_size), - frames_to_bytes(runtime, runtime->period_size)); - ret = fsi_data_push(fsi); - break; - case SNDRV_PCM_TRIGGER_STOP: - fsi_irq_disable(fsi, is_play); - fsi_stream_pop(fsi); - break; - } - - return ret; -} - -static struct snd_soc_dai_ops fsi_dai_ops = { - .startup = fsi_dai_startup, - .shutdown = fsi_dai_shutdown, - .trigger = fsi_dai_trigger, -}; - -/************************************************************************ - - - pcm ops - - -************************************************************************/ -static struct snd_pcm_hardware fsi_pcm_hardware = { - .info = SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE, - .formats = FSI_FMTS, - .rates = FSI_RATES, - .rate_min = 8000, - .rate_max = 192000, - .channels_min = 1, - .channels_max = 2, - .buffer_bytes_max = 64 * 1024, - .period_bytes_min = 32, - .period_bytes_max = 8192, - .periods_min = 1, - .periods_max = 32, - .fifo_size = 256, -}; - -static int fsi_pcm_open(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - int ret = 0; - - snd_soc_set_runtime_hwparams(substream, &fsi_pcm_hardware); - - ret = snd_pcm_hw_constraint_integer(runtime, - SNDRV_PCM_HW_PARAM_PERIODS); - - return ret; -} - -static int fsi_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *hw_params) -{ - return snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params)); -} - -static int fsi_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - -static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - struct fsi_priv *fsi = fsi_get(substream); - int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - long location; - - location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play); - if (location < 0) - location = 0; - - return bytes_to_frames(runtime, location); -} - -static struct snd_pcm_ops fsi_pcm_ops = { - .open = fsi_pcm_open, - .ioctl = snd_pcm_lib_ioctl, - .hw_params = fsi_hw_params, - .hw_free = fsi_hw_free, - .pointer = fsi_pointer, -}; - -/************************************************************************ - - - snd_soc_platform - - -************************************************************************/ -#define PREALLOC_BUFFER (32 * 1024) -#define PREALLOC_BUFFER_MAX (32 * 1024) - -static void fsi_pcm_free(struct snd_pcm *pcm) -{ - snd_pcm_lib_preallocate_free_for_all(pcm); -} - -static int fsi_pcm_new(struct snd_card *card, - struct snd_soc_dai *dai, - struct snd_pcm *pcm) -{ - /* - * dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel - * in MMAP mode (i.e. aplay -M) - */ - return snd_pcm_lib_preallocate_pages_for_all( - pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_KERNEL), - PREALLOC_BUFFER, PREALLOC_BUFFER_MAX); -} - -/************************************************************************ - - - alsa struct - - -************************************************************************/ -struct snd_soc_dai fsi_soc_dai[] = { - { - .name = "FSIA", - .id = 0, - .playback = { - .rates = FSI_RATES, - .formats = FSI_FMTS, - .channels_min = 1, - .channels_max = 8, - }, - /* capture not supported */ - .ops = &fsi_dai_ops, - }, - { - .name = "FSIB", - .id = 1, - .playback = { - .rates = FSI_RATES, - .formats = FSI_FMTS, - .channels_min = 1, - .channels_max = 8, - }, - /* capture not supported */ - .ops = &fsi_dai_ops, - }, -}; -EXPORT_SYMBOL_GPL(fsi_soc_dai); - -struct snd_soc_platform fsi_soc_platform = { - .name = "fsi-pcm", - .pcm_ops = &fsi_pcm_ops, - .pcm_new = fsi_pcm_new, - .pcm_free = fsi_pcm_free, -}; -EXPORT_SYMBOL_GPL(fsi_soc_platform); - -/************************************************************************ - - - platform function - - -************************************************************************/ -static int fsi_probe(struct platform_device *pdev) -{ - struct resource *res; - char clk_name[8]; - unsigned int irq; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - if (!res || !irq) { - dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); - ret = -ENODEV; - goto exit; - } - - master = kzalloc(sizeof(*master), GFP_KERNEL); - if (!master) { - dev_err(&pdev->dev, "Could not allocate master\n"); - ret = -ENOMEM; - goto exit; - } - - master->base = ioremap_nocache(res->start, resource_size(res)); - if (!master->base) { - ret = -ENXIO; - dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); - goto exit_kfree; - } - - master->irq = irq; - master->info = pdev->dev.platform_data; - master->fsia.base = master->base; - master->fsib.base = master->base + 0x40; - - master->fsia.dma_chan = -1; - master->fsib.dma_chan = -1; - - ret = fsi_get_dma_chan(); - if (ret < 0) { - dev_err(&pdev->dev, "cannot get dma api\n"); - goto exit_iounmap; - } - - /* FSI is based on SPU mstp */ - snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id); - master->clk = clk_get(NULL, clk_name); - if (IS_ERR(master->clk)) { - dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name); - ret = -EIO; - goto exit_free_dma; - } - - fsi_soc_dai[0].dev = &pdev->dev; - fsi_soc_dai[1].dev = &pdev->dev; - - fsi_soft_all_reset(); - - ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); - if (ret) { - dev_err(&pdev->dev, "irq request err\n"); - goto exit_free_dma; - } - - ret = snd_soc_register_platform(&fsi_soc_platform); - if (ret < 0) { - dev_err(&pdev->dev, "cannot snd soc register\n"); - goto exit_free_irq; - } - - return snd_soc_register_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); - -exit_free_irq: - free_irq(irq, master); -exit_free_dma: - fsi_free_dma_chan(); -exit_iounmap: - iounmap(master->base); -exit_kfree: - kfree(master); - master = NULL; -exit: - return ret; -} - -static int fsi_remove(struct platform_device *pdev) -{ - snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); - snd_soc_unregister_platform(&fsi_soc_platform); - - clk_put(master->clk); - - fsi_free_dma_chan(); - - free_irq(master->irq, master); - - iounmap(master->base); - kfree(master); - master = NULL; - return 0; -} - -static struct platform_driver fsi_driver = { - .driver = { - .name = "sh_fsi", - }, - .probe = fsi_probe, - .remove = fsi_remove, -}; - -static int __init fsi_mobile_init(void) -{ - return platform_driver_register(&fsi_driver); -} - -static void __exit fsi_mobile_exit(void) -{ - platform_driver_unregister(&fsi_driver); -} -module_init(fsi_mobile_init); -module_exit(fsi_mobile_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SuperH onchip FSI audio driver"); -MODULE_AUTHOR("Kuninori Morimoto "); diff --git a/trunk/sound/soc/soc-cache.c b/trunk/sound/soc/soc-cache.c deleted file mode 100644 index c8ceddc2a26c..000000000000 --- a/trunk/sound/soc/soc-cache.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * soc-cache.c -- ASoC register cache helpers - * - * Copyright 2009 Wolfson Microelectronics PLC. - * - * Author: Mark Brown - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include -#include -#include - -static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg >= codec->reg_cache_size) - return -1; - return cache[reg]; -} - -static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u16 *cache = codec->reg_cache; - u8 data[2]; - int ret; - - BUG_ON(codec->volatile_register); - - data[0] = (reg << 1) | ((value >> 8) & 0x0001); - data[1] = value & 0x00ff; - - if (reg < codec->reg_cache_size) - cache[reg] = value; - ret = codec->hw_write(codec->control_data, data, 2); - if (ret == 2) - return 0; - if (ret < 0) - return ret; - else - return -EIO; -} - -#if defined(CONFIG_SPI_MASTER) -static int snd_soc_7_9_spi_write(void *control_data, const char *data, - int len) -{ - struct spi_device *spi = control_data; - struct spi_transfer t; - struct spi_message m; - u8 msg[2]; - - if (len <= 0) - return 0; - - msg[0] = data[0]; - msg[1] = data[1]; - - spi_message_init(&m); - memset(&t, 0, (sizeof t)); - - t.tx_buf = &msg[0]; - t.len = len; - - spi_message_add_tail(&t, &m); - spi_sync(spi, &m); - - return len; -} -#else -#define snd_soc_7_9_spi_write NULL -#endif - -static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - u16 *reg_cache = codec->reg_cache; - u8 data[3]; - - data[0] = reg; - data[1] = (value >> 8) & 0xff; - data[2] = value & 0xff; - - if (!snd_soc_codec_volatile_register(codec, reg)) - reg_cache[reg] = value; - - if (codec->hw_write(codec->control_data, data, 3) == 3) - return 0; - else - return -EIO; -} - -static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, - unsigned int reg) -{ - u16 *cache = codec->reg_cache; - - if (reg >= codec->reg_cache_size || - snd_soc_codec_volatile_register(codec, reg)) - return codec->hw_read(codec, reg); - else - return cache[reg]; -} - -#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) -static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec, - unsigned int r) -{ - struct i2c_msg xfer[2]; - u8 reg = r; - u16 data; - int ret; - struct i2c_client *client = codec->control_data; - - /* Write register */ - xfer[0].addr = client->addr; - xfer[0].flags = 0; - xfer[0].len = 1; - xfer[0].buf = ® - - /* Read data */ - xfer[1].addr = client->addr; - xfer[1].flags = I2C_M_RD; - xfer[1].len = 2; - xfer[1].buf = (u8 *)&data; - - ret = i2c_transfer(client->adapter, xfer, 2); - if (ret != 2) { - dev_err(&client->dev, "i2c_transfer() returned %d\n", ret); - return 0; - } - - return (data >> 8) | ((data & 0xff) << 8); -} -#else -#define snd_soc_8_16_read_i2c NULL -#endif - -static struct { - int addr_bits; - int data_bits; - int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int); - int (*spi_write)(void *, const char *, int); - unsigned int (*read)(struct snd_soc_codec *, unsigned int); - unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); -} io_types[] = { - { 7, 9, snd_soc_7_9_write, snd_soc_7_9_spi_write, snd_soc_7_9_read }, - { 8, 16, snd_soc_8_16_write, NULL, snd_soc_8_16_read, - snd_soc_8_16_read_i2c }, -}; - -/** - * snd_soc_codec_set_cache_io: Set up standard I/O functions. - * - * @codec: CODEC to configure. - * @type: Type of cache. - * @addr_bits: Number of bits of register address data. - * @data_bits: Number of bits of data per register. - * @control: Control bus used. - * - * Register formats are frequently shared between many I2C and SPI - * devices. In order to promote code reuse the ASoC core provides - * some standard implementations of CODEC read and write operations - * which can be set up using this function. - * - * The caller is responsible for allocating and initialising the - * actual cache. - * - * Note that at present this code cannot be used by CODECs with - * volatile registers. - */ -int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec, - int addr_bits, int data_bits, - enum snd_soc_control_type control) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(io_types); i++) - if (io_types[i].addr_bits == addr_bits && - io_types[i].data_bits == data_bits) - break; - if (i == ARRAY_SIZE(io_types)) { - printk(KERN_ERR - "No I/O functions for %d bit address %d bit data\n", - addr_bits, data_bits); - return -EINVAL; - } - - codec->write = io_types[i].write; - codec->read = io_types[i].read; - - switch (control) { - case SND_SOC_CUSTOM: - break; - - case SND_SOC_I2C: -#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) - codec->hw_write = (hw_write_t)i2c_master_send; -#endif - if (io_types[i].i2c_read) - codec->hw_read = io_types[i].i2c_read; - break; - - case SND_SOC_SPI: - if (io_types[i].spi_write) - codec->hw_write = io_types[i].spi_write; - break; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); diff --git a/trunk/sound/soc/soc-core.c b/trunk/sound/soc/soc-core.c index 7ff04ad2a97e..1d70829464ef 100644 --- a/trunk/sound/soc/soc-core.c +++ b/trunk/sound/soc/soc-core.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -620,9 +619,8 @@ static struct snd_pcm_ops soc_pcm_ops = { #ifdef CONFIG_PM /* powers down audio subsystem for suspend */ -static int soc_suspend(struct device *dev) +static int soc_suspend(struct platform_device *pdev, pm_message_t state) { - struct platform_device *pdev = to_platform_device(dev); struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_card *card = socdev->card; struct snd_soc_platform *platform = card->platform; @@ -658,7 +656,7 @@ static int soc_suspend(struct device *dev) snd_pcm_suspend_all(card->dai_link[i].pcm); if (card->suspend_pre) - card->suspend_pre(pdev, PMSG_SUSPEND); + card->suspend_pre(pdev, state); for (i = 0; i < card->num_links; i++) { struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; @@ -684,7 +682,7 @@ static int soc_suspend(struct device *dev) } if (codec_dev->suspend) - codec_dev->suspend(pdev, PMSG_SUSPEND); + codec_dev->suspend(pdev, state); for (i = 0; i < card->num_links; i++) { struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; @@ -693,7 +691,7 @@ static int soc_suspend(struct device *dev) } if (card->suspend_post) - card->suspend_post(pdev, PMSG_SUSPEND); + card->suspend_post(pdev, state); return 0; } @@ -767,9 +765,8 @@ static void soc_resume_deferred(struct work_struct *work) } /* powers up audio subsystem after a suspend */ -static int soc_resume(struct device *dev) +static int soc_resume(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_card *card = socdev->card; struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai; @@ -791,44 +788,6 @@ static int soc_resume(struct device *dev) return 0; } -/** - * snd_soc_suspend_device: Notify core of device suspend - * - * @dev: Device being suspended. - * - * In order to ensure that the entire audio subsystem is suspended in a - * coordinated fashion ASoC devices should suspend themselves when - * called by ASoC. When the standard kernel suspend process asks the - * device to suspend it should call this function to initiate a suspend - * of the entire ASoC card. - * - * \note Currently this function is stubbed out. - */ -int snd_soc_suspend_device(struct device *dev) -{ - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_suspend_device); - -/** - * snd_soc_resume_device: Notify core of device resume - * - * @dev: Device being resumed. - * - * In order to ensure that the entire audio subsystem is resumed in a - * coordinated fashion ASoC devices should resume themselves when called - * by ASoC. When the standard kernel resume process asks the device - * to resume it should call this function. Once all the components of - * the card have notified that they are ready to be resumed the card - * will be resumed. - * - * \note Currently this function is stubbed out. - */ -int snd_soc_resume_device(struct device *dev) -{ - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_resume_device); #else #define soc_suspend NULL #define soc_resume NULL @@ -1022,39 +981,16 @@ static int soc_remove(struct platform_device *pdev) return 0; } -static int soc_poweroff(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct snd_soc_device *socdev = platform_get_drvdata(pdev); - struct snd_soc_card *card = socdev->card; - - if (!card->instantiated) - return 0; - - /* Flush out pmdown_time work - we actually do want to run it - * now, we're shutting down so no imminent restart. */ - run_delayed_work(&card->delayed_work); - - snd_soc_dapm_shutdown(socdev); - - return 0; -} - -static struct dev_pm_ops soc_pm_ops = { - .suspend = soc_suspend, - .resume = soc_resume, - .poweroff = soc_poweroff, -}; - /* ASoC platform driver */ static struct platform_driver soc_driver = { .driver = { .name = "soc-audio", .owner = THIS_MODULE, - .pm = &soc_pm_ops, }, .probe = soc_probe, .remove = soc_remove, + .suspend = soc_suspend, + .resume = soc_resume, }; /* create a new pcm */ @@ -1126,23 +1062,6 @@ static int soc_new_pcm(struct snd_soc_device *socdev, return ret; } -/** - * snd_soc_codec_volatile_register: Report if a register is volatile. - * - * @codec: CODEC to query. - * @reg: Register to query. - * - * Boolean function indiciating if a CODEC register is volatile. - */ -int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg) -{ - if (codec->volatile_register) - return codec->volatile_register(reg); - else - return 0; -} -EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); - /* codec register dump */ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) { @@ -1156,9 +1075,6 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) count += sprintf(buf, "%s registers\n", codec->name); for (i = 0; i < codec->reg_cache_size; i += step) { - if (codec->readable_register && !codec->readable_register(i)) - continue; - count += sprintf(buf + count, "%2x: ", i); if (count >= PAGE_SIZE - 1) break; @@ -1267,18 +1183,10 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) if (!codec->debugfs_pop_time) printk(KERN_WARNING "Failed to create pop time debugfs file\n"); - - codec->debugfs_dapm = debugfs_create_dir("dapm", debugfs_root); - if (!codec->debugfs_dapm) - printk(KERN_WARNING - "Failed to create DAPM debugfs directory\n"); - - snd_soc_dapm_debugfs_init(codec); } static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) { - debugfs_remove_recursive(codec->debugfs_dapm); debugfs_remove(codec->debugfs_pop_time); debugfs_remove(codec->debugfs_reg); } @@ -1356,10 +1264,10 @@ EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); * Returns 1 for change else 0. */ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg, - unsigned int mask, unsigned int value) + unsigned short mask, unsigned short value) { int change; - unsigned int old, new; + unsigned short old, new; mutex_lock(&io_mutex); old = snd_soc_read(codec, reg); @@ -1386,10 +1294,10 @@ EXPORT_SYMBOL_GPL(snd_soc_update_bits); * Returns 1 for change else 0. */ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg, - unsigned int mask, unsigned int value) + unsigned short mask, unsigned short value) { int change; - unsigned int old, new; + unsigned short old, new; mutex_lock(&io_mutex); old = snd_soc_read(codec, reg); @@ -1473,11 +1381,8 @@ int snd_soc_init_card(struct snd_soc_device *socdev) continue; } } - if (card->dai_link[i].codec_dai->ac97_control) { + if (card->dai_link[i].codec_dai->ac97_control) ac97 = 1; - snd_ac97_dev_add_pdata(codec->ac97, - card->dai_link[i].cpu_dai->ac97_pdata); - } } snprintf(codec->card->shortname, sizeof(codec->card->shortname), "%s", card->name); @@ -1681,7 +1586,7 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, bitmask; + unsigned short val, bitmask; for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; @@ -1710,8 +1615,8 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - unsigned int mask, bitmask; + unsigned short val; + unsigned short mask, bitmask; for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; @@ -1747,7 +1652,7 @@ int snd_soc_get_value_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; + unsigned short reg_val, val, mux; reg_val = snd_soc_read(codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; @@ -1786,8 +1691,8 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val; - unsigned int mask; + unsigned short val; + unsigned short mask; if (ucontrol->value.enumerated.item[0] > e->max - 1) return -EINVAL; @@ -1947,7 +1852,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - unsigned int val, val2, val_mask; + unsigned short val, val2, val_mask; val = (ucontrol->value.integer.value[0] & mask); if (invert) @@ -2013,7 +1918,7 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, unsigned int reg2 = mc->rreg; unsigned int shift = mc->shift; int max = mc->max; - unsigned int mask = (1 << fls(max)) - 1; + unsigned int mask = (1<invert; ucontrol->value.integer.value[0] = @@ -2053,7 +1958,7 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; int err; - unsigned int val, val2, val_mask; + unsigned short val, val2, val_mask; val_mask = mask << shift; val = (ucontrol->value.integer.value[0] & mask); @@ -2145,7 +2050,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); unsigned int reg = mc->reg; int min = mc->min; - unsigned int val; + unsigned short val; val = (ucontrol->value.integer.value[0]+min) & 0xff; val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; @@ -2231,20 +2136,17 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); /** * snd_soc_dai_set_tdm_slot - configure DAI TDM. * @dai: DAI - * @tx_mask: bitmask representing active TX slots. - * @rx_mask: bitmask representing active RX slots. + * @mask: DAI specific mask representing used slots. * @slots: Number of slots in use. - * @slot_width: Width in bits for each slot. * * Configures a DAI for TDM operation. Both mask and slots are codec and DAI * specific. */ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, - unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) + unsigned int mask, int slots) { if (dai->ops && dai->ops->set_tdm_slot) - return dai->ops->set_tdm_slot(dai, tx_mask, rx_mask, - slots, slot_width); + return dai->ops->set_tdm_slot(dai, mask, slots); else return -EINVAL; } diff --git a/trunk/sound/soc/soc-dapm.c b/trunk/sound/soc/soc-dapm.c index 0d8b08ef8731..21c69074aa17 100644 --- a/trunk/sound/soc/soc-dapm.c +++ b/trunk/sound/soc/soc-dapm.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -53,41 +52,19 @@ /* dapm power sequences - make this per codec in the future */ static int dapm_up_seq[] = { - [snd_soc_dapm_pre] = 0, - [snd_soc_dapm_supply] = 1, - [snd_soc_dapm_micbias] = 2, - [snd_soc_dapm_aif_in] = 3, - [snd_soc_dapm_aif_out] = 3, - [snd_soc_dapm_mic] = 4, - [snd_soc_dapm_mux] = 5, - [snd_soc_dapm_value_mux] = 5, - [snd_soc_dapm_dac] = 6, - [snd_soc_dapm_mixer] = 7, - [snd_soc_dapm_mixer_named_ctl] = 7, - [snd_soc_dapm_pga] = 8, - [snd_soc_dapm_adc] = 9, - [snd_soc_dapm_hp] = 10, - [snd_soc_dapm_spk] = 10, - [snd_soc_dapm_post] = 11, + snd_soc_dapm_pre, snd_soc_dapm_supply, snd_soc_dapm_micbias, + snd_soc_dapm_mic, snd_soc_dapm_mux, snd_soc_dapm_value_mux, + snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, + snd_soc_dapm_pga, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, + snd_soc_dapm_post }; static int dapm_down_seq[] = { - [snd_soc_dapm_pre] = 0, - [snd_soc_dapm_adc] = 1, - [snd_soc_dapm_hp] = 2, - [snd_soc_dapm_spk] = 2, - [snd_soc_dapm_pga] = 4, - [snd_soc_dapm_mixer_named_ctl] = 5, - [snd_soc_dapm_mixer] = 5, - [snd_soc_dapm_dac] = 6, - [snd_soc_dapm_mic] = 7, - [snd_soc_dapm_micbias] = 8, - [snd_soc_dapm_mux] = 9, - [snd_soc_dapm_value_mux] = 9, - [snd_soc_dapm_aif_in] = 10, - [snd_soc_dapm_aif_out] = 10, - [snd_soc_dapm_supply] = 11, - [snd_soc_dapm_post] = 12, + snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, + snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, + snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, + snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_supply, + snd_soc_dapm_post }; static void pop_wait(u32 pop_time) @@ -153,12 +130,8 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, if (card->set_bias_level) ret = card->set_bias_level(card, level); - if (ret == 0) { - if (codec->set_bias_level) - ret = codec->set_bias_level(codec, level); - else - codec->bias_level = level; - } + if (ret == 0 && codec->set_bias_level) + ret = codec->set_bias_level(codec, level); return ret; } @@ -233,8 +206,6 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, case snd_soc_dapm_micbias: case snd_soc_dapm_vmid: case snd_soc_dapm_supply: - case snd_soc_dapm_aif_in: - case snd_soc_dapm_aif_out: p->connect = 1; break; /* does effect routing - dynamically connected */ @@ -297,7 +268,7 @@ static int dapm_connect_mixer(struct snd_soc_codec *codec, static int dapm_update_bits(struct snd_soc_dapm_widget *widget) { int change, power; - unsigned int old, new; + unsigned short old, new; struct snd_soc_codec *codec = widget->codec; /* check for valid widgets */ @@ -508,14 +479,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget) if (widget->id == snd_soc_dapm_supply) return 0; - switch (widget->id) { - case snd_soc_dapm_adc: - case snd_soc_dapm_aif_out: - if (widget->active) - return 1; - default: - break; - } + if (widget->id == snd_soc_dapm_adc && widget->active) + return 1; if (widget->connected) { /* connected pin ? */ @@ -554,14 +519,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget) return 0; /* active stream ? */ - switch (widget->id) { - case snd_soc_dapm_dac: - case snd_soc_dapm_aif_in: - if (widget->active) - return 1; - default: - break; - } + if (widget->id == snd_soc_dapm_dac && widget->active) + return 1; if (widget->connected) { /* connected pin ? */ @@ -730,211 +689,53 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w) return power; } -static int dapm_seq_compare(struct snd_soc_dapm_widget *a, - struct snd_soc_dapm_widget *b, - int sort[]) -{ - if (sort[a->id] != sort[b->id]) - return sort[a->id] - sort[b->id]; - if (a->reg != b->reg) - return a->reg - b->reg; - - return 0; -} - -/* Insert a widget in order into a DAPM power sequence. */ -static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget, - struct list_head *list, - int sort[]) -{ - struct snd_soc_dapm_widget *w; - - list_for_each_entry(w, list, power_list) - if (dapm_seq_compare(new_widget, w, sort) < 0) { - list_add_tail(&new_widget->power_list, &w->power_list); - return; - } - - list_add_tail(&new_widget->power_list, list); -} - -/* Apply the coalesced changes from a DAPM sequence */ -static void dapm_seq_run_coalesced(struct snd_soc_codec *codec, - struct list_head *pending) +/* + * Scan a single DAPM widget for a complete audio path and update the + * power status appropriately. + */ +static int dapm_power_widget(struct snd_soc_codec *codec, int event, + struct snd_soc_dapm_widget *w) { - struct snd_soc_dapm_widget *w; - int reg, power, ret; - unsigned int value = 0; - unsigned int mask = 0; - unsigned int cur_mask; - - reg = list_first_entry(pending, struct snd_soc_dapm_widget, - power_list)->reg; + int ret; - list_for_each_entry(w, pending, power_list) { - cur_mask = 1 << w->shift; - BUG_ON(reg != w->reg); + switch (w->id) { + case snd_soc_dapm_pre: + if (!w->event) + return 0; - if (w->invert) - power = !w->power; - else - power = w->power; - - mask |= cur_mask; - if (power) - value |= cur_mask; - - pop_dbg(codec->pop_time, - "pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n", - w->name, reg, value, mask); - - /* power up pre event */ - if (w->power && w->event && - (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { - pop_dbg(codec->pop_time, "pop test : %s PRE_PMU\n", - w->name); - ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); + if (event == SND_SOC_DAPM_STREAM_START) { + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMU); if (ret < 0) - pr_err("%s: pre event failed: %d\n", - w->name, ret); - } - - /* power down pre event */ - if (!w->power && w->event && - (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { - pop_dbg(codec->pop_time, "pop test : %s PRE_PMD\n", - w->name); - ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); + return ret; + } else if (event == SND_SOC_DAPM_STREAM_STOP) { + ret = w->event(w, + NULL, SND_SOC_DAPM_PRE_PMD); if (ret < 0) - pr_err("%s: pre event failed: %d\n", - w->name, ret); + return ret; } + return 0; - /* Lower PGA volume to reduce pops */ - if (w->id == snd_soc_dapm_pga && !w->power) - dapm_set_pga(w, w->power); - } - - if (reg >= 0) { - pop_dbg(codec->pop_time, - "pop test : Applying 0x%x/0x%x to %x in %dms\n", - value, mask, reg, codec->pop_time); - pop_wait(codec->pop_time); - snd_soc_update_bits(codec, reg, mask, value); - } - - list_for_each_entry(w, pending, power_list) { - /* Raise PGA volume to reduce pops */ - if (w->id == snd_soc_dapm_pga && w->power) - dapm_set_pga(w, w->power); + case snd_soc_dapm_post: + if (!w->event) + return 0; - /* power up post event */ - if (w->power && w->event && - (w->event_flags & SND_SOC_DAPM_POST_PMU)) { - pop_dbg(codec->pop_time, "pop test : %s POST_PMU\n", - w->name); + if (event == SND_SOC_DAPM_STREAM_START) { ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMU); if (ret < 0) - pr_err("%s: post event failed: %d\n", - w->name, ret); - } - - /* power down post event */ - if (!w->power && w->event && - (w->event_flags & SND_SOC_DAPM_POST_PMD)) { - pop_dbg(codec->pop_time, "pop test : %s POST_PMD\n", - w->name); - ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); + return ret; + } else if (event == SND_SOC_DAPM_STREAM_STOP) { + ret = w->event(w, + NULL, SND_SOC_DAPM_POST_PMD); if (ret < 0) - pr_err("%s: post event failed: %d\n", - w->name, ret); - } - } -} - -/* Apply a DAPM power sequence. - * - * We walk over a pre-sorted list of widgets to apply power to. In - * order to minimise the number of writes to the device required - * multiple widgets will be updated in a single write where possible. - * Currently anything that requires more than a single write is not - * handled. - */ -static void dapm_seq_run(struct snd_soc_codec *codec, struct list_head *list, - int event, int sort[]) -{ - struct snd_soc_dapm_widget *w, *n; - LIST_HEAD(pending); - int cur_sort = -1; - int cur_reg = SND_SOC_NOPM; - int ret; - - list_for_each_entry_safe(w, n, list, power_list) { - ret = 0; - - /* Do we need to apply any queued changes? */ - if (sort[w->id] != cur_sort || w->reg != cur_reg) { - if (!list_empty(&pending)) - dapm_seq_run_coalesced(codec, &pending); - - INIT_LIST_HEAD(&pending); - cur_sort = -1; - cur_reg = SND_SOC_NOPM; - } - - switch (w->id) { - case snd_soc_dapm_pre: - if (!w->event) - list_for_each_entry_safe_continue(w, n, list, - power_list); - - if (event == SND_SOC_DAPM_STREAM_START) - ret = w->event(w, - NULL, SND_SOC_DAPM_PRE_PMU); - else if (event == SND_SOC_DAPM_STREAM_STOP) - ret = w->event(w, - NULL, SND_SOC_DAPM_PRE_PMD); - break; - - case snd_soc_dapm_post: - if (!w->event) - list_for_each_entry_safe_continue(w, n, list, - power_list); - - if (event == SND_SOC_DAPM_STREAM_START) - ret = w->event(w, - NULL, SND_SOC_DAPM_POST_PMU); - else if (event == SND_SOC_DAPM_STREAM_STOP) - ret = w->event(w, - NULL, SND_SOC_DAPM_POST_PMD); - break; - - case snd_soc_dapm_input: - case snd_soc_dapm_output: - case snd_soc_dapm_hp: - case snd_soc_dapm_mic: - case snd_soc_dapm_line: - case snd_soc_dapm_spk: - /* No register support currently */ - ret = dapm_generic_apply_power(w); - break; - - default: - /* Queue it up for application */ - cur_sort = sort[w->id]; - cur_reg = w->reg; - list_move(&w->power_list, &pending); - break; + return ret; } + return 0; - if (ret < 0) - pr_err("Failed to apply widget power: %d\n", - ret); + default: + return dapm_generic_apply_power(w); } - - if (!list_empty(&pending)) - dapm_seq_run_coalesced(codec, &pending); } /* @@ -950,22 +751,23 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) { struct snd_soc_device *socdev = codec->socdev; struct snd_soc_dapm_widget *w; - LIST_HEAD(up_list); - LIST_HEAD(down_list); int ret = 0; - int power; + int i, power; int sys_power = 0; + INIT_LIST_HEAD(&codec->up_list); + INIT_LIST_HEAD(&codec->down_list); + /* Check which widgets we need to power and store them in * lists indicating if they should be powered up or down. */ list_for_each_entry(w, &codec->dapm_widgets, list) { switch (w->id) { case snd_soc_dapm_pre: - dapm_seq_insert(w, &down_list, dapm_down_seq); + list_add_tail(&codec->down_list, &w->power_list); break; case snd_soc_dapm_post: - dapm_seq_insert(w, &up_list, dapm_up_seq); + list_add_tail(&codec->up_list, &w->power_list); break; default: @@ -980,31 +782,16 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) continue; if (power) - dapm_seq_insert(w, &up_list, dapm_up_seq); + list_add_tail(&w->power_list, &codec->up_list); else - dapm_seq_insert(w, &down_list, dapm_down_seq); + list_add_tail(&w->power_list, + &codec->down_list); w->power = power; break; } } - /* If there are no DAPM widgets then try to figure out power from the - * event type. - */ - if (list_empty(&codec->dapm_widgets)) { - switch (event) { - case SND_SOC_DAPM_STREAM_START: - case SND_SOC_DAPM_STREAM_RESUME: - sys_power = 1; - break; - case SND_SOC_DAPM_STREAM_NOP: - sys_power = codec->bias_level != SND_SOC_BIAS_STANDBY; - default: - break; - } - } - /* If we're changing to all on or all off then prepare */ if ((sys_power && codec->bias_level == SND_SOC_BIAS_STANDBY) || (!sys_power && codec->bias_level == SND_SOC_BIAS_ON)) { @@ -1015,10 +802,32 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) } /* Power down widgets first; try to avoid amplifying pops. */ - dapm_seq_run(codec, &down_list, event, dapm_down_seq); + for (i = 0; i < ARRAY_SIZE(dapm_down_seq); i++) { + list_for_each_entry(w, &codec->down_list, power_list) { + /* is widget in stream order */ + if (w->id != dapm_down_seq[i]) + continue; + + ret = dapm_power_widget(codec, event, w); + if (ret != 0) + pr_err("Failed to power down %s: %d\n", + w->name, ret); + } + } /* Now power up. */ - dapm_seq_run(codec, &up_list, event, dapm_up_seq); + for (i = 0; i < ARRAY_SIZE(dapm_up_seq); i++) { + list_for_each_entry(w, &codec->up_list, power_list) { + /* is widget in stream order */ + if (w->id != dapm_up_seq[i]) + continue; + + ret = dapm_power_widget(codec, event, w); + if (ret != 0) + pr_err("Failed to power up %s: %d\n", + w->name, ret); + } + } /* If we just powered the last thing off drop to standby bias */ if (codec->bias_level == SND_SOC_BIAS_PREPARE && !sys_power) { @@ -1036,9 +845,6 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event) pr_err("Failed to apply active bias: %d\n", ret); } - pop_dbg(codec->pop_time, "DAPM sequencing finished, waiting %dms\n", - codec->pop_time); - return 0; } @@ -1075,8 +881,6 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) case snd_soc_dapm_mixer: case snd_soc_dapm_mixer_named_ctl: case snd_soc_dapm_supply: - case snd_soc_dapm_aif_in: - case snd_soc_dapm_aif_out: if (w->name) { in = is_connected_input_ep(w); dapm_clear_walk(w->codec); @@ -1102,92 +906,6 @@ static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) } #endif -#ifdef CONFIG_DEBUG_FS -static int dapm_widget_power_open_file(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t dapm_widget_power_read_file(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct snd_soc_dapm_widget *w = file->private_data; - char *buf; - int in, out; - ssize_t ret; - struct snd_soc_dapm_path *p = NULL; - - buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - in = is_connected_input_ep(w); - dapm_clear_walk(w->codec); - out = is_connected_output_ep(w); - dapm_clear_walk(w->codec); - - ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d\n", - w->name, w->power ? "On" : "Off", in, out); - - if (w->active && w->sname) - ret += snprintf(buf, PAGE_SIZE - ret, " stream %s active\n", - w->sname); - - list_for_each_entry(p, &w->sources, list_sink) { - if (p->connect) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - " in %s %s\n", - p->name ? p->name : "static", - p->source->name); - } - list_for_each_entry(p, &w->sinks, list_source) { - if (p->connect) - ret += snprintf(buf + ret, PAGE_SIZE - ret, - " out %s %s\n", - p->name ? p->name : "static", - p->sink->name); - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); - - kfree(buf); - return ret; -} - -static const struct file_operations dapm_widget_power_fops = { - .open = dapm_widget_power_open_file, - .read = dapm_widget_power_read_file, -}; - -void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec) -{ - struct snd_soc_dapm_widget *w; - struct dentry *d; - - if (!codec->debugfs_dapm) - return; - - list_for_each_entry(w, &codec->dapm_widgets, list) { - if (!w->name) - continue; - - d = debugfs_create_file(w->name, 0444, - codec->debugfs_dapm, w, - &dapm_widget_power_fops); - if (!d) - printk(KERN_WARNING - "ASoC: Failed to create %s debugfs file\n", - w->name); - } -} -#else -void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec) -{ -} -#endif - /* test and update the power status of a mux widget */ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, struct snd_kcontrol *kcontrol, int mask, @@ -1420,8 +1138,8 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, if (wsink->id == snd_soc_dapm_input) { if (wsource->id == snd_soc_dapm_micbias || wsource->id == snd_soc_dapm_mic || - wsource->id == snd_soc_dapm_line || - wsource->id == snd_soc_dapm_output) + wsink->id == snd_soc_dapm_line || + wsink->id == snd_soc_dapm_output) wsink->ext = 1; } if (wsource->id == snd_soc_dapm_output) { @@ -1453,8 +1171,6 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, case snd_soc_dapm_pre: case snd_soc_dapm_post: case snd_soc_dapm_supply: - case snd_soc_dapm_aif_in: - case snd_soc_dapm_aif_out: list_add(&path->list, &codec->dapm_paths); list_add(&path->list_sink, &wsink->sources); list_add(&path->list_source, &wsource->sinks); @@ -1557,11 +1273,9 @@ int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) dapm_new_mux(codec, w); break; case snd_soc_dapm_adc: - case snd_soc_dapm_aif_out: w->power_check = dapm_adc_check_power; break; case snd_soc_dapm_dac: - case snd_soc_dapm_aif_in: w->power_check = dapm_dac_check_power; break; case snd_soc_dapm_pga: @@ -1658,7 +1372,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, int max = mc->max; unsigned int mask = (1 << fls(max)) - 1; unsigned int invert = mc->invert; - unsigned int val, val2, val_mask; + unsigned short val, val2, val_mask; int ret; val = (ucontrol->value.integer.value[0] & mask); @@ -1722,7 +1436,7 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, bitmask; + unsigned short val, bitmask; for (bitmask = 1; bitmask < e->max; bitmask <<= 1) ; @@ -1750,8 +1464,8 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux; - unsigned int mask, bitmask; + unsigned short val, mux; + unsigned short mask, bitmask; int ret = 0; for (bitmask = 1; bitmask < e->max; bitmask <<= 1) @@ -1809,7 +1523,7 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int reg_val, val, mux; + unsigned short reg_val, val, mux; reg_val = snd_soc_read(widget->codec, e->reg); val = (reg_val >> e->shift_l) & e->mask; @@ -1849,8 +1563,8 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, { struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - unsigned int val, mux; - unsigned int mask; + unsigned short val, mux; + unsigned short mask; int ret = 0; if (ucontrol->value.enumerated.item[0] > e->max - 1) @@ -2166,36 +1880,6 @@ void snd_soc_dapm_free(struct snd_soc_device *socdev) } EXPORT_SYMBOL_GPL(snd_soc_dapm_free); -/* - * snd_soc_dapm_shutdown - callback for system shutdown - */ -void snd_soc_dapm_shutdown(struct snd_soc_device *socdev) -{ - struct snd_soc_codec *codec = socdev->card->codec; - struct snd_soc_dapm_widget *w; - LIST_HEAD(down_list); - int powerdown = 0; - - list_for_each_entry(w, &codec->dapm_widgets, list) { - if (w->power) { - dapm_seq_insert(w, &down_list, dapm_down_seq); - w->power = 0; - powerdown = 1; - } - } - - /* If there were no widgets to power down we're already in - * standby. - */ - if (powerdown) { - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_PREPARE); - dapm_seq_run(codec, &down_list, 0, dapm_down_seq); - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_STANDBY); - } - - snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_OFF); -} - /* Module information */ MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); diff --git a/trunk/sound/soc/soc-jack.c b/trunk/sound/soc/soc-jack.c index 1d455ab79490..28346fb2e70c 100644 --- a/trunk/sound/soc/soc-jack.c +++ b/trunk/sound/soc/soc-jack.c @@ -73,15 +73,14 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) oldstatus = jack->status; jack->status &= ~mask; - jack->status |= status & mask; + jack->status |= status; - /* The DAPM sync is expensive enough to be worth skipping. - * However, empty mask means pin synchronization is desired. */ - if (mask && (jack->status == oldstatus)) + /* The DAPM sync is expensive enough to be worth skipping */ + if (jack->status == oldstatus) goto out; list_for_each_entry(pin, &jack->pins, list) { - enable = pin->mask & jack->status; + enable = pin->mask & status; if (pin->invert) enable = !enable; @@ -221,9 +220,6 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, if (ret) goto err; - INIT_WORK(&gpios[i].work, gpio_work); - gpios[i].jack = jack; - ret = request_irq(gpio_to_irq(gpios[i].gpio), gpio_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, @@ -232,13 +228,8 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, if (ret) goto err; -#ifdef CONFIG_GPIO_SYSFS - /* Expose GPIO value over sysfs for diagnostic purposes */ - gpio_export(gpios[i].gpio, false); -#endif - - /* Update initial jack status */ - snd_soc_jack_gpio_detect(&gpios[i]); + INIT_WORK(&gpios[i].work, gpio_work); + gpios[i].jack = jack; } return 0; @@ -267,9 +258,6 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, int i; for (i = 0; i < count; i++) { -#ifdef CONFIG_GPIO_SYSFS - gpio_unexport(gpios[i].gpio); -#endif free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]); gpio_free(gpios[i].gpio); gpios[i].jack = NULL; diff --git a/trunk/sound/soc/txx9/txx9aclc.c b/trunk/sound/soc/txx9/txx9aclc.c index efed64b8b026..938a58a5a244 100644 --- a/trunk/sound/soc/txx9/txx9aclc.c +++ b/trunk/sound/soc/txx9/txx9aclc.c @@ -297,17 +297,15 @@ static int txx9aclc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, static bool filter(struct dma_chan *chan, void *param) { struct txx9aclc_dmadata *dmadata = param; - char *devname; - bool found = false; + char devname[20 + 2]; /* FIXME: old BUS_ID_SIZE + 2 */ - devname = kasprintf(GFP_KERNEL, "%s.%d", dmadata->dma_res->name, + snprintf(devname, sizeof(devname), "%s.%d", dmadata->dma_res->name, (int)dmadata->dma_res->start); if (strcmp(dev_name(chan->device->dev), devname) == 0) { chan->private = &dmadata->dma_slave; - found = true; + return true; } - kfree(devname); - return found; + return false; } static int txx9aclc_dma_init(struct txx9aclc_soc_device *dev,